diff options
Diffstat (limited to 'src/namestore')
53 files changed, 0 insertions, 22669 deletions
diff --git a/src/namestore/.gitignore b/src/namestore/.gitignore deleted file mode 100644 index 2265f9815..000000000 --- a/src/namestore/.gitignore +++ /dev/null | |||
@@ -1,61 +0,0 @@ | |||
1 | gnunet-service-namestore | ||
2 | gnunet-namestore | ||
3 | gnunet-namestore-dbtool | ||
4 | gnunet-namestore-zonefile | ||
5 | gnunet-namestore-fcfsd | ||
6 | test_namestore_api_lookup_nick.nc | ||
7 | test_namestore_api_lookup_private.nc | ||
8 | test_namestore_api_lookup_public.nc | ||
9 | test_namestore_api_lookup_shadow.nc | ||
10 | test_namestore_api_lookup_shadow_filter.nc | ||
11 | test_namestore_api_monitoring.nc | ||
12 | test_namestore_api_monitoring_existing.nc | ||
13 | test_namestore_api_remove.nc | ||
14 | test_namestore_api_remove_not_existing_record.nc | ||
15 | test_namestore_api_store.nc | ||
16 | test_namestore_api_store_update.nc | ||
17 | test_namestore_api_zone_iteration.nc | ||
18 | test_namestore_api_zone_iteration_nick.nc | ||
19 | test_namestore_api_zone_iteration_specific_zone.nc | ||
20 | test_namestore_api_zone_iteration_stop.nc | ||
21 | test_plugin_namestore_postgres | ||
22 | test_plugin_namestore_sqlite | ||
23 | gnunet-zoneimport | ||
24 | test_namestore_api_lookup_nick_postgres | ||
25 | test_namestore_api_lookup_nick_sqlite | ||
26 | test_namestore_api_lookup_private_postgres | ||
27 | test_namestore_api_lookup_private_sqlite | ||
28 | test_namestore_api_lookup_public_postgres | ||
29 | test_namestore_api_lookup_public_sqlite | ||
30 | test_namestore_api_lookup_shadow_filter_postgres | ||
31 | test_namestore_api_lookup_shadow_filter_sqlite | ||
32 | test_namestore_api_lookup_shadow_postgres | ||
33 | test_namestore_api_lookup_shadow_sqlite | ||
34 | test_namestore_api_monitoring_existing_postgres | ||
35 | test_namestore_api_monitoring_existing_sqlite | ||
36 | test_namestore_api_monitoring_postgres | ||
37 | test_namestore_api_monitoring_sqlite | ||
38 | test_namestore_api_remove_not_existing_record_postgres | ||
39 | test_namestore_api_remove_not_existing_record_sqlite | ||
40 | test_namestore_api_remove_postgres | ||
41 | test_namestore_api_remove_sqlite | ||
42 | test_namestore_api_store_postgres | ||
43 | test_namestore_api_store_sqlite | ||
44 | test_namestore_api_store_update_postgres | ||
45 | test_namestore_api_store_update_sqlite | ||
46 | test_namestore_api_zone_iteration_nick_postgres | ||
47 | test_namestore_api_zone_iteration_nick_sqlite | ||
48 | test_namestore_api_zone_iteration_postgres | ||
49 | test_namestore_api_zone_iteration_specific_zone_postgres | ||
50 | test_namestore_api_zone_iteration_specific_zone_sqlite | ||
51 | test_namestore_api_zone_iteration_sqlite | ||
52 | test_namestore_api_zone_iteration_stop_postgres | ||
53 | test_namestore_api_zone_iteration_stop_sqlite | ||
54 | test_namestore_api_zone_to_name_postgres | ||
55 | test_namestore_api_zone_to_name_sqlite | ||
56 | test_namestore_api_tx_rollback_postgres | ||
57 | test_namestore_api_tx_rollback_sqlite | ||
58 | test_namestore_api_edit_records_postgres | ||
59 | perf_namestore_api_import_sqlite | ||
60 | perf_namestore_api_import_postgres | ||
61 | test_namestore_api_store_locking_sqlite | ||
diff --git a/src/namestore/Makefile.am b/src/namestore/Makefile.am deleted file mode 100644 index 685829cc2..000000000 --- a/src/namestore/Makefile.am +++ /dev/null | |||
@@ -1,543 +0,0 @@ | |||
1 | # This Makefile.am is in the public domain | ||
2 | AM_CPPFLAGS = -I$(top_srcdir)/src/include $(POSTGRESQL_CPPFLAGS) | ||
3 | |||
4 | plugindir = $(libdir)/gnunet | ||
5 | |||
6 | pkgcfgdir= $(pkgdatadir)/config.d/ | ||
7 | |||
8 | libexecdir= $(pkglibdir)/libexec/ | ||
9 | |||
10 | sqldir = $(prefix)/share/gnunet/sql/ | ||
11 | |||
12 | sql_DATA = \ | ||
13 | namestore-0001.sql \ | ||
14 | namestore-drop.sql | ||
15 | |||
16 | pkgcfg_DATA = \ | ||
17 | namestore.conf | ||
18 | |||
19 | if USE_COVERAGE | ||
20 | AM_CFLAGS = --coverage -O0 | ||
21 | XLIBS = -lgcov | ||
22 | endif | ||
23 | |||
24 | |||
25 | if HAVE_SQLITE | ||
26 | SQLITE_PLUGIN = libgnunet_plugin_namestore_sqlite.la | ||
27 | SQLITE_TESTS = test_plugin_namestore_sqlite \ | ||
28 | test_namestore_api_store_sqlite \ | ||
29 | test_namestore_api_store_update_sqlite \ | ||
30 | test_namestore_api_zone_iteration_sqlite \ | ||
31 | test_namestore_api_remove_sqlite \ | ||
32 | test_namestore_api_lookup_nick_sqlite \ | ||
33 | test_namestore_api_monitoring_sqlite \ | ||
34 | test_namestore_api_remove_not_existing_record_sqlite \ | ||
35 | test_namestore_api_zone_iteration_nick_sqlite \ | ||
36 | test_namestore_api_zone_iteration_specific_zone_sqlite \ | ||
37 | test_namestore_api_zone_iteration_stop_sqlite \ | ||
38 | test_namestore_api_monitoring_existing_sqlite \ | ||
39 | test_namestore_api_zone_to_name_sqlite \ | ||
40 | perf_namestore_api_zone_iteration_sqlite \ | ||
41 | perf_namestore_api_import_sqlite \ | ||
42 | perf_namestore_api_import_postgres \ | ||
43 | test_namestore_api_tx_rollback_sqlite | ||
44 | endif | ||
45 | |||
46 | |||
47 | if HAVE_POSTGRESQL | ||
48 | POSTGRES_PLUGIN = libgnunet_plugin_namestore_postgres.la | ||
49 | POSTGRES_TESTS = test_plugin_namestore_postgres \ | ||
50 | test_namestore_api_store_postgres \ | ||
51 | test_namestore_api_store_update_postgres \ | ||
52 | test_namestore_api_remove_postgres \ | ||
53 | test_namestore_api_zone_iteration_postgres \ | ||
54 | test_namestore_api_lookup_nick_postgres \ | ||
55 | test_namestore_api_monitoring_postgres \ | ||
56 | test_namestore_api_remove_not_existing_record_postgres \ | ||
57 | test_namestore_api_zone_iteration_nick_postgres \ | ||
58 | test_namestore_api_zone_iteration_specific_zone_postgres \ | ||
59 | test_namestore_api_zone_iteration_stop_postgres \ | ||
60 | test_namestore_api_monitoring_existing_postgres \ | ||
61 | test_namestore_api_zone_to_name_postgres \ | ||
62 | perf_namestore_api_zone_iteration_postgres \ | ||
63 | test_namestore_api_tx_rollback_postgres | ||
64 | if HAVE_EXPERIMENTAL | ||
65 | POSTGRES_TESTS += test_namestore_api_edit_records_postgres | ||
66 | endif | ||
67 | endif | ||
68 | |||
69 | if HAVE_SQLITE | ||
70 | check_PROGRAMS = \ | ||
71 | $(SQLITE_TESTS) \ | ||
72 | $(POSTGRES_TESTS) | ||
73 | endif | ||
74 | |||
75 | if ENABLE_TEST_RUN | ||
76 | AM_TESTS_ENVIRONMENT=export GNUNET_PREFIX=$${GNUNET_PREFIX:-@libdir@};export PATH=$${GNUNET_PREFIX:-@prefix@}/bin:$$PATH;unset XDG_DATA_HOME;unset XDG_CONFIG_HOME; | ||
77 | TESTS = \ | ||
78 | $(check_PROGRAMS) \ | ||
79 | $(check_SCRIPTS) | ||
80 | endif | ||
81 | |||
82 | REST_PLUGIN = libgnunet_plugin_rest_namestore.la | ||
83 | |||
84 | lib_LTLIBRARIES = \ | ||
85 | libgnunetnamestore.la | ||
86 | |||
87 | |||
88 | libexec_PROGRAMS = \ | ||
89 | gnunet-service-namestore | ||
90 | |||
91 | bin_PROGRAMS = \ | ||
92 | gnunet-namestore \ | ||
93 | gnunet-namestore-dbtool \ | ||
94 | gnunet-namestore-zonefile \ | ||
95 | gnunet-zoneimport | ||
96 | |||
97 | libexec_PROGRAMS += \ | ||
98 | gnunet-namestore-fcfsd | ||
99 | |||
100 | |||
101 | plugin_LTLIBRARIES = \ | ||
102 | $(SQLITE_PLUGIN) \ | ||
103 | $(POSTGRES_PLUGIN) \ | ||
104 | $(REST_PLUGIN) | ||
105 | |||
106 | |||
107 | libgnunet_plugin_rest_namestore_la_SOURCES = \ | ||
108 | plugin_rest_namestore.c | ||
109 | libgnunet_plugin_rest_namestore_la_LIBADD = \ | ||
110 | libgnunetnamestore.la \ | ||
111 | $(top_builddir)/src/service/rest/libgnunetrest.la \ | ||
112 | $(top_builddir)/src/service/identity/libgnunetidentity.la \ | ||
113 | $(top_builddir)/src/lib/json/libgnunetjson.la \ | ||
114 | $(top_builddir)/src/lib/gnsrecord/libgnunetgnsrecord.la \ | ||
115 | $(top_builddir)/src/lib/gnsrecord/libgnunetgnsrecordjson.la \ | ||
116 | $(top_builddir)/src/lib/util/libgnunetutil.la $(XLIBS) \ | ||
117 | $(LTLIBINTL) -ljansson $(MHD_LIBS) | ||
118 | libgnunet_plugin_rest_namestore_la_LDFLAGS = \ | ||
119 | $(GN_PLUGIN_LDFLAGS) | ||
120 | libgnunet_plugin_rest_namestore_la_CFLAGS = $(MHD_CFLAGS) $(AM_CFLAGS) | ||
121 | |||
122 | |||
123 | libgnunetnamestore_la_SOURCES = \ | ||
124 | namestore_api.c \ | ||
125 | namestore_api_monitor.c \ | ||
126 | namestore.h | ||
127 | libgnunetnamestore_la_LIBADD = \ | ||
128 | $(top_builddir)/src/lib/gnsrecord/libgnunetgnsrecord.la \ | ||
129 | $(top_builddir)/src/service/identity/libgnunetidentity.la \ | ||
130 | $(top_builddir)/src/service/statistics/libgnunetstatistics.la \ | ||
131 | $(top_builddir)/src/lib/util/libgnunetutil.la \ | ||
132 | $(GN_LIBINTL) | ||
133 | libgnunetnamestore_la_LDFLAGS = \ | ||
134 | $(GN_LIB_LDFLAGS) \ | ||
135 | -version-info 0:1:0 | ||
136 | |||
137 | gnunet_namestore_zonefile_SOURCES = \ | ||
138 | gnunet-namestore-zonefile.c | ||
139 | gnunet_namestore_zonefile_LDADD = \ | ||
140 | libgnunetnamestore.la \ | ||
141 | $(top_builddir)/src/service/identity/libgnunetidentity.la \ | ||
142 | $(top_builddir)/src/lib/gnsrecord/libgnunetgnsrecord.la \ | ||
143 | $(top_builddir)/src/lib/util/libgnunetutil.la \ | ||
144 | $(GN_LIBINTL) | ||
145 | |||
146 | gnunet_zoneimport_SOURCES = \ | ||
147 | gnunet-zoneimport.c | ||
148 | gnunet_zoneimport_LDADD = \ | ||
149 | libgnunetnamestore.la \ | ||
150 | $(top_builddir)/src/service/statistics/libgnunetstatistics.la \ | ||
151 | $(top_builddir)/src/service/identity/libgnunetidentity.la \ | ||
152 | $(top_builddir)/src/lib/gnsrecord/libgnunetgnsrecord.la \ | ||
153 | $(top_builddir)/src/lib/util/libgnunetutil.la \ | ||
154 | $(GN_LIBINTL) | ||
155 | |||
156 | gnunet_namestore_SOURCES = \ | ||
157 | gnunet-namestore.c | ||
158 | gnunet_namestore_LDADD = \ | ||
159 | $(top_builddir)/src/service/identity/libgnunetidentity.la \ | ||
160 | $(top_builddir)/src/lib/gnsrecord/libgnunetgnsrecord.la \ | ||
161 | $(top_builddir)/src/lib/util/libgnunetutil.la \ | ||
162 | libgnunetnamestore.la \ | ||
163 | $(GN_LIBINTL) | ||
164 | |||
165 | gnunet_namestore_dbtool_SOURCES = \ | ||
166 | gnunet-namestore-dbtool.c | ||
167 | gnunet_namestore_dbtool_LDADD = \ | ||
168 | $(top_builddir)/src/lib/util/libgnunetutil.la \ | ||
169 | libgnunetnamestore.la \ | ||
170 | $(GN_LIBINTL) | ||
171 | |||
172 | |||
173 | |||
174 | gnunet_namestore_fcfsd_SOURCES = \ | ||
175 | gnunet-namestore-fcfsd.c | ||
176 | gnunet_namestore_fcfsd_LDADD = $(MHD_LIBS) \ | ||
177 | $(top_builddir)/src/lib/gnsrecord/libgnunetgnsrecord.la \ | ||
178 | $(top_builddir)/src/service/identity/libgnunetidentity.la \ | ||
179 | libgnunetnamestore.la \ | ||
180 | $(top_builddir)/src/lib/util/libgnunetutil.la \ | ||
181 | $(top_builddir)/src/lib/json/libgnunetjson.la \ | ||
182 | $(GN_LIBINTL) -ljansson | ||
183 | gnunet_namestore_fcfsd_CFLAGS = $(MHD_CFLAGS) $(AM_CFLAGS) | ||
184 | |||
185 | |||
186 | gnunet_service_namestore_SOURCES = \ | ||
187 | gnunet-service-namestore.c | ||
188 | gnunet_service_namestore_LDADD = \ | ||
189 | $(top_builddir)/src/service/namecache/libgnunetnamecache.la \ | ||
190 | $(top_builddir)/src/lib/gnsrecord/libgnunetgnsrecord.la \ | ||
191 | $(top_builddir)/src/service/identity/libgnunetidentity.la \ | ||
192 | $(top_builddir)/src/service/statistics/libgnunetstatistics.la \ | ||
193 | $(top_builddir)/src/lib/util/libgnunetutil.la \ | ||
194 | libgnunetnamestore.la \ | ||
195 | $(GN_LIBINTL) | ||
196 | |||
197 | |||
198 | |||
199 | libgnunet_plugin_namestore_sqlite_la_SOURCES = \ | ||
200 | plugin_namestore_sqlite.c | ||
201 | libgnunet_plugin_namestore_sqlite_la_LIBADD = \ | ||
202 | $(top_builddir)/src/lib/gnsrecord/libgnunetgnsrecord.la \ | ||
203 | $(top_builddir)/src/service/identity/libgnunetidentity.la \ | ||
204 | $(top_builddir)/src/lib/sq/libgnunetsq.la \ | ||
205 | $(top_builddir)/src/service/statistics/libgnunetstatistics.la \ | ||
206 | $(top_builddir)/src/lib/util/libgnunetutil.la $(XLIBS) -lsqlite3 \ | ||
207 | $(LTLIBINTL) | ||
208 | libgnunet_plugin_namestore_sqlite_la_LDFLAGS = \ | ||
209 | $(GN_PLUGIN_LDFLAGS) | ||
210 | |||
211 | libgnunet_plugin_namestore_postgres_la_SOURCES = \ | ||
212 | plugin_namestore_postgres.c | ||
213 | libgnunet_plugin_namestore_postgres_la_LIBADD = \ | ||
214 | $(top_builddir)/src/lib/gnsrecord/libgnunetgnsrecord.la \ | ||
215 | $(top_builddir)/src/service/identity/libgnunetidentity.la \ | ||
216 | $(top_builddir)/src/lib/pq/libgnunetpq.la \ | ||
217 | $(top_builddir)/src/service/statistics/libgnunetstatistics.la \ | ||
218 | $(top_builddir)/src/lib/util/libgnunetutil.la $(XLIBS) -lpq \ | ||
219 | $(LTLIBINTL) | ||
220 | libgnunet_plugin_namestore_postgres_la_LDFLAGS = \ | ||
221 | $(GN_PLUGIN_LDFLAGS) $(POSTGRESQL_LDFLAGS) | ||
222 | |||
223 | test_namestore_api_store_sqlite_SOURCES = \ | ||
224 | test_namestore_api_store.c | ||
225 | test_namestore_api_store_sqlite_LDADD = \ | ||
226 | $(top_builddir)/src/service/testing/libgnunettesting.la \ | ||
227 | $(top_builddir)/src/lib/util/libgnunetutil.la \ | ||
228 | $(top_builddir)/src/lib/gnsrecord/libgnunetgnsrecord.la \ | ||
229 | $(top_builddir)/src/service/identity/libgnunetidentity.la \ | ||
230 | libgnunetnamestore.la | ||
231 | |||
232 | test_namestore_api_store_postgres_SOURCES = \ | ||
233 | test_namestore_api_store.c | ||
234 | test_namestore_api_store_postgres_LDADD = \ | ||
235 | $(top_builddir)/src/service/testing/libgnunettesting.la \ | ||
236 | $(top_builddir)/src/lib/util/libgnunetutil.la \ | ||
237 | $(top_builddir)/src/lib/gnsrecord/libgnunetgnsrecord.la \ | ||
238 | $(top_builddir)/src/service/identity/libgnunetidentity.la \ | ||
239 | libgnunetnamestore.la | ||
240 | |||
241 | test_namestore_api_store_update_sqlite_SOURCES = \ | ||
242 | test_namestore_api_store_update.c | ||
243 | test_namestore_api_store_update_sqlite_LDADD = \ | ||
244 | $(top_builddir)/src/service/testing/libgnunettesting.la \ | ||
245 | $(top_builddir)/src/lib/util/libgnunetutil.la \ | ||
246 | $(top_builddir)/src/service/identity/libgnunetidentity.la \ | ||
247 | $(top_builddir)/src/lib/gnsrecord/libgnunetgnsrecord.la \ | ||
248 | $(top_builddir)/src/service/namecache/libgnunetnamecache.la \ | ||
249 | libgnunetnamestore.la | ||
250 | |||
251 | test_namestore_api_store_update_postgres_SOURCES = \ | ||
252 | test_namestore_api_store_update.c | ||
253 | test_namestore_api_store_update_postgres_LDADD = \ | ||
254 | $(top_builddir)/src/service/testing/libgnunettesting.la \ | ||
255 | $(top_builddir)/src/lib/util/libgnunetutil.la \ | ||
256 | $(top_builddir)/src/service/identity/libgnunetidentity.la \ | ||
257 | $(top_builddir)/src/lib/gnsrecord/libgnunetgnsrecord.la \ | ||
258 | $(top_builddir)/src/service/namecache/libgnunetnamecache.la \ | ||
259 | libgnunetnamestore.la | ||
260 | |||
261 | test_namestore_api_lookup_nick_sqlite_SOURCES = \ | ||
262 | test_namestore_api_lookup_nick.c | ||
263 | test_namestore_api_lookup_nick_sqlite_LDADD = \ | ||
264 | $(top_builddir)/src/service/testing/libgnunettesting.la \ | ||
265 | $(top_builddir)/src/lib/util/libgnunetutil.la \ | ||
266 | $(top_builddir)/src/service/identity/libgnunetidentity.la \ | ||
267 | $(top_builddir)/src/lib/gnsrecord/libgnunetgnsrecord.la \ | ||
268 | $(top_builddir)/src/service/namecache/libgnunetnamecache.la \ | ||
269 | libgnunetnamestore.la | ||
270 | |||
271 | test_namestore_api_lookup_nick_postgres_SOURCES = \ | ||
272 | test_namestore_api_lookup_nick.c | ||
273 | test_namestore_api_lookup_nick_postgres_LDADD = \ | ||
274 | $(top_builddir)/src/service/testing/libgnunettesting.la \ | ||
275 | $(top_builddir)/src/lib/util/libgnunetutil.la \ | ||
276 | $(top_builddir)/src/service/identity/libgnunetidentity.la \ | ||
277 | $(top_builddir)/src/lib/gnsrecord/libgnunetgnsrecord.la \ | ||
278 | $(top_builddir)/src/service/namecache/libgnunetnamecache.la \ | ||
279 | libgnunetnamestore.la | ||
280 | |||
281 | test_namestore_api_remove_sqlite_SOURCES = \ | ||
282 | test_namestore_api_remove.c | ||
283 | test_namestore_api_remove_sqlite_LDADD = \ | ||
284 | $(top_builddir)/src/service/identity/libgnunetidentity.la \ | ||
285 | $(top_builddir)/src/service/testing/libgnunettesting.la \ | ||
286 | $(top_builddir)/src/lib/util/libgnunetutil.la \ | ||
287 | $(top_builddir)/src/lib/gnsrecord/libgnunetgnsrecord.la \ | ||
288 | libgnunetnamestore.la | ||
289 | |||
290 | test_namestore_api_remove_postgres_SOURCES = \ | ||
291 | test_namestore_api_remove.c | ||
292 | test_namestore_api_remove_postgres_LDADD = \ | ||
293 | $(top_builddir)/src/service/identity/libgnunetidentity.la \ | ||
294 | $(top_builddir)/src/service/testing/libgnunettesting.la \ | ||
295 | $(top_builddir)/src/lib/util/libgnunetutil.la \ | ||
296 | $(top_builddir)/src/lib/gnsrecord/libgnunetgnsrecord.la \ | ||
297 | libgnunetnamestore.la | ||
298 | |||
299 | test_namestore_api_remove_not_existing_record_sqlite_SOURCES = \ | ||
300 | test_namestore_api_remove_not_existing_record.c | ||
301 | test_namestore_api_remove_not_existing_record_sqlite_LDADD = \ | ||
302 | $(top_builddir)/src/service/testing/libgnunettesting.la \ | ||
303 | $(top_builddir)/src/lib/util/libgnunetutil.la \ | ||
304 | $(top_builddir)/src/service/identity/libgnunetidentity.la \ | ||
305 | $(top_builddir)/src/lib/gnsrecord/libgnunetgnsrecord.la \ | ||
306 | libgnunetnamestore.la | ||
307 | |||
308 | test_namestore_api_remove_not_existing_record_postgres_SOURCES = \ | ||
309 | test_namestore_api_remove_not_existing_record.c | ||
310 | test_namestore_api_remove_not_existing_record_postgres_LDADD = \ | ||
311 | $(top_builddir)/src/service/testing/libgnunettesting.la \ | ||
312 | $(top_builddir)/src/service/identity/libgnunetidentity.la \ | ||
313 | $(top_builddir)/src/lib/util/libgnunetutil.la \ | ||
314 | $(top_builddir)/src/lib/gnsrecord/libgnunetgnsrecord.la \ | ||
315 | libgnunetnamestore.la | ||
316 | |||
317 | test_namestore_api_zone_to_name_sqlite_SOURCES = \ | ||
318 | test_namestore_api_zone_to_name.c | ||
319 | test_namestore_api_zone_to_name_sqlite_LDADD = \ | ||
320 | $(top_builddir)/src/service/identity/libgnunetidentity.la \ | ||
321 | $(top_builddir)/src/service/testing/libgnunettesting.la \ | ||
322 | $(top_builddir)/src/lib/util/libgnunetutil.la \ | ||
323 | libgnunetnamestore.la | ||
324 | |||
325 | test_namestore_api_zone_to_name_postgres_SOURCES = \ | ||
326 | test_namestore_api_zone_to_name.c | ||
327 | test_namestore_api_zone_to_name_postgres_LDADD = \ | ||
328 | $(top_builddir)/src/service/identity/libgnunetidentity.la \ | ||
329 | $(top_builddir)/src/service/testing/libgnunettesting.la \ | ||
330 | $(top_builddir)/src/lib/util/libgnunetutil.la \ | ||
331 | libgnunetnamestore.la | ||
332 | |||
333 | test_namestore_api_monitoring_sqlite_SOURCES = \ | ||
334 | test_namestore_api_monitoring.c | ||
335 | test_namestore_api_monitoring_sqlite_LDADD = \ | ||
336 | $(top_builddir)/src/service/identity/libgnunetidentity.la \ | ||
337 | $(top_builddir)/src/service/testing/libgnunettesting.la \ | ||
338 | libgnunetnamestore.la \ | ||
339 | $(top_builddir)/src/lib/gnsrecord/libgnunetgnsrecord.la \ | ||
340 | $(top_builddir)/src/lib/util/libgnunetutil.la | ||
341 | |||
342 | test_namestore_api_monitoring_postgres_SOURCES = \ | ||
343 | test_namestore_api_monitoring.c | ||
344 | test_namestore_api_monitoring_postgres_LDADD = \ | ||
345 | $(top_builddir)/src/service/testing/libgnunettesting.la \ | ||
346 | $(top_builddir)/src/service/identity/libgnunetidentity.la \ | ||
347 | libgnunetnamestore.la \ | ||
348 | $(top_builddir)/src/lib/gnsrecord/libgnunetgnsrecord.la \ | ||
349 | $(top_builddir)/src/lib/util/libgnunetutil.la | ||
350 | |||
351 | test_namestore_api_monitoring_existing_sqlite_SOURCES = \ | ||
352 | test_namestore_api_monitoring_existing.c | ||
353 | test_namestore_api_monitoring_existing_sqlite_LDADD = \ | ||
354 | $(top_builddir)/src/service/testing/libgnunettesting.la \ | ||
355 | $(top_builddir)/src/service/identity/libgnunetidentity.la \ | ||
356 | libgnunetnamestore.la \ | ||
357 | $(top_builddir)/src/lib/gnsrecord/libgnunetgnsrecord.la \ | ||
358 | $(top_builddir)/src/lib/util/libgnunetutil.la | ||
359 | |||
360 | test_namestore_api_monitoring_existing_postgres_SOURCES = \ | ||
361 | test_namestore_api_monitoring_existing.c | ||
362 | test_namestore_api_monitoring_existing_postgres_LDADD = \ | ||
363 | $(top_builddir)/src/service/testing/libgnunettesting.la \ | ||
364 | libgnunetnamestore.la \ | ||
365 | $(top_builddir)/src/lib/gnsrecord/libgnunetgnsrecord.la \ | ||
366 | $(top_builddir)/src/service/identity/libgnunetidentity.la \ | ||
367 | $(top_builddir)/src/lib/util/libgnunetutil.la | ||
368 | |||
369 | test_namestore_api_tx_rollback_sqlite_SOURCES = \ | ||
370 | test_namestore_api_tx_rollback.c | ||
371 | test_namestore_api_tx_rollback_sqlite_LDADD = \ | ||
372 | $(top_builddir)/src/service/testing/libgnunettesting.la \ | ||
373 | $(top_builddir)/src/service/identity/libgnunetidentity.la \ | ||
374 | libgnunetnamestore.la \ | ||
375 | $(top_builddir)/src/lib/gnsrecord/libgnunetgnsrecord.la \ | ||
376 | $(top_builddir)/src/lib/util/libgnunetutil.la | ||
377 | |||
378 | test_namestore_api_tx_rollback_postgres_SOURCES = \ | ||
379 | test_namestore_api_tx_rollback.c | ||
380 | test_namestore_api_tx_rollback_postgres_LDADD = \ | ||
381 | $(top_builddir)/src/service/testing/libgnunettesting.la \ | ||
382 | $(top_builddir)/src/service/identity/libgnunetidentity.la \ | ||
383 | libgnunetnamestore.la \ | ||
384 | $(top_builddir)/src/lib/gnsrecord/libgnunetgnsrecord.la \ | ||
385 | $(top_builddir)/src/lib/util/libgnunetutil.la | ||
386 | |||
387 | if HAVE_EXPERIMENTAL | ||
388 | test_namestore_api_edit_records_postgres_SOURCES = \ | ||
389 | test_namestore_api_edit_records.c | ||
390 | test_namestore_api_edit_records_postgres_LDADD = \ | ||
391 | $(top_builddir)/src/service/testing/libgnunettesting.la \ | ||
392 | $(top_builddir)/src/service/identity/libgnunetidentity.la \ | ||
393 | libgnunetnamestore.la \ | ||
394 | $(top_builddir)/src/lib/gnsrecord/libgnunetgnsrecord.la \ | ||
395 | $(top_builddir)/src/lib/util/libgnunetutil.la | ||
396 | endif | ||
397 | |||
398 | test_namestore_api_zone_iteration_sqlite_SOURCES = \ | ||
399 | test_namestore_api_zone_iteration.c | ||
400 | test_namestore_api_zone_iteration_sqlite_LDADD = \ | ||
401 | $(top_builddir)/src/service/testing/libgnunettesting.la \ | ||
402 | $(top_builddir)/src/service/identity/libgnunetidentity.la \ | ||
403 | $(top_builddir)/src/lib/util/libgnunetutil.la \ | ||
404 | $(top_builddir)/src/lib/gnsrecord/libgnunetgnsrecord.la \ | ||
405 | libgnunetnamestore.la | ||
406 | |||
407 | test_namestore_api_zone_iteration_postgres_SOURCES = \ | ||
408 | test_namestore_api_zone_iteration.c | ||
409 | test_namestore_api_zone_iteration_postgres_LDADD = \ | ||
410 | $(top_builddir)/src/service/testing/libgnunettesting.la \ | ||
411 | $(top_builddir)/src/service/identity/libgnunetidentity.la \ | ||
412 | $(top_builddir)/src/lib/util/libgnunetutil.la \ | ||
413 | $(top_builddir)/src/lib/gnsrecord/libgnunetgnsrecord.la \ | ||
414 | libgnunetnamestore.la | ||
415 | |||
416 | perf_namestore_api_zone_iteration_postgres_SOURCES = \ | ||
417 | perf_namestore_api_zone_iteration.c | ||
418 | perf_namestore_api_zone_iteration_postgres_LDADD = \ | ||
419 | $(top_builddir)/src/service/testing/libgnunettesting.la \ | ||
420 | $(top_builddir)/src/lib/util/libgnunetutil.la \ | ||
421 | $(top_builddir)/src/service/identity/libgnunetidentity.la \ | ||
422 | $(top_builddir)/src/lib/gnsrecord/libgnunetgnsrecord.la \ | ||
423 | libgnunetnamestore.la | ||
424 | |||
425 | perf_namestore_api_import_sqlite_SOURCES = \ | ||
426 | perf_namestore_api_import.c | ||
427 | perf_namestore_api_import_sqlite_LDADD = \ | ||
428 | $(top_builddir)/src/service/testing/libgnunettesting.la \ | ||
429 | $(top_builddir)/src/lib/util/libgnunetutil.la \ | ||
430 | $(top_builddir)/src/service/identity/libgnunetidentity.la \ | ||
431 | $(top_builddir)/src/lib/gnsrecord/libgnunetgnsrecord.la \ | ||
432 | libgnunetnamestore.la | ||
433 | |||
434 | perf_namestore_api_import_postgres_SOURCES = \ | ||
435 | perf_namestore_api_import.c | ||
436 | perf_namestore_api_import_postgres_LDADD = \ | ||
437 | $(top_builddir)/src/service/testing/libgnunettesting.la \ | ||
438 | $(top_builddir)/src/lib/util/libgnunetutil.la \ | ||
439 | $(top_builddir)/src/service/identity/libgnunetidentity.la \ | ||
440 | $(top_builddir)/src/lib/gnsrecord/libgnunetgnsrecord.la \ | ||
441 | libgnunetnamestore.la | ||
442 | |||
443 | |||
444 | perf_namestore_api_zone_iteration_sqlite_SOURCES = \ | ||
445 | perf_namestore_api_zone_iteration.c | ||
446 | perf_namestore_api_zone_iteration_sqlite_LDADD = \ | ||
447 | $(top_builddir)/src/service/testing/libgnunettesting.la \ | ||
448 | $(top_builddir)/src/service/identity/libgnunetidentity.la \ | ||
449 | $(top_builddir)/src/lib/util/libgnunetutil.la \ | ||
450 | $(top_builddir)/src/lib/gnsrecord/libgnunetgnsrecord.la \ | ||
451 | libgnunetnamestore.la | ||
452 | |||
453 | test_namestore_api_zone_iteration_nick_sqlite_SOURCES = \ | ||
454 | test_namestore_api_zone_iteration_nick.c | ||
455 | test_namestore_api_zone_iteration_nick_sqlite_LDADD = \ | ||
456 | $(top_builddir)/src/service/testing/libgnunettesting.la \ | ||
457 | $(top_builddir)/src/service/identity/libgnunetidentity.la \ | ||
458 | $(top_builddir)/src/lib/util/libgnunetutil.la \ | ||
459 | $(top_builddir)/src/lib/gnsrecord/libgnunetgnsrecord.la \ | ||
460 | libgnunetnamestore.la | ||
461 | |||
462 | test_namestore_api_zone_iteration_nick_postgres_SOURCES = \ | ||
463 | test_namestore_api_zone_iteration_nick.c | ||
464 | test_namestore_api_zone_iteration_nick_postgres_LDADD = \ | ||
465 | $(top_builddir)/src/service/testing/libgnunettesting.la \ | ||
466 | $(top_builddir)/src/service/identity/libgnunetidentity.la \ | ||
467 | $(top_builddir)/src/lib/util/libgnunetutil.la \ | ||
468 | $(top_builddir)/src/lib/gnsrecord/libgnunetgnsrecord.la \ | ||
469 | libgnunetnamestore.la | ||
470 | |||
471 | test_namestore_api_zone_iteration_specific_zone_sqlite_SOURCES = \ | ||
472 | test_namestore_api_zone_iteration_specific_zone.c | ||
473 | test_namestore_api_zone_iteration_specific_zone_sqlite_LDADD = \ | ||
474 | $(top_builddir)/src/service/testing/libgnunettesting.la \ | ||
475 | $(top_builddir)/src/service/identity/libgnunetidentity.la \ | ||
476 | $(top_builddir)/src/lib/util/libgnunetutil.la \ | ||
477 | $(top_builddir)/src/lib/gnsrecord/libgnunetgnsrecord.la \ | ||
478 | libgnunetnamestore.la | ||
479 | |||
480 | test_namestore_api_zone_iteration_specific_zone_postgres_SOURCES = \ | ||
481 | test_namestore_api_zone_iteration_specific_zone.c | ||
482 | test_namestore_api_zone_iteration_specific_zone_postgres_LDADD = \ | ||
483 | $(top_builddir)/src/service/testing/libgnunettesting.la \ | ||
484 | $(top_builddir)/src/service/identity/libgnunetidentity.la \ | ||
485 | $(top_builddir)/src/lib/util/libgnunetutil.la \ | ||
486 | $(top_builddir)/src/lib/gnsrecord/libgnunetgnsrecord.la \ | ||
487 | libgnunetnamestore.la | ||
488 | |||
489 | test_namestore_api_zone_iteration_stop_sqlite_SOURCES = \ | ||
490 | test_namestore_api_zone_iteration_stop.c | ||
491 | test_namestore_api_zone_iteration_stop_sqlite_LDADD = \ | ||
492 | $(top_builddir)/src/service/testing/libgnunettesting.la \ | ||
493 | $(top_builddir)/src/service/identity/libgnunetidentity.la \ | ||
494 | $(top_builddir)/src/lib/util/libgnunetutil.la \ | ||
495 | $(top_builddir)/src/lib/gnsrecord/libgnunetgnsrecord.la \ | ||
496 | libgnunetnamestore.la | ||
497 | |||
498 | test_namestore_api_zone_iteration_stop_postgres_SOURCES = \ | ||
499 | test_namestore_api_zone_iteration_stop.c | ||
500 | test_namestore_api_zone_iteration_stop_postgres_LDADD = \ | ||
501 | $(top_builddir)/src/service/testing/libgnunettesting.la \ | ||
502 | $(top_builddir)/src/service/identity/libgnunetidentity.la \ | ||
503 | $(top_builddir)/src/lib/util/libgnunetutil.la \ | ||
504 | $(top_builddir)/src/lib/gnsrecord/libgnunetgnsrecord.la \ | ||
505 | libgnunetnamestore.la | ||
506 | |||
507 | test_plugin_namestore_sqlite_SOURCES = \ | ||
508 | test_plugin_namestore.c | ||
509 | test_plugin_namestore_sqlite_LDADD = \ | ||
510 | $(top_builddir)/src/service/testing/libgnunettesting.la \ | ||
511 | $(top_builddir)/src/service/identity/libgnunetidentity.la \ | ||
512 | $(top_builddir)/src/lib/util/libgnunetutil.la | ||
513 | |||
514 | test_plugin_namestore_postgres_SOURCES = \ | ||
515 | test_plugin_namestore.c | ||
516 | test_plugin_namestore_postgres_LDADD = \ | ||
517 | $(top_builddir)/src/service/identity/libgnunetidentity.la \ | ||
518 | $(top_builddir)/src/service/testing/libgnunettesting.la \ | ||
519 | $(top_builddir)/src/lib/util/libgnunetutil.la | ||
520 | |||
521 | check_SCRIPTS = \ | ||
522 | test_namestore_put.sh \ | ||
523 | test_namestore_put_stdin.sh \ | ||
524 | test_namestore_lookup.sh \ | ||
525 | test_namestore_delete.sh \ | ||
526 | test_namestore_zonefile_import.sh | ||
527 | |||
528 | check_SCRIPTS += \ | ||
529 | test_plugin_rest_namestore.sh | ||
530 | |||
531 | EXTRA_DIST = \ | ||
532 | test_common.c \ | ||
533 | test_namestore_api.conf \ | ||
534 | test_namestore_api_postgres.conf \ | ||
535 | test_namestore_api_sqlite.conf \ | ||
536 | perf_namestore_api_postgres.conf \ | ||
537 | perf_namestore_api_sqlite.conf \ | ||
538 | test_plugin_namestore_sqlite.conf \ | ||
539 | test_plugin_namestore_postgres.conf \ | ||
540 | test_hostkey \ | ||
541 | example_zonefile \ | ||
542 | $(check_SCRIPTS) \ | ||
543 | $(sql_DATA) | ||
diff --git a/src/namestore/example_zonefile b/src/namestore/example_zonefile deleted file mode 100644 index 5e380ff90..000000000 --- a/src/namestore/example_zonefile +++ /dev/null | |||
@@ -1,27 +0,0 @@ | |||
1 | $ORIGIN example.com. ; designates the start of this zone file in the namespace | ||
2 | $TTL 3600 ; default expiration time (in seconds) of all RRs without their own TTL value | ||
3 | example.com. IN SOA ns.example.com. username.example.com. ( 2020091025 ; A comment | ||
4 | 7200 ; Comment | ||
5 | ; empty line on purpose | ||
6 | 3600 | ||
7 | 1209600 | ||
8 | 3600 ) | ||
9 | example.com. IN NS ns ; ns.example.com is a nameserver for example.com | ||
10 | example.com. IN NS ns.somewhere.example. ; ns.somewhere.example is a backup nameserver for example.com | ||
11 | example.com. IN MX 10 mail.example.com. ; mail.example.com is the mailserver for example.com | ||
12 | @ IN MX 20 mail2.example.com. ; equivalent to above line, "@" represents zone origin | ||
13 | @ IN MX 50 mail3 ; equivalent to above line, but using a relative host name | ||
14 | b.example.com. IN A 192.0.2.1 ; IPv4 address for example.com | ||
15 | IN AAAA 2001:db8:10::1 ; IPv6 address for example.com | ||
16 | ns IN A 192.0.2.2 ; IPv4 address for ns.example.com | ||
17 | IN AAAA 2001:db8:10::2 ; IPv6 address for ns.example.com | ||
18 | www IN CNAME example.com. ; www.example.com is an alias for example.com | ||
19 | wwwtest IN CNAME www ; wwwtest.example.com is another alias for www.example.com | ||
20 | mail IN A 192.0.2.3 ; IPv4 address for mail.example.com | ||
21 | mail2 IN A 192.0.2.4 ; IPv4 address for mail2.example.com | ||
22 | mail3 IN A 192.0.2.5 ; IPv4 address for mail3.example.com | ||
23 | |||
24 | mail3 IN TXT "This is ; quoted" ; A quoted comment separator | ||
25 | $ORIGIN example.de. | ||
26 | www2 IN A 192.0.2.7 ; IPv4 address for www2.example.de | ||
27 | |||
diff --git a/src/namestore/gnunet-namestore-dbtool.c b/src/namestore/gnunet-namestore-dbtool.c deleted file mode 100644 index 835d7a228..000000000 --- a/src/namestore/gnunet-namestore-dbtool.c +++ /dev/null | |||
@@ -1,199 +0,0 @@ | |||
1 | /* | ||
2 | This file is part of GNUnet. | ||
3 | Copyright (C) 2012, 2013, 2014, 2019, 2022 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-dbtool.c | ||
22 | * @brief command line tool to manipulate the database backends for the namestore | ||
23 | * @author Martin Schanzenbach | ||
24 | * | ||
25 | */ | ||
26 | #include "platform.h" | ||
27 | #include <gnunet_util_lib.h> | ||
28 | #include <gnunet_namestore_plugin.h> | ||
29 | |||
30 | /** | ||
31 | * Name of the plugin argument | ||
32 | */ | ||
33 | static char *pluginname; | ||
34 | |||
35 | /** | ||
36 | * Reset argument | ||
37 | */ | ||
38 | static int reset; | ||
39 | |||
40 | /** | ||
41 | * Initialize argument | ||
42 | */ | ||
43 | static int init; | ||
44 | |||
45 | /** | ||
46 | * Return code | ||
47 | */ | ||
48 | static int ret = 0; | ||
49 | |||
50 | /** | ||
51 | * Task run on shutdown. Cleans up everything. | ||
52 | * | ||
53 | * @param cls unused | ||
54 | */ | ||
55 | static void | ||
56 | do_shutdown (void *cls) | ||
57 | { | ||
58 | (void) cls; | ||
59 | if (NULL != pluginname) | ||
60 | GNUNET_free (pluginname); | ||
61 | } | ||
62 | |||
63 | |||
64 | /** | ||
65 | * Main function that will be run. | ||
66 | * | ||
67 | * @param cls closure | ||
68 | * @param args remaining command-line arguments | ||
69 | * @param cfgfile name of the configuration file used (for saving, can be NULL!) | ||
70 | * @param cfg configuration | ||
71 | */ | ||
72 | static void | ||
73 | run (void *cls, | ||
74 | char *const *args, | ||
75 | const char *cfgfile, | ||
76 | const struct GNUNET_CONFIGURATION_Handle *cfg) | ||
77 | { | ||
78 | char *db_lib_name; | ||
79 | struct GNUNET_NAMESTORE_PluginFunctions *plugin; | ||
80 | |||
81 | (void) cls; | ||
82 | (void) args; | ||
83 | (void) cfgfile; | ||
84 | if (NULL != args[0]) | ||
85 | GNUNET_log ( | ||
86 | GNUNET_ERROR_TYPE_WARNING, | ||
87 | _ ("Superfluous command line arguments (starting with `%s') ignored\n"), | ||
88 | args[0]); | ||
89 | |||
90 | GNUNET_SCHEDULER_add_shutdown (&do_shutdown, | ||
91 | (void *) cfg); | ||
92 | if (NULL == pluginname) | ||
93 | { | ||
94 | fprintf (stderr, "No plugin given!\n"); | ||
95 | ret = 1; | ||
96 | GNUNET_SCHEDULER_shutdown (); | ||
97 | return; | ||
98 | } | ||
99 | GNUNET_asprintf (&db_lib_name, | ||
100 | "libgnunet_plugin_namestore_%s", | ||
101 | pluginname); | ||
102 | plugin = GNUNET_PLUGIN_load (db_lib_name, (void *) cfg); | ||
103 | if (NULL == plugin) | ||
104 | { | ||
105 | fprintf (stderr, | ||
106 | "Failed to load %s!\n", | ||
107 | db_lib_name); | ||
108 | ret = 1; | ||
109 | GNUNET_SCHEDULER_shutdown (); | ||
110 | GNUNET_free (db_lib_name); | ||
111 | return; | ||
112 | } | ||
113 | if (reset) | ||
114 | { | ||
115 | if (GNUNET_OK != | ||
116 | plugin->drop_tables (plugin->cls)) | ||
117 | { | ||
118 | fprintf (stderr, | ||
119 | "Failed to reset database\n"); | ||
120 | ret = 1; | ||
121 | GNUNET_free (db_lib_name); | ||
122 | GNUNET_SCHEDULER_shutdown (); | ||
123 | return; | ||
124 | } | ||
125 | } | ||
126 | if (init || reset) | ||
127 | { | ||
128 | if (GNUNET_OK != | ||
129 | plugin->create_tables (plugin->cls)) | ||
130 | { | ||
131 | fprintf (stderr, | ||
132 | "Failed to initialize database\n"); | ||
133 | ret = 1; | ||
134 | GNUNET_free (db_lib_name); | ||
135 | GNUNET_SCHEDULER_shutdown (); | ||
136 | return; | ||
137 | } | ||
138 | } | ||
139 | GNUNET_SCHEDULER_shutdown (); | ||
140 | GNUNET_break (NULL == GNUNET_PLUGIN_unload (db_lib_name, | ||
141 | plugin)); | ||
142 | GNUNET_free (db_lib_name); | ||
143 | } | ||
144 | |||
145 | |||
146 | /** | ||
147 | * The main function for gnunet-namestore-dbtool. | ||
148 | * | ||
149 | * @param argc number of arguments from the command line | ||
150 | * @param argv command line arguments | ||
151 | * @return 0 ok, 1 on error | ||
152 | */ | ||
153 | int | ||
154 | main (int argc, char *const *argv) | ||
155 | { | ||
156 | struct GNUNET_GETOPT_CommandLineOption options[] = { | ||
157 | GNUNET_GETOPT_option_flag ('i', "init", | ||
158 | gettext_noop ("initialize database"), | ||
159 | &init), | ||
160 | GNUNET_GETOPT_option_flag ('r', | ||
161 | "reset", | ||
162 | gettext_noop ( | ||
163 | "reset database (DANGEROUS: All existing data is lost!"), | ||
164 | &reset), | ||
165 | GNUNET_GETOPT_option_string ( | ||
166 | 'p', | ||
167 | "plugin", | ||
168 | "PLUGIN", | ||
169 | gettext_noop ( | ||
170 | "the namestore plugin to work with, e.g. 'sqlite'"), | ||
171 | &pluginname), | ||
172 | GNUNET_GETOPT_OPTION_END | ||
173 | }; | ||
174 | int lret; | ||
175 | |||
176 | if (GNUNET_OK != | ||
177 | GNUNET_STRINGS_get_utf8_args (argc, argv, | ||
178 | &argc, &argv)) | ||
179 | return 2; | ||
180 | |||
181 | GNUNET_log_setup ("gnunet-namestore-dbtool", | ||
182 | "WARNING", | ||
183 | NULL); | ||
184 | if (GNUNET_OK != | ||
185 | (lret = GNUNET_PROGRAM_run (argc, | ||
186 | argv, | ||
187 | "gnunet-namestore-dbtool", | ||
188 | _ ( | ||
189 | "GNUnet namestore database manipulation tool"), | ||
190 | options, | ||
191 | &run, | ||
192 | NULL))) | ||
193 | { | ||
194 | GNUNET_free_nz ((void *) argv); | ||
195 | return lret; | ||
196 | } | ||
197 | GNUNET_free_nz ((void *) argv); | ||
198 | return ret; | ||
199 | } | ||
diff --git a/src/namestore/gnunet-namestore-fcfsd.c b/src/namestore/gnunet-namestore-fcfsd.c deleted file mode 100644 index 4948ae441..000000000 --- a/src/namestore/gnunet-namestore-fcfsd.c +++ /dev/null | |||
@@ -1,1160 +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 | */ | ||
42 | struct 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 | */ | ||
63 | struct 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_CRYPTO_PublicKey key; | ||
114 | }; | ||
115 | |||
116 | /** | ||
117 | * Name of the zone being managed. | ||
118 | */ | ||
119 | static char *zone = NULL; | ||
120 | |||
121 | /** | ||
122 | * The port the daemon is listening to for HTTP requests. | ||
123 | */ | ||
124 | static unsigned long long port = 18080; | ||
125 | |||
126 | /** | ||
127 | * Connection with the namestore service. | ||
128 | */ | ||
129 | static struct GNUNET_NAMESTORE_Handle *namestore = NULL; | ||
130 | |||
131 | /** | ||
132 | * Connection with the identity service. | ||
133 | */ | ||
134 | static struct GNUNET_IDENTITY_Handle *identity = NULL; | ||
135 | |||
136 | /** | ||
137 | * Private key of the zone. | ||
138 | */ | ||
139 | static const struct GNUNET_CRYPTO_PrivateKey *zone_key = NULL; | ||
140 | |||
141 | /** | ||
142 | * The HTTP daemon. | ||
143 | */ | ||
144 | static struct MHD_Daemon *httpd = NULL; | ||
145 | |||
146 | /** | ||
147 | * Task executing the HTTP daemon. | ||
148 | */ | ||
149 | static struct GNUNET_SCHEDULER_Task *httpd_task = NULL; | ||
150 | |||
151 | /** | ||
152 | * The main page, a.k.a. "index.html" | ||
153 | */ | ||
154 | static struct StaticPage *main_page = NULL; | ||
155 | |||
156 | /** | ||
157 | * Page indicating the requested resource could not be found. | ||
158 | */ | ||
159 | static struct StaticPage *notfound_page = NULL; | ||
160 | |||
161 | /** | ||
162 | * Page indicating the requested resource could not be accessed, and other | ||
163 | * errors. | ||
164 | */ | ||
165 | static struct StaticPage *forbidden_page = NULL; | ||
166 | |||
167 | /** | ||
168 | * The relative expiration time for added records | ||
169 | */ | ||
170 | static struct GNUNET_TIME_Relative record_exp; | ||
171 | |||
172 | /** | ||
173 | * Task ran at shutdown to clean up everything. | ||
174 | * | ||
175 | * @param cls unused | ||
176 | */ | ||
177 | static void | ||
178 | do_shutdown (void *cls) | ||
179 | { | ||
180 | /* We cheat a bit here: the file descriptor is implicitly closed by MHD, so | ||
181 | calling `GNUNET_DISK_file_close' would generate a spurious warning message | ||
182 | in the log. Since that function does nothing but close the descriptor and | ||
183 | free the allocated memory, After destroying the response all that's left to | ||
184 | do is call `GNUNET_free'. */ | ||
185 | if (NULL != main_page) | ||
186 | { | ||
187 | MHD_destroy_response (main_page->response); | ||
188 | GNUNET_free (main_page->handle); | ||
189 | GNUNET_free (main_page); | ||
190 | } | ||
191 | if (NULL != notfound_page) | ||
192 | { | ||
193 | MHD_destroy_response (notfound_page->response); | ||
194 | GNUNET_free (notfound_page->handle); | ||
195 | GNUNET_free (notfound_page); | ||
196 | } | ||
197 | if (NULL != forbidden_page) | ||
198 | { | ||
199 | MHD_destroy_response (forbidden_page->response); | ||
200 | GNUNET_free (forbidden_page->handle); | ||
201 | GNUNET_free (forbidden_page); | ||
202 | } | ||
203 | |||
204 | if (NULL != namestore) | ||
205 | { | ||
206 | GNUNET_NAMESTORE_disconnect (namestore); | ||
207 | } | ||
208 | |||
209 | if (NULL != identity) | ||
210 | { | ||
211 | GNUNET_IDENTITY_disconnect (identity); | ||
212 | } | ||
213 | |||
214 | if (NULL != httpd_task) | ||
215 | { | ||
216 | GNUNET_SCHEDULER_cancel (httpd_task); | ||
217 | } | ||
218 | if (NULL != httpd) | ||
219 | { | ||
220 | MHD_stop_daemon (httpd); | ||
221 | } | ||
222 | } | ||
223 | |||
224 | |||
225 | /** | ||
226 | * Called when the HTTP server has some pending operations. | ||
227 | * | ||
228 | * @param cls unused | ||
229 | */ | ||
230 | static void | ||
231 | do_httpd (void *cls); | ||
232 | |||
233 | /** | ||
234 | * Schedule a task to run MHD. | ||
235 | */ | ||
236 | static void | ||
237 | run_httpd (void) | ||
238 | { | ||
239 | fd_set rs; | ||
240 | fd_set ws; | ||
241 | fd_set es; | ||
242 | |||
243 | struct GNUNET_NETWORK_FDSet *grs = GNUNET_NETWORK_fdset_create (); | ||
244 | struct GNUNET_NETWORK_FDSet *gws = GNUNET_NETWORK_fdset_create (); | ||
245 | struct GNUNET_NETWORK_FDSet *ges = GNUNET_NETWORK_fdset_create (); | ||
246 | |||
247 | FD_ZERO (&rs); | ||
248 | FD_ZERO (&ws); | ||
249 | FD_ZERO (&es); | ||
250 | |||
251 | int max = -1; | ||
252 | GNUNET_assert (MHD_YES == MHD_get_fdset (httpd, &rs, &ws, &es, &max)); | ||
253 | |||
254 | unsigned MHD_LONG_LONG timeout = 0; | ||
255 | struct GNUNET_TIME_Relative gtime = GNUNET_TIME_UNIT_FOREVER_REL; | ||
256 | if (MHD_YES == MHD_get_timeout (httpd, &timeout)) | ||
257 | { | ||
258 | gtime = GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MILLISECONDS, | ||
259 | timeout); | ||
260 | } | ||
261 | |||
262 | GNUNET_NETWORK_fdset_copy_native (grs, &rs, max + 1); | ||
263 | GNUNET_NETWORK_fdset_copy_native (gws, &ws, max + 1); | ||
264 | GNUNET_NETWORK_fdset_copy_native (ges, &es, max + 1); | ||
265 | |||
266 | httpd_task = GNUNET_SCHEDULER_add_select (GNUNET_SCHEDULER_PRIORITY_HIGH, | ||
267 | gtime, | ||
268 | grs, | ||
269 | gws, | ||
270 | &do_httpd, | ||
271 | NULL); | ||
272 | GNUNET_NETWORK_fdset_destroy (grs); | ||
273 | GNUNET_NETWORK_fdset_destroy (gws); | ||
274 | GNUNET_NETWORK_fdset_destroy (ges); | ||
275 | } | ||
276 | |||
277 | |||
278 | /** | ||
279 | * Called when the HTTP server has some pending operations. | ||
280 | * | ||
281 | * @param cls unused | ||
282 | */ | ||
283 | static void | ||
284 | do_httpd (void *cls) | ||
285 | { | ||
286 | httpd_task = NULL; | ||
287 | MHD_run (httpd); | ||
288 | run_httpd (); | ||
289 | } | ||
290 | |||
291 | |||
292 | static void | ||
293 | run_httpd_now (void) | ||
294 | { | ||
295 | if (NULL != httpd_task) | ||
296 | { | ||
297 | GNUNET_SCHEDULER_cancel (httpd_task); | ||
298 | httpd_task = NULL; | ||
299 | } | ||
300 | httpd_task = GNUNET_SCHEDULER_add_now (&do_httpd, NULL); | ||
301 | } | ||
302 | |||
303 | |||
304 | /** | ||
305 | * Generate a JSON object. | ||
306 | * | ||
307 | * @param key the key for the first element | ||
308 | * @param value the value for the first element | ||
309 | * @param ... key-value pairs of the object, terminated by NULL | ||
310 | * @return a JSON string (allocated) | ||
311 | */ | ||
312 | static char * | ||
313 | make_json (const char *key, const char *value, ...) | ||
314 | { | ||
315 | va_list args; | ||
316 | va_start (args, value); | ||
317 | |||
318 | json_t *obj = NULL; | ||
319 | |||
320 | obj = json_object (); | ||
321 | if ((NULL == key) || (NULL == value)) | ||
322 | { | ||
323 | va_end (args); | ||
324 | return json_dumps (obj, JSON_COMPACT); | ||
325 | } | ||
326 | |||
327 | json_object_set (obj, key, json_string (value)); | ||
328 | |||
329 | char *k = va_arg (args, char *); | ||
330 | if (NULL == k) | ||
331 | { | ||
332 | va_end (args); | ||
333 | return json_dumps (obj, JSON_COMPACT); | ||
334 | } | ||
335 | char *v = va_arg (args, char *); | ||
336 | if (NULL == v) | ||
337 | { | ||
338 | va_end (args); | ||
339 | return json_dumps (obj, JSON_COMPACT); | ||
340 | } | ||
341 | |||
342 | while (NULL != k && NULL != v) | ||
343 | { | ||
344 | json_object_set (obj, k, json_string (v)); | ||
345 | k = va_arg (args, char *); | ||
346 | if (NULL != k) | ||
347 | { | ||
348 | v = va_arg (args, char *); | ||
349 | } | ||
350 | } | ||
351 | |||
352 | va_end (args); | ||
353 | |||
354 | char *json = json_dumps (obj, JSON_COMPACT); | ||
355 | json_decref (obj); | ||
356 | |||
357 | return json; | ||
358 | } | ||
359 | |||
360 | |||
361 | /** | ||
362 | * The namestore search task failed. | ||
363 | * | ||
364 | * @param cls the request data | ||
365 | */ | ||
366 | static void | ||
367 | search_error_cb (void *cls) | ||
368 | { | ||
369 | struct RequestData *rd = cls; | ||
370 | MHD_resume_connection (rd->c); | ||
371 | rd->searching = NULL; | ||
372 | rd->body = make_json ("error", "true", | ||
373 | "message", _ ("can not search the namestore"), | ||
374 | NULL); | ||
375 | rd->body_length = strlen (rd->body); | ||
376 | rd->code = MHD_HTTP_INTERNAL_SERVER_ERROR; | ||
377 | run_httpd_now (); | ||
378 | } | ||
379 | |||
380 | |||
381 | /** | ||
382 | * The lookup terminated with some results. | ||
383 | * | ||
384 | * @param cls closure | ||
385 | * @param zone the private key of the zone | ||
386 | * @param label the result label | ||
387 | * @param count number of records found | ||
388 | * @param d records found | ||
389 | */ | ||
390 | static void | ||
391 | search_done_cb (void *cls, | ||
392 | const struct GNUNET_CRYPTO_PrivateKey *zone, | ||
393 | const char *label, | ||
394 | unsigned int count, | ||
395 | const struct GNUNET_GNSRECORD_Data *d) | ||
396 | { | ||
397 | (void) zone; | ||
398 | (void) d; | ||
399 | |||
400 | struct RequestData *rd = cls; | ||
401 | MHD_resume_connection (rd->c); | ||
402 | |||
403 | rd->searching = NULL; | ||
404 | rd->body = make_json ("error", "false", | ||
405 | "free", (0 == count) ? "true" : "false", | ||
406 | NULL); | ||
407 | rd->body_length = strlen (rd->body); | ||
408 | rd->code = MHD_HTTP_OK; | ||
409 | |||
410 | run_httpd_now (); | ||
411 | } | ||
412 | |||
413 | |||
414 | /** | ||
415 | * An error occurred while registering a name. | ||
416 | * | ||
417 | * @param cls the connection | ||
418 | */ | ||
419 | static void | ||
420 | register_error_cb (void *cls) | ||
421 | { | ||
422 | struct RequestData *rd = cls; | ||
423 | |||
424 | MHD_resume_connection (rd->c); | ||
425 | rd->searching = NULL; | ||
426 | rd->body = make_json ("error", "true", | ||
427 | "message", _ ("unable to scan namestore"), | ||
428 | NULL); | ||
429 | rd->body_length = strlen (rd->body); | ||
430 | rd->code = MHD_HTTP_INTERNAL_SERVER_ERROR; | ||
431 | run_httpd_now (); | ||
432 | } | ||
433 | |||
434 | |||
435 | static void | ||
436 | register_done_cb (void *cls, | ||
437 | enum GNUNET_ErrorCode ec) | ||
438 | { | ||
439 | struct RequestData *rd = cls; | ||
440 | |||
441 | MHD_resume_connection (rd->c); | ||
442 | rd->searching = NULL; | ||
443 | |||
444 | if (GNUNET_EC_NONE != ec) | ||
445 | { | ||
446 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, | ||
447 | _ ("Failed to create record for `%s': %s\n"), | ||
448 | rd->register_name, | ||
449 | GNUNET_ErrorCode_get_hint (ec)); | ||
450 | rd->body = make_json ("error", "true", | ||
451 | "message", | ||
452 | GNUNET_ErrorCode_get_hint (ec), | ||
453 | NULL); | ||
454 | rd->body_length = strlen (rd->body); | ||
455 | rd->code = MHD_HTTP_INTERNAL_SERVER_ERROR; | ||
456 | } | ||
457 | else | ||
458 | { | ||
459 | rd->body = make_json ("error", "false", | ||
460 | "message", _ ("no errors"), | ||
461 | NULL); | ||
462 | rd->body_length = strlen (rd->body); | ||
463 | rd->code = MHD_HTTP_OK; | ||
464 | } | ||
465 | |||
466 | run_httpd_now (); | ||
467 | } | ||
468 | |||
469 | |||
470 | /** | ||
471 | * Attempt to register the requested name. | ||
472 | * | ||
473 | * @param cls the connection | ||
474 | * @param key the zone key | ||
475 | * @param label name of the record | ||
476 | * @param count number of records found | ||
477 | * @param d records | ||
478 | */ | ||
479 | static void | ||
480 | register_do_cb (void *cls, | ||
481 | const struct GNUNET_CRYPTO_PrivateKey *key, | ||
482 | const char *label, | ||
483 | unsigned int count, | ||
484 | const struct GNUNET_GNSRECORD_Data *d) | ||
485 | { | ||
486 | (void) key; | ||
487 | (void) d; | ||
488 | |||
489 | struct RequestData *rd = cls; | ||
490 | |||
491 | rd->searching = NULL; | ||
492 | |||
493 | if (0 != count) | ||
494 | { | ||
495 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, | ||
496 | _ ("The requested key `%s' exists as `%s'\n"), | ||
497 | rd->register_key, | ||
498 | label); | ||
499 | |||
500 | MHD_resume_connection (rd->c); | ||
501 | rd->searching = NULL; | ||
502 | rd->body = make_json ("error", "true", | ||
503 | "message", _ ("key exists"), | ||
504 | NULL); | ||
505 | rd->body_length = strlen (rd->body); | ||
506 | rd->code = MHD_HTTP_FORBIDDEN; | ||
507 | run_httpd_now (); | ||
508 | return; | ||
509 | } | ||
510 | |||
511 | struct GNUNET_GNSRECORD_Data gd; | ||
512 | char *gdraw = NULL; | ||
513 | |||
514 | if (GNUNET_OK != GNUNET_GNSRECORD_data_from_identity (&(rd->key), | ||
515 | &gdraw, | ||
516 | &(gd.data_size), | ||
517 | &(gd.record_type))) | ||
518 | { | ||
519 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, | ||
520 | _ ("Error creating record data\n")); | ||
521 | MHD_resume_connection (rd->c); | ||
522 | rd->searching = NULL; | ||
523 | rd->body = make_json ("error", "true", | ||
524 | "message", _ ("unable to store record"), | ||
525 | NULL); | ||
526 | rd->body_length = strlen (rd->body); | ||
527 | rd->code = MHD_HTTP_INTERNAL_SERVER_ERROR; | ||
528 | run_httpd_now (); | ||
529 | return; | ||
530 | } | ||
531 | |||
532 | gd.data = gdraw; | ||
533 | gd.expiration_time = record_exp.rel_value_us; | ||
534 | gd.flags = GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION; | ||
535 | |||
536 | rd->searching = GNUNET_NAMESTORE_records_store (namestore, | ||
537 | zone_key, | ||
538 | rd->register_name, | ||
539 | 1, | ||
540 | &gd, | ||
541 | ®ister_done_cb, | ||
542 | rd); | ||
543 | |||
544 | GNUNET_free (gdraw); | ||
545 | } | ||
546 | |||
547 | |||
548 | /** | ||
549 | * An error occurred while iterating the namestore. | ||
550 | * | ||
551 | * @param cls the connection | ||
552 | */ | ||
553 | static void | ||
554 | iterate_error_cb (void *cls) | ||
555 | { | ||
556 | struct RequestData *rd = cls; | ||
557 | |||
558 | MHD_resume_connection (rd->c); | ||
559 | rd->iterating = NULL; | ||
560 | rd->body = make_json ("error", "true", | ||
561 | "message", _ ("unable to scan namestore"), | ||
562 | NULL); | ||
563 | rd->body_length = strlen (rd->body); | ||
564 | rd->code = MHD_HTTP_INTERNAL_SERVER_ERROR; | ||
565 | run_httpd_now (); | ||
566 | } | ||
567 | |||
568 | |||
569 | /** | ||
570 | * A block was received from the namestore. | ||
571 | * | ||
572 | * @param cls the connection | ||
573 | * @param key the zone key | ||
574 | * @param label the records' label | ||
575 | * @param count number of records found | ||
576 | * @param d the found records | ||
577 | */ | ||
578 | static void | ||
579 | iterate_do_cb (void *cls, | ||
580 | const struct GNUNET_CRYPTO_PrivateKey *key, | ||
581 | const char *label, | ||
582 | unsigned int count, | ||
583 | const struct GNUNET_GNSRECORD_Data *d) | ||
584 | { | ||
585 | (void) key; | ||
586 | (void) label; | ||
587 | (void) d; | ||
588 | |||
589 | struct RequestData *rd = cls; | ||
590 | |||
591 | if (0 == strcmp (label, rd->register_name)) | ||
592 | { | ||
593 | GNUNET_break (0 != count); | ||
594 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, | ||
595 | _ ("Requested name `%s' exists with `%u' records\n"), | ||
596 | rd->register_name, | ||
597 | count); | ||
598 | |||
599 | MHD_resume_connection (rd->c); | ||
600 | rd->body = make_json ("error", "true", | ||
601 | "message", _ ("name exists\n"), | ||
602 | NULL); | ||
603 | rd->body_length = strlen (rd->body); | ||
604 | rd->code = MHD_HTTP_FORBIDDEN; | ||
605 | GNUNET_NAMESTORE_zone_iteration_stop (rd->iterating); | ||
606 | run_httpd_now (); | ||
607 | return; | ||
608 | } | ||
609 | |||
610 | GNUNET_NAMESTORE_zone_iterator_next (rd->iterating, 1); | ||
611 | } | ||
612 | |||
613 | |||
614 | /** | ||
615 | * All entries in the namestore have been iterated over. | ||
616 | * | ||
617 | * @param cls the connection | ||
618 | */ | ||
619 | static void | ||
620 | iterate_done_cb (void *cls) | ||
621 | { | ||
622 | struct RequestData *rd = cls; | ||
623 | |||
624 | rd->iterating = NULL; | ||
625 | |||
626 | /* See if the key was not registered already */ | ||
627 | rd->searching = GNUNET_NAMESTORE_zone_to_name (namestore, | ||
628 | zone_key, | ||
629 | &(rd->key), | ||
630 | ®ister_error_cb, | ||
631 | rd, | ||
632 | ®ister_do_cb, | ||
633 | rd); | ||
634 | } | ||
635 | |||
636 | |||
637 | /** | ||
638 | * Generate a response containing JSON and send it to the client. | ||
639 | * | ||
640 | * @param c the connection | ||
641 | * @param body the response body | ||
642 | * @param length the body length in bytes | ||
643 | * @param code the response code | ||
644 | * @return MHD_NO on error | ||
645 | */ | ||
646 | static MHD_RESULT | ||
647 | serve_json (struct MHD_Connection *c, | ||
648 | char *body, | ||
649 | size_t length, | ||
650 | int code) | ||
651 | { | ||
652 | struct MHD_Response *response = | ||
653 | MHD_create_response_from_buffer (length, | ||
654 | body, | ||
655 | MHD_RESPMEM_PERSISTENT); | ||
656 | MHD_RESULT r = MHD_queue_response (c, code, response); | ||
657 | MHD_destroy_response (response); | ||
658 | return r; | ||
659 | } | ||
660 | |||
661 | |||
662 | /** | ||
663 | * Send a response back to a connected client. | ||
664 | * | ||
665 | * @param cls unused | ||
666 | * @param connection the connection with the client | ||
667 | * @param url the requested address | ||
668 | * @param method the HTTP method used | ||
669 | * @param version the protocol version (including the "HTTP/" part) | ||
670 | * @param upload_data data sent with a POST request | ||
671 | * @param upload_data_size length in bytes of the POST data | ||
672 | * @param ptr used to pass data between request handling phases | ||
673 | * @return MHD_NO on error | ||
674 | */ | ||
675 | static MHD_RESULT | ||
676 | create_response (void *cls, | ||
677 | struct MHD_Connection *connection, | ||
678 | const char *url, | ||
679 | const char *method, | ||
680 | const char *version, | ||
681 | const char *upload_data, | ||
682 | size_t *upload_data_size, | ||
683 | void **ptr) | ||
684 | { | ||
685 | (void) cls; | ||
686 | (void) version; | ||
687 | |||
688 | struct RequestData *rd = *ptr; | ||
689 | |||
690 | if (0 == strcmp (method, MHD_HTTP_METHOD_GET)) | ||
691 | { | ||
692 | /* Handle a previously suspended request */ | ||
693 | if (NULL != rd) | ||
694 | { | ||
695 | return serve_json (rd->c, rd->body, rd->body_length, rd->code); | ||
696 | } | ||
697 | |||
698 | if (0 == strcmp ("/", url)) | ||
699 | { | ||
700 | return MHD_queue_response (connection, | ||
701 | MHD_HTTP_OK, | ||
702 | main_page->response); | ||
703 | } | ||
704 | |||
705 | if (0 == strcmp ("/search", url)) | ||
706 | { | ||
707 | const char *name = MHD_lookup_connection_value (connection, | ||
708 | MHD_GET_ARGUMENT_KIND, | ||
709 | "name"); | ||
710 | if (NULL == name) | ||
711 | { | ||
712 | return MHD_queue_response (connection, | ||
713 | MHD_HTTP_BAD_REQUEST, | ||
714 | forbidden_page->response); | ||
715 | } | ||
716 | |||
717 | MHD_suspend_connection (connection); | ||
718 | rd = GNUNET_new (struct RequestData); | ||
719 | rd->c = connection; | ||
720 | rd->searching = GNUNET_NAMESTORE_records_lookup (namestore, | ||
721 | zone_key, | ||
722 | name, | ||
723 | &search_error_cb, | ||
724 | rd, | ||
725 | &search_done_cb, | ||
726 | rd); | ||
727 | *ptr = rd; | ||
728 | return MHD_YES; | ||
729 | } | ||
730 | |||
731 | return MHD_queue_response (connection, | ||
732 | MHD_HTTP_NOT_FOUND, | ||
733 | notfound_page->response); | ||
734 | } | ||
735 | |||
736 | if (0 == strcmp (method, MHD_HTTP_METHOD_HEAD)) | ||
737 | { | ||
738 | /* We take a shortcut here by always serving the main page: starting a | ||
739 | namestore lookup, allocating the necessary resources, waiting for the | ||
740 | lookup to complete and then discard everything just because it was a HEAD | ||
741 | and thus only the headers are significative, is an unnecessary waste of | ||
742 | resources. The handling of this method could be smarter, for example by | ||
743 | sending a proper content type header based on the endpoint, but this is | ||
744 | not a service in which HEAD requests are significant, so there's no need | ||
745 | to spend too much time here. */ | ||
746 | return MHD_queue_response (connection, | ||
747 | MHD_HTTP_OK, | ||
748 | main_page->response); | ||
749 | } | ||
750 | |||
751 | if (0 == strcmp (method, MHD_HTTP_METHOD_POST)) | ||
752 | { | ||
753 | if (0 == strcmp ("/register", url)) | ||
754 | { | ||
755 | /* Handle a previously suspended request */ | ||
756 | if ((NULL != rd) && (NULL != rd->body)) | ||
757 | { | ||
758 | return serve_json (rd->c, rd->body, rd->body_length, rd->code); | ||
759 | } | ||
760 | |||
761 | if (NULL == rd) | ||
762 | { | ||
763 | rd = GNUNET_new (struct RequestData); | ||
764 | rd->c = connection; | ||
765 | rd->body = NULL; | ||
766 | rd->ptr = NULL; | ||
767 | *ptr = rd; | ||
768 | } | ||
769 | |||
770 | json_t *json = NULL; | ||
771 | enum GNUNET_JSON_PostResult result = | ||
772 | GNUNET_JSON_post_parser (32 * 1024, | ||
773 | connection, | ||
774 | &(rd->ptr), | ||
775 | upload_data, | ||
776 | upload_data_size, | ||
777 | &json); | ||
778 | |||
779 | switch (result) | ||
780 | { | ||
781 | case GNUNET_JSON_PR_CONTINUE: | ||
782 | /* Keep processing POST data */ | ||
783 | return MHD_YES; | ||
784 | case GNUNET_JSON_PR_OUT_OF_MEMORY: | ||
785 | case GNUNET_JSON_PR_REQUEST_TOO_LARGE: | ||
786 | rd->body = make_json ("error", "true", | ||
787 | "message", _ ("unable to process submitted data"), | ||
788 | NULL); | ||
789 | rd->body_length = strlen (rd->body); | ||
790 | #ifdef MHD_HTTP_CONTENT_TOO_LARGE | ||
791 | rd->code = MHD_HTTP_CONTENT_TOO_LARGE; | ||
792 | #else | ||
793 | rd->code = MHD_HTTP_PAYLOAD_TOO_LARGE; | ||
794 | #endif | ||
795 | return MHD_YES; | ||
796 | case GNUNET_JSON_PR_JSON_INVALID: | ||
797 | rd->body = make_json ("error", "true", | ||
798 | "message", _ ("the submitted data is invalid"), | ||
799 | NULL); | ||
800 | rd->body_length = strlen (rd->body); | ||
801 | rd->code = MHD_HTTP_BAD_REQUEST; | ||
802 | return MHD_YES; | ||
803 | default: | ||
804 | break; | ||
805 | } | ||
806 | |||
807 | /* POST data has been read in its entirety */ | ||
808 | |||
809 | const char *name = json_string_value (json_object_get (json, "name")); | ||
810 | const char *key = json_string_value (json_object_get (json, "key")); | ||
811 | if ((NULL == name) || (NULL == key) || (0 == strlen (name)) || (0 == | ||
812 | strlen ( | ||
813 | key))) | ||
814 | { | ||
815 | json_decref (json); | ||
816 | rd->body = make_json ("error", "true", | ||
817 | "message", _ ("invalid parameters"), | ||
818 | NULL); | ||
819 | rd->body_length = strlen (rd->body); | ||
820 | rd->code = MHD_HTTP_BAD_REQUEST; | ||
821 | return MHD_YES; | ||
822 | } | ||
823 | |||
824 | rd->register_name = strdup (name); | ||
825 | rd->register_key = strdup (key); | ||
826 | |||
827 | json_decref (json); | ||
828 | GNUNET_JSON_post_parser_cleanup (rd->ptr); | ||
829 | |||
830 | if ((NULL != strchr (rd->register_name, '.')) || | ||
831 | (NULL != strchr (rd->register_name, '+'))) | ||
832 | { | ||
833 | rd->body = make_json ("error", "true", | ||
834 | "message", _ ("invalid name"), | ||
835 | NULL); | ||
836 | rd->body_length = strlen (rd->body); | ||
837 | rd->code = MHD_HTTP_BAD_REQUEST; | ||
838 | return MHD_YES; | ||
839 | } | ||
840 | |||
841 | if (GNUNET_OK != GNUNET_CRYPTO_public_key_from_string (rd->register_key, | ||
842 | &(rd->key))) | ||
843 | { | ||
844 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, | ||
845 | _ ("Unable to parse key %s\n"), | ||
846 | rd->register_key); | ||
847 | |||
848 | rd->body = make_json ("error", "true", | ||
849 | "message", _ ("unable to parse key"), | ||
850 | NULL); | ||
851 | rd->body_length = strlen (rd->body); | ||
852 | rd->code = MHD_HTTP_INTERNAL_SERVER_ERROR; | ||
853 | return MHD_YES; | ||
854 | } | ||
855 | |||
856 | MHD_suspend_connection (connection); | ||
857 | /* See if the requested name is free */ | ||
858 | rd->iterating = | ||
859 | GNUNET_NAMESTORE_zone_iteration_start (namestore, | ||
860 | zone_key, | ||
861 | &iterate_error_cb, | ||
862 | rd, | ||
863 | &iterate_do_cb, | ||
864 | rd, | ||
865 | &iterate_done_cb, | ||
866 | rd); | ||
867 | return MHD_YES; | ||
868 | } | ||
869 | |||
870 | return MHD_queue_response (connection, | ||
871 | MHD_HTTP_FORBIDDEN, | ||
872 | forbidden_page->response); | ||
873 | } | ||
874 | |||
875 | return MHD_queue_response (connection, | ||
876 | MHD_HTTP_NOT_IMPLEMENTED, | ||
877 | forbidden_page->response); | ||
878 | } | ||
879 | |||
880 | |||
881 | /** | ||
882 | * Called when a request is completed. | ||
883 | * | ||
884 | * @param cls unused | ||
885 | * @param connection the connection | ||
886 | * @param ptr connection-specific data | ||
887 | * @param status status code | ||
888 | */ | ||
889 | static void | ||
890 | completed_cb (void *cls, | ||
891 | struct MHD_Connection *connection, | ||
892 | void **ptr, | ||
893 | enum MHD_RequestTerminationCode status) | ||
894 | { | ||
895 | (void) cls; | ||
896 | (void) connection; | ||
897 | (void) status; | ||
898 | |||
899 | struct RequestData *rd = *ptr; | ||
900 | |||
901 | if (NULL == rd) | ||
902 | { | ||
903 | return; | ||
904 | } | ||
905 | |||
906 | if (NULL == rd->body) | ||
907 | { | ||
908 | GNUNET_free (rd->body); | ||
909 | } | ||
910 | |||
911 | if (NULL != rd->searching) | ||
912 | { | ||
913 | GNUNET_NAMESTORE_cancel (rd->searching); | ||
914 | } | ||
915 | |||
916 | if (NULL != rd->register_name) | ||
917 | { | ||
918 | GNUNET_free (rd->register_name); | ||
919 | } | ||
920 | |||
921 | if (NULL != rd->register_key) | ||
922 | { | ||
923 | GNUNET_free (rd->register_key); | ||
924 | } | ||
925 | |||
926 | if (NULL != rd->iterating) | ||
927 | { | ||
928 | GNUNET_NAMESTORE_zone_iteration_stop (rd->iterating); | ||
929 | } | ||
930 | |||
931 | GNUNET_free (rd); | ||
932 | } | ||
933 | |||
934 | |||
935 | /** | ||
936 | * Called for each ego provided by the identity service. | ||
937 | * | ||
938 | * @param cls closure | ||
939 | * @param ego the ego | ||
940 | * @param ctx application-provided data for the ego | ||
941 | * @param name the ego name | ||
942 | */ | ||
943 | static void | ||
944 | identity_cb (void *cls, | ||
945 | struct GNUNET_IDENTITY_Ego *ego, | ||
946 | void **ctx, | ||
947 | const char *name) | ||
948 | { | ||
949 | (void) cls; | ||
950 | (void) ctx; | ||
951 | |||
952 | if ((NULL == name) || (0 != strcmp (name, zone))) | ||
953 | { | ||
954 | return; | ||
955 | } | ||
956 | |||
957 | if (NULL == ego) | ||
958 | { | ||
959 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
960 | _ ("No ego configured for `fcfsd` subsystem\n")); | ||
961 | GNUNET_SCHEDULER_shutdown (); | ||
962 | return; | ||
963 | } | ||
964 | |||
965 | zone_key = GNUNET_IDENTITY_ego_get_private_key (ego); | ||
966 | |||
967 | int flags = MHD_USE_DUAL_STACK | MHD_USE_DEBUG | MHD_ALLOW_SUSPEND_RESUME; | ||
968 | do | ||
969 | { | ||
970 | httpd = MHD_start_daemon (flags, | ||
971 | (uint16_t) port, | ||
972 | NULL, NULL, | ||
973 | &create_response, NULL, | ||
974 | MHD_OPTION_CONNECTION_LIMIT, 128, | ||
975 | MHD_OPTION_PER_IP_CONNECTION_LIMIT, 1, | ||
976 | MHD_OPTION_CONNECTION_TIMEOUT, 4 * 1024, | ||
977 | MHD_OPTION_NOTIFY_COMPLETED, &completed_cb, NULL, | ||
978 | MHD_OPTION_END); | ||
979 | flags = MHD_USE_DEBUG; | ||
980 | } while (NULL == httpd && flags != MHD_USE_DEBUG); | ||
981 | |||
982 | if (NULL == httpd) | ||
983 | { | ||
984 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
985 | _ ("Failed to start HTTP server\n")); | ||
986 | GNUNET_SCHEDULER_shutdown (); | ||
987 | return; | ||
988 | } | ||
989 | |||
990 | run_httpd (); | ||
991 | } | ||
992 | |||
993 | |||
994 | /** | ||
995 | * Open a file on disk and generate a response object for it. | ||
996 | * | ||
997 | * @param name name of the file to open | ||
998 | * @param basedir directory where the file is located | ||
999 | * @return NULL on error | ||
1000 | */ | ||
1001 | static struct StaticPage * | ||
1002 | open_static_page (const char *name, const char *basedir) | ||
1003 | { | ||
1004 | char *fullname = NULL; | ||
1005 | GNUNET_asprintf (&fullname, "%s/fcfsd-%s", basedir, name); | ||
1006 | |||
1007 | struct GNUNET_DISK_FileHandle *f = | ||
1008 | GNUNET_DISK_file_open (fullname, | ||
1009 | GNUNET_DISK_OPEN_READ, | ||
1010 | GNUNET_DISK_PERM_NONE); | ||
1011 | GNUNET_free (fullname); | ||
1012 | |||
1013 | if (NULL == f) | ||
1014 | { | ||
1015 | return NULL; | ||
1016 | } | ||
1017 | |||
1018 | off_t size = 0; | ||
1019 | if (GNUNET_SYSERR == GNUNET_DISK_file_handle_size (f, &size)) | ||
1020 | { | ||
1021 | GNUNET_DISK_file_close (f); | ||
1022 | return NULL; | ||
1023 | } | ||
1024 | |||
1025 | struct MHD_Response *response = | ||
1026 | MHD_create_response_from_fd64 (size, | ||
1027 | f->fd); | ||
1028 | |||
1029 | if (NULL == response) | ||
1030 | { | ||
1031 | GNUNET_DISK_file_close (f); | ||
1032 | return NULL; | ||
1033 | } | ||
1034 | |||
1035 | struct StaticPage *page = GNUNET_new (struct StaticPage); | ||
1036 | page->handle = f; | ||
1037 | page->size = (uint64_t) size; | ||
1038 | page->response = response; | ||
1039 | return page; | ||
1040 | } | ||
1041 | |||
1042 | |||
1043 | /** | ||
1044 | * Called after the service is up. | ||
1045 | * | ||
1046 | * @param cls closure | ||
1047 | * @param args remaining command line arguments | ||
1048 | * @param cfgfile name of the configuration file | ||
1049 | * @param cfg the service configuration | ||
1050 | */ | ||
1051 | static void | ||
1052 | run_service (void *cls, | ||
1053 | char *const *args, | ||
1054 | const char *cfgfile, | ||
1055 | const struct GNUNET_CONFIGURATION_Handle *cfg) | ||
1056 | { | ||
1057 | (void) cls; | ||
1058 | (void) args; | ||
1059 | (void) cfgfile; | ||
1060 | |||
1061 | GNUNET_log_setup ("fcfsd", "WARNING", NULL); | ||
1062 | |||
1063 | if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_time (cfg, | ||
1064 | "fcfsd", | ||
1065 | "RELATIVE_RECORD_EXPIRATION", | ||
1066 | &record_exp)) | ||
1067 | { | ||
1068 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, | ||
1069 | _("No expiration specified for records.\n")); | ||
1070 | GNUNET_SCHEDULER_shutdown (); | ||
1071 | return; | ||
1072 | } | ||
1073 | |||
1074 | if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_number (cfg, | ||
1075 | "fcfsd", | ||
1076 | "HTTPPORT", | ||
1077 | &port)) | ||
1078 | { | ||
1079 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, | ||
1080 | _ ("No port specified, using default value\n")); | ||
1081 | } | ||
1082 | |||
1083 | GNUNET_SCHEDULER_add_shutdown (&do_shutdown, NULL); | ||
1084 | |||
1085 | namestore = GNUNET_NAMESTORE_connect (cfg); | ||
1086 | if (NULL == namestore) | ||
1087 | { | ||
1088 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
1089 | _ ("Failed to connect to namestore\n")); | ||
1090 | GNUNET_SCHEDULER_shutdown (); | ||
1091 | return; | ||
1092 | } | ||
1093 | |||
1094 | identity = GNUNET_IDENTITY_connect (cfg, &identity_cb, NULL); | ||
1095 | if (NULL == identity) | ||
1096 | { | ||
1097 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
1098 | _ ("Failed to connect to identity\n")); | ||
1099 | GNUNET_SCHEDULER_shutdown (); | ||
1100 | return; | ||
1101 | } | ||
1102 | |||
1103 | char *basedir = NULL; | ||
1104 | if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_filename (cfg, | ||
1105 | "fcfsd", | ||
1106 | "HTMLDIR", | ||
1107 | &basedir)) | ||
1108 | { | ||
1109 | basedir = GNUNET_OS_installation_get_path (GNUNET_OS_IPK_DATADIR); | ||
1110 | } | ||
1111 | |||
1112 | main_page = open_static_page ("index.html", basedir); | ||
1113 | notfound_page = open_static_page ("notfound.html", basedir); | ||
1114 | forbidden_page = open_static_page ("forbidden.html", basedir); | ||
1115 | |||
1116 | GNUNET_free (basedir); | ||
1117 | |||
1118 | if ((NULL == main_page) || (NULL == notfound_page) || (NULL == | ||
1119 | forbidden_page) ) | ||
1120 | { | ||
1121 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
1122 | _ ("Unable to set up the daemon\n")); | ||
1123 | GNUNET_SCHEDULER_shutdown (); | ||
1124 | return; | ||
1125 | } | ||
1126 | } | ||
1127 | |||
1128 | |||
1129 | /** | ||
1130 | * The main function of the fcfs daemon. | ||
1131 | * | ||
1132 | * @param argc number of arguments from the command line | ||
1133 | * @param argv the command line arguments | ||
1134 | * @return 0 successful exit, a different value otherwise | ||
1135 | */ | ||
1136 | int | ||
1137 | main (int argc, char *const *argv) | ||
1138 | { | ||
1139 | struct GNUNET_GETOPT_CommandLineOption options[] = { | ||
1140 | GNUNET_GETOPT_option_mandatory | ||
1141 | (GNUNET_GETOPT_option_string ('z', | ||
1142 | "zone", | ||
1143 | "EGO", | ||
1144 | gettext_noop ( | ||
1145 | "name of the zone managed by FCFSD"), | ||
1146 | &zone)), | ||
1147 | GNUNET_GETOPT_OPTION_END | ||
1148 | }; | ||
1149 | |||
1150 | return ((GNUNET_OK == GNUNET_PROGRAM_run (argc, | ||
1151 | argv, | ||
1152 | "gnunet-namestore-fcfsd", | ||
1153 | _ ( | ||
1154 | "GNU Name System First-Come-First-Served name registration service"), | ||
1155 | options, | ||
1156 | &run_service, | ||
1157 | NULL)) ? | ||
1158 | 0 : | ||
1159 | 1); | ||
1160 | } | ||
diff --git a/src/namestore/gnunet-namestore-zonefile.c b/src/namestore/gnunet-namestore-zonefile.c deleted file mode 100644 index dfd438e94..000000000 --- a/src/namestore/gnunet-namestore-zonefile.c +++ /dev/null | |||
@@ -1,763 +0,0 @@ | |||
1 | /* | ||
2 | This file is part of GNUnet. | ||
3 | Copyright (C) 2012, 2013, 2014, 2019, 2022 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-dbtool.c | ||
22 | * @brief command line tool to manipulate the database backends for the namestore | ||
23 | * @author Martin Schanzenbach | ||
24 | * | ||
25 | */ | ||
26 | #include "platform.h" | ||
27 | #include <gnunet_util_lib.h> | ||
28 | #include <gnunet_namestore_plugin.h> | ||
29 | |||
30 | #define MAX_RECORDS_PER_NAME 50 | ||
31 | |||
32 | /** | ||
33 | * Maximum length of a zonefile line | ||
34 | */ | ||
35 | #define MAX_ZONEFILE_LINE_LEN 4096 | ||
36 | |||
37 | /** | ||
38 | * FIXME: Soft limit this? | ||
39 | */ | ||
40 | #define MAX_ZONEFILE_RECORD_DATA_LEN 2048 | ||
41 | |||
42 | /** | ||
43 | * The record data under a single label. Reused. | ||
44 | * Hard limit. | ||
45 | */ | ||
46 | static struct GNUNET_GNSRECORD_Data rd[MAX_RECORDS_PER_NAME]; | ||
47 | |||
48 | /** | ||
49 | * Current record $TTL to use | ||
50 | */ | ||
51 | static struct GNUNET_TIME_Relative ttl; | ||
52 | |||
53 | /** | ||
54 | * Current origin | ||
55 | */ | ||
56 | static char origin[GNUNET_DNSPARSER_MAX_NAME_LENGTH]; | ||
57 | |||
58 | /** | ||
59 | * Number of records for currently parsed set | ||
60 | */ | ||
61 | static unsigned int rd_count = 0; | ||
62 | |||
63 | /** | ||
64 | * Return code | ||
65 | */ | ||
66 | static int ret = 0; | ||
67 | |||
68 | /** | ||
69 | * Name of the ego | ||
70 | */ | ||
71 | static char *ego_name = NULL; | ||
72 | |||
73 | /** | ||
74 | * Currently read line or NULL on EOF | ||
75 | */ | ||
76 | static char *res; | ||
77 | |||
78 | /** | ||
79 | * Statistics, how many published record sets | ||
80 | */ | ||
81 | static unsigned int published_sets = 0; | ||
82 | |||
83 | /** | ||
84 | * Statistics, how many records published in aggregate | ||
85 | */ | ||
86 | static unsigned int published_records = 0; | ||
87 | |||
88 | |||
89 | /** | ||
90 | * Handle to identity lookup. | ||
91 | */ | ||
92 | static struct GNUNET_IDENTITY_EgoLookup *el; | ||
93 | |||
94 | /** | ||
95 | * Private key for the our zone. | ||
96 | */ | ||
97 | static struct GNUNET_CRYPTO_PrivateKey zone_pkey; | ||
98 | |||
99 | /** | ||
100 | * Queue entry for the 'add' operation. | ||
101 | */ | ||
102 | static struct GNUNET_NAMESTORE_QueueEntry *ns_qe; | ||
103 | |||
104 | /** | ||
105 | * Handle to the namestore. | ||
106 | */ | ||
107 | static struct GNUNET_NAMESTORE_Handle *ns; | ||
108 | |||
109 | /** | ||
110 | * Origin create operations | ||
111 | */ | ||
112 | static struct GNUNET_IDENTITY_Operation *id_op; | ||
113 | |||
114 | /** | ||
115 | * Handle to IDENTITY | ||
116 | */ | ||
117 | static struct GNUNET_IDENTITY_Handle *id; | ||
118 | |||
119 | /** | ||
120 | * Current configurataion | ||
121 | */ | ||
122 | static const struct GNUNET_CONFIGURATION_Handle *cfg; | ||
123 | |||
124 | /** | ||
125 | * Scheduled parse task | ||
126 | */ | ||
127 | static struct GNUNET_SCHEDULER_Task *parse_task; | ||
128 | |||
129 | /** | ||
130 | * The current state of the parser | ||
131 | */ | ||
132 | static int state; | ||
133 | |||
134 | enum ZonefileImportState | ||
135 | { | ||
136 | |||
137 | /* Uninitialized */ | ||
138 | ZS_READY, | ||
139 | |||
140 | /* The initial state */ | ||
141 | ZS_ORIGIN_SET, | ||
142 | |||
143 | /* The $ORIGIN has changed */ | ||
144 | ZS_ORIGIN_CHANGED, | ||
145 | |||
146 | /* The record name/label has changed */ | ||
147 | ZS_NAME_CHANGED | ||
148 | |||
149 | }; | ||
150 | |||
151 | |||
152 | |||
153 | /** | ||
154 | * Task run on shutdown. Cleans up everything. | ||
155 | * | ||
156 | * @param cls unused | ||
157 | */ | ||
158 | static void | ||
159 | do_shutdown (void *cls) | ||
160 | { | ||
161 | (void) cls; | ||
162 | if (NULL != ego_name) | ||
163 | GNUNET_free (ego_name); | ||
164 | if (NULL != el) | ||
165 | { | ||
166 | GNUNET_IDENTITY_ego_lookup_cancel (el); | ||
167 | el = NULL; | ||
168 | } | ||
169 | if (NULL != ns_qe) | ||
170 | GNUNET_NAMESTORE_cancel (ns_qe); | ||
171 | if (NULL != id_op) | ||
172 | GNUNET_IDENTITY_cancel (id_op); | ||
173 | if (NULL != ns) | ||
174 | GNUNET_NAMESTORE_disconnect (ns); | ||
175 | if (NULL != id) | ||
176 | GNUNET_IDENTITY_disconnect (id); | ||
177 | for (int i = 0; i < rd_count; i++) | ||
178 | { | ||
179 | void *rd_ptr = (void*) rd[i].data; | ||
180 | GNUNET_free (rd_ptr); | ||
181 | } | ||
182 | if (NULL != parse_task) | ||
183 | GNUNET_SCHEDULER_cancel (parse_task); | ||
184 | } | ||
185 | |||
186 | static void | ||
187 | tx_end (void *cls, enum GNUNET_ErrorCode ec) | ||
188 | { | ||
189 | ns_qe = NULL; | ||
190 | if (GNUNET_EC_NONE != ec) | ||
191 | { | ||
192 | fprintf (stderr, | ||
193 | _ ("Ego `%s' not known to identity service\n"), | ||
194 | ego_name); | ||
195 | GNUNET_SCHEDULER_shutdown (); | ||
196 | ret = -1; | ||
197 | } | ||
198 | GNUNET_SCHEDULER_shutdown (); | ||
199 | } | ||
200 | |||
201 | static void | ||
202 | parse (void *cls); | ||
203 | |||
204 | static char* | ||
205 | trim (char *line) | ||
206 | { | ||
207 | char *ltrimmed = line; | ||
208 | int ltrimmed_len; | ||
209 | int quoted = 0; | ||
210 | |||
211 | // Trim all whitespace to the left | ||
212 | while (*ltrimmed == ' ') | ||
213 | ltrimmed++; | ||
214 | ltrimmed_len = strlen (ltrimmed); | ||
215 | // Find the first occurence of an unqoted ';', which is our comment | ||
216 | for (int i = 0; i < ltrimmed_len; i++) | ||
217 | { | ||
218 | if (ltrimmed[i] == '"') | ||
219 | quoted = ! quoted; | ||
220 | if ((ltrimmed[i] != ';') || quoted) | ||
221 | continue; | ||
222 | ltrimmed[i] = '\0'; | ||
223 | } | ||
224 | ltrimmed_len = strlen (ltrimmed); | ||
225 | // Remove trailing whitespace | ||
226 | for (int i = ltrimmed_len; i > 0; i--) | ||
227 | { | ||
228 | if (ltrimmed[i - 1] != ' ') | ||
229 | break; | ||
230 | ltrimmed[i - 1] = '\0'; | ||
231 | } | ||
232 | ltrimmed_len = strlen (ltrimmed); | ||
233 | if (ltrimmed[ltrimmed_len - 1] == '\n') | ||
234 | ltrimmed[ltrimmed_len - 1] = ' '; | ||
235 | return ltrimmed; | ||
236 | } | ||
237 | |||
238 | static char* | ||
239 | next_token (char *token) | ||
240 | { | ||
241 | char *next = token; | ||
242 | while (*next == ' ') | ||
243 | next++; | ||
244 | return next; | ||
245 | } | ||
246 | |||
247 | static int | ||
248 | parse_ttl (char *token, struct GNUNET_TIME_Relative *ttl) | ||
249 | { | ||
250 | char *next; | ||
251 | unsigned int ttl_tmp; | ||
252 | |||
253 | next = strchr (token, ';'); | ||
254 | if (NULL != next) | ||
255 | next[0] = '\0'; | ||
256 | next = strchr (token, ' '); | ||
257 | if (NULL != next) | ||
258 | next[0] = '\0'; | ||
259 | if (1 != sscanf (token, "%u", &ttl_tmp)) | ||
260 | { | ||
261 | fprintf (stderr, "Unable to parse TTL `%s'\n", token); | ||
262 | return GNUNET_SYSERR; | ||
263 | } | ||
264 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "TTL is: %u\n", ttl_tmp); | ||
265 | ttl->rel_value_us = ttl_tmp * 1000 * 1000; | ||
266 | return GNUNET_OK; | ||
267 | } | ||
268 | |||
269 | static int | ||
270 | parse_origin (char *token, char *origin) | ||
271 | { | ||
272 | char *next; | ||
273 | next = strchr (token, ';'); | ||
274 | if (NULL != next) | ||
275 | next[0] = '\0'; | ||
276 | next = strchr (token, ' '); | ||
277 | if (NULL != next) | ||
278 | next[0] = '\0'; | ||
279 | strcpy (origin, token); | ||
280 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Origin is: %s\n", origin); | ||
281 | return GNUNET_OK; | ||
282 | } | ||
283 | |||
284 | static void | ||
285 | origin_create_cb (void *cls, const struct GNUNET_CRYPTO_PrivateKey *pk, | ||
286 | enum GNUNET_ErrorCode ec) | ||
287 | { | ||
288 | id_op = NULL; | ||
289 | if (GNUNET_EC_NONE != ec) | ||
290 | { | ||
291 | fprintf (stderr, "Error: %s\n", GNUNET_ErrorCode_get_hint (ec)); | ||
292 | ret = 1; | ||
293 | GNUNET_SCHEDULER_shutdown (); | ||
294 | return; | ||
295 | } | ||
296 | state = ZS_ORIGIN_SET; | ||
297 | zone_pkey = *pk; | ||
298 | parse_task = GNUNET_SCHEDULER_add_now (&parse, NULL); | ||
299 | } | ||
300 | |||
301 | static void | ||
302 | origin_lookup_cb (void *cls, struct GNUNET_IDENTITY_Ego *ego) | ||
303 | { | ||
304 | |||
305 | el = NULL; | ||
306 | |||
307 | if (NULL == ego) | ||
308 | { | ||
309 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
310 | "$ORIGIN %s does not exist, creating...\n", ego_name); | ||
311 | id_op = GNUNET_IDENTITY_create (id, ego_name, NULL, | ||
312 | GNUNET_PUBLIC_KEY_TYPE_ECDSA, // FIXME make configurable | ||
313 | origin_create_cb, | ||
314 | NULL); | ||
315 | return; | ||
316 | } | ||
317 | state = ZS_ORIGIN_SET; | ||
318 | zone_pkey = *GNUNET_IDENTITY_ego_get_private_key (ego); | ||
319 | parse_task = GNUNET_SCHEDULER_add_now (&parse, NULL); | ||
320 | } | ||
321 | |||
322 | static void | ||
323 | add_continuation (void *cls, enum GNUNET_ErrorCode ec) | ||
324 | { | ||
325 | ns_qe = NULL; | ||
326 | if (GNUNET_EC_NONE != ec) | ||
327 | { | ||
328 | fprintf (stderr, | ||
329 | _ ("Failed to store records...\n")); | ||
330 | GNUNET_SCHEDULER_shutdown (); | ||
331 | ret = -1; | ||
332 | } | ||
333 | if (ZS_ORIGIN_CHANGED == state) | ||
334 | { | ||
335 | if (NULL != ego_name) | ||
336 | GNUNET_free (ego_name); | ||
337 | ego_name = GNUNET_strdup (origin); | ||
338 | if (ego_name[strlen (ego_name) - 1] == '.') | ||
339 | ego_name[strlen (ego_name) - 1] = '\0'; | ||
340 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
341 | "Changing origin to %s\n", ego_name); | ||
342 | el = GNUNET_IDENTITY_ego_lookup (cfg, ego_name, | ||
343 | &origin_lookup_cb, NULL); | ||
344 | return; | ||
345 | } | ||
346 | parse_task = GNUNET_SCHEDULER_add_now (&parse, NULL); | ||
347 | } | ||
348 | |||
349 | |||
350 | |||
351 | /** | ||
352 | * Main function that will be run. | ||
353 | * | ||
354 | * TODO: | ||
355 | * - We must assume that names are not repeated later in the zonefile because | ||
356 | * our _store APIs are replacing. No sure if that is common in zonefiles. | ||
357 | * - We must only actually store a record set when the name to store changes or | ||
358 | * the end of the file is reached. | ||
359 | * that way we can group them and add (see above). | ||
360 | * - We need to hope our string formats are compatible, but seems ok. | ||
361 | * | ||
362 | * @param cls closure | ||
363 | * @param args remaining command-line arguments | ||
364 | * @param cfgfile name of the configuration file used (for saving, can be NULL!) | ||
365 | * @param cfg configuration | ||
366 | */ | ||
367 | static void | ||
368 | parse (void *cls) | ||
369 | { | ||
370 | char buf[MAX_ZONEFILE_LINE_LEN]; | ||
371 | char payload[MAX_ZONEFILE_RECORD_DATA_LEN]; | ||
372 | char *next; | ||
373 | char *token; | ||
374 | char *payload_pos; | ||
375 | static char lastname[GNUNET_DNSPARSER_MAX_LABEL_LENGTH]; | ||
376 | char newname[GNUNET_DNSPARSER_MAX_LABEL_LENGTH]; | ||
377 | void *data; | ||
378 | size_t data_size; | ||
379 | int ttl_line = 0; | ||
380 | int type; | ||
381 | int bracket_unclosed = 0; | ||
382 | int quoted = 0; | ||
383 | |||
384 | parse_task = NULL; | ||
385 | /* use filename provided as 1st argument (stdin by default) */ | ||
386 | int ln = 0; | ||
387 | while ((res = fgets (buf, sizeof(buf), stdin))) /* read each line of input */ | ||
388 | { | ||
389 | ln++; | ||
390 | ttl_line = 0; | ||
391 | token = trim (buf); | ||
392 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
393 | "Trimmed line (bracket %s): `%s'\n", | ||
394 | (bracket_unclosed > 0) ? "unclosed" : "closed", | ||
395 | token); | ||
396 | if ((0 == strlen (token)) || | ||
397 | ((1 == strlen (token)) && (' ' == *token))) | ||
398 | continue; // I guess we can safely ignore blank lines | ||
399 | if (bracket_unclosed == 0) | ||
400 | { | ||
401 | /* Payload is already parsed */ | ||
402 | payload_pos = payload; | ||
403 | /* Find space */ | ||
404 | next = strchr (token, ' '); | ||
405 | if (NULL == next) | ||
406 | { | ||
407 | fprintf (stderr, "Error at line %u: %s\n", ln, token); | ||
408 | ret = 1; | ||
409 | GNUNET_SCHEDULER_shutdown (); | ||
410 | return; | ||
411 | } | ||
412 | next[0] = '\0'; | ||
413 | next++; | ||
414 | if (0 == (strcmp (token, "$ORIGIN"))) | ||
415 | { | ||
416 | state = ZS_ORIGIN_CHANGED; | ||
417 | token = next_token (next); | ||
418 | } | ||
419 | else if (0 == (strcmp (token, "$TTL"))) | ||
420 | { | ||
421 | ttl_line = 1; | ||
422 | token = next_token (next); | ||
423 | } | ||
424 | else | ||
425 | { | ||
426 | if (0 == strcmp (token, "IN")) // Inherit name from before | ||
427 | { | ||
428 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
429 | "Old name: %s\n", lastname); | ||
430 | strcpy (newname, lastname); | ||
431 | token[strlen (token)] = ' '; | ||
432 | } | ||
433 | else if (token[strlen (token) - 1] != '.') // no fqdn | ||
434 | { | ||
435 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "New name: %s\n", token); | ||
436 | if (GNUNET_DNSPARSER_MAX_LABEL_LENGTH < strlen (token)) | ||
437 | { | ||
438 | fprintf (stderr, | ||
439 | _ ("Name `%s' is too long\n"), | ||
440 | token); | ||
441 | ret = 1; | ||
442 | GNUNET_SCHEDULER_shutdown (); | ||
443 | return; | ||
444 | } | ||
445 | strcpy (newname, token); | ||
446 | token = next_token (next); | ||
447 | } | ||
448 | else if (0 == strcmp (token, origin)) | ||
449 | { | ||
450 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "New name: @\n"); | ||
451 | strcpy (newname, "@"); | ||
452 | token = next_token (next); | ||
453 | } | ||
454 | else | ||
455 | { | ||
456 | if (strlen (token) < strlen (origin)) | ||
457 | { | ||
458 | fprintf (stderr, "Wrong origin: %s (expected %s)\n", token, origin); | ||
459 | break; // FIXME error? | ||
460 | } | ||
461 | if (0 != strcmp (token + (strlen (token) - strlen (origin)), origin)) | ||
462 | { | ||
463 | fprintf (stderr, "Wrong origin: %s (expected %s)\n", token, origin); | ||
464 | break; | ||
465 | } | ||
466 | token[strlen (token) - strlen (origin) - 1] = '\0'; | ||
467 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "New name: %s\n", token); | ||
468 | if (GNUNET_DNSPARSER_MAX_LABEL_LENGTH < strlen (token)) | ||
469 | { | ||
470 | fprintf (stderr, | ||
471 | _ ("Name `%s' is too long\n"), | ||
472 | token); | ||
473 | ret = 1; | ||
474 | GNUNET_SCHEDULER_shutdown (); | ||
475 | return; | ||
476 | } | ||
477 | strcpy (newname, token); | ||
478 | token = next_token (next); | ||
479 | } | ||
480 | if (0 != strcmp (newname, lastname) && | ||
481 | (0 < rd_count)) | ||
482 | { | ||
483 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
484 | "Name changed %s->%s, storing record set of %u elements\n", | ||
485 | lastname, newname, | ||
486 | rd_count); | ||
487 | state = ZS_NAME_CHANGED; | ||
488 | } | ||
489 | else { | ||
490 | strcpy (lastname, newname); | ||
491 | } | ||
492 | } | ||
493 | |||
494 | if (ttl_line) | ||
495 | { | ||
496 | if (GNUNET_SYSERR == parse_ttl (token, &ttl)) | ||
497 | { | ||
498 | fprintf (stderr, _ ("Failed to parse $TTL\n")); | ||
499 | ret = 1; | ||
500 | GNUNET_SCHEDULER_shutdown (); | ||
501 | return; | ||
502 | } | ||
503 | continue; | ||
504 | } | ||
505 | if (ZS_ORIGIN_CHANGED == state) | ||
506 | { | ||
507 | if (GNUNET_SYSERR == parse_origin (token, origin)) | ||
508 | { | ||
509 | fprintf (stderr, _ ("Failed to parse $ORIGIN from %s\n"), token); | ||
510 | ret = 1; | ||
511 | GNUNET_SCHEDULER_shutdown (); | ||
512 | return; | ||
513 | } | ||
514 | break; | ||
515 | } | ||
516 | if (ZS_READY == state) | ||
517 | { | ||
518 | fprintf (stderr, | ||
519 | _ ( | ||
520 | "You must provide $ORIGIN in your zonefile or via arguments (--zone)!\n")); | ||
521 | ret = 1; | ||
522 | GNUNET_SCHEDULER_shutdown (); | ||
523 | return; | ||
524 | } | ||
525 | // This is a record, let's go | ||
526 | if (MAX_RECORDS_PER_NAME == rd_count) | ||
527 | { | ||
528 | fprintf (stderr, | ||
529 | _ ("Only %u records per unique name supported.\n"), | ||
530 | MAX_RECORDS_PER_NAME); | ||
531 | ret = 1; | ||
532 | GNUNET_SCHEDULER_shutdown (); | ||
533 | return; | ||
534 | } | ||
535 | rd[rd_count].flags = GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION; | ||
536 | rd[rd_count].expiration_time = ttl.rel_value_us; | ||
537 | next = strchr (token, ' '); | ||
538 | if (NULL == next) | ||
539 | { | ||
540 | fprintf (stderr, "Error, last token: %s\n", token); | ||
541 | ret = 1; | ||
542 | GNUNET_SCHEDULER_shutdown (); | ||
543 | break; | ||
544 | } | ||
545 | next[0] = '\0'; | ||
546 | next++; | ||
547 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "class is: %s\n", token); | ||
548 | while (*next == ' ') | ||
549 | next++; | ||
550 | token = next; | ||
551 | next = strchr (token, ' '); | ||
552 | if (NULL == next) | ||
553 | { | ||
554 | fprintf (stderr, "Error\n"); | ||
555 | break; | ||
556 | } | ||
557 | next[0] = '\0'; | ||
558 | next++; | ||
559 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "type is: %s\n", token); | ||
560 | type = GNUNET_GNSRECORD_typename_to_number (token); | ||
561 | rd[rd_count].record_type = type; | ||
562 | while (*next == ' ') | ||
563 | next++; | ||
564 | token = next; | ||
565 | } | ||
566 | for (int i = 0; i < strlen (token); i++) | ||
567 | { | ||
568 | if (token[i] == '"') | ||
569 | quoted = ! quoted; | ||
570 | if ((token[i] == '(') && ! quoted) | ||
571 | bracket_unclosed++; | ||
572 | if ((token[i] == ')') && ! quoted) | ||
573 | bracket_unclosed--; | ||
574 | } | ||
575 | memcpy (payload_pos, token, strlen (token)); | ||
576 | payload_pos += strlen (token); | ||
577 | if (bracket_unclosed > 0) | ||
578 | { | ||
579 | *payload_pos = ' '; | ||
580 | payload_pos++; | ||
581 | continue; | ||
582 | } | ||
583 | *payload_pos = '\0'; | ||
584 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "data is: %s\n\n", payload); | ||
585 | if (GNUNET_OK != | ||
586 | GNUNET_GNSRECORD_string_to_value (type, payload, | ||
587 | &data, | ||
588 | &data_size)) | ||
589 | { | ||
590 | fprintf (stderr, | ||
591 | _ ("Data `%s' invalid\n"), | ||
592 | payload); | ||
593 | ret = 1; | ||
594 | GNUNET_SCHEDULER_shutdown (); | ||
595 | return; | ||
596 | } | ||
597 | rd[rd_count].data = data; | ||
598 | rd[rd_count].data_size = data_size; | ||
599 | if (ZS_NAME_CHANGED == state) | ||
600 | break; | ||
601 | rd_count++; | ||
602 | } | ||
603 | if (rd_count > 0) | ||
604 | { | ||
605 | ns_qe = GNUNET_NAMESTORE_records_store (ns, | ||
606 | &zone_pkey, | ||
607 | lastname, | ||
608 | rd_count, | ||
609 | rd, | ||
610 | &add_continuation, | ||
611 | NULL); | ||
612 | published_sets++; | ||
613 | published_records += rd_count; | ||
614 | for (int i = 0; i < rd_count; i++) | ||
615 | { | ||
616 | data = (void*) rd[i].data; | ||
617 | GNUNET_free (data); | ||
618 | } | ||
619 | if (ZS_NAME_CHANGED == state) | ||
620 | { | ||
621 | rd[0] = rd[rd_count]; // recover last rd parsed. | ||
622 | rd_count = 1; | ||
623 | strcpy (lastname, newname); | ||
624 | state = ZS_ORIGIN_SET; | ||
625 | } | ||
626 | else | ||
627 | rd_count = 0; | ||
628 | return; | ||
629 | } | ||
630 | if (ZS_ORIGIN_CHANGED == state) | ||
631 | { | ||
632 | if (NULL != ego_name) | ||
633 | GNUNET_free (ego_name); | ||
634 | ego_name = GNUNET_strdup (origin); | ||
635 | if (ego_name[strlen (ego_name) - 1] == '.') | ||
636 | ego_name[strlen (ego_name) - 1] = '\0'; | ||
637 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
638 | "Changing origin to %s\n", ego_name); | ||
639 | el = GNUNET_IDENTITY_ego_lookup (cfg, ego_name, | ||
640 | &origin_lookup_cb, NULL); | ||
641 | return; | ||
642 | } | ||
643 | printf ("Published %u records sets with total %u records\n", | ||
644 | published_sets, published_records); | ||
645 | ns_qe = GNUNET_NAMESTORE_transaction_commit (ns, | ||
646 | &tx_end, | ||
647 | NULL); | ||
648 | } | ||
649 | |||
650 | static void | ||
651 | tx_start (void *cls, enum GNUNET_ErrorCode ec) | ||
652 | { | ||
653 | ns_qe = NULL; | ||
654 | if (GNUNET_EC_NONE != ec) | ||
655 | { | ||
656 | fprintf (stderr, | ||
657 | _ ("Ego `%s' not known to identity service\n"), | ||
658 | ego_name); | ||
659 | GNUNET_SCHEDULER_shutdown (); | ||
660 | ret = -1; | ||
661 | return; | ||
662 | } | ||
663 | parse_task = GNUNET_SCHEDULER_add_now (&parse, NULL); | ||
664 | } | ||
665 | |||
666 | static void | ||
667 | identity_cb (void *cls, struct GNUNET_IDENTITY_Ego *ego) | ||
668 | { | ||
669 | |||
670 | el = NULL; | ||
671 | if (NULL == ego) | ||
672 | { | ||
673 | if (NULL != ego_name) | ||
674 | { | ||
675 | fprintf (stderr, | ||
676 | _ ("Ego `%s' not known to identity service\n"), | ||
677 | ego_name); | ||
678 | |||
679 | } | ||
680 | GNUNET_SCHEDULER_shutdown (); | ||
681 | ret = -1; | ||
682 | return; | ||
683 | } | ||
684 | zone_pkey = *GNUNET_IDENTITY_ego_get_private_key (ego); | ||
685 | sprintf (origin, "%s.", ego_name); | ||
686 | state = ZS_ORIGIN_SET; | ||
687 | ns_qe = GNUNET_NAMESTORE_transaction_begin (ns, | ||
688 | &tx_start, | ||
689 | NULL); | ||
690 | } | ||
691 | |||
692 | |||
693 | static void | ||
694 | run (void *cls, | ||
695 | char *const *args, | ||
696 | const char *cfgfile, | ||
697 | const struct GNUNET_CONFIGURATION_Handle *_cfg) | ||
698 | { | ||
699 | cfg = _cfg; | ||
700 | ns = GNUNET_NAMESTORE_connect (cfg); | ||
701 | GNUNET_SCHEDULER_add_shutdown (&do_shutdown, (void *) cfg); | ||
702 | if (NULL == ns) | ||
703 | { | ||
704 | fprintf (stderr, | ||
705 | _ ("Failed to connect to NAMESTORE\n")); | ||
706 | return; | ||
707 | } | ||
708 | id = GNUNET_IDENTITY_connect (cfg, NULL, NULL); | ||
709 | if (NULL == id) | ||
710 | { | ||
711 | fprintf (stderr, | ||
712 | _ ("Failed to connect to IDENTITY\n")); | ||
713 | return; | ||
714 | } | ||
715 | if (NULL != ego_name) | ||
716 | el = GNUNET_IDENTITY_ego_lookup (cfg, ego_name, &identity_cb, (void *) cfg); | ||
717 | else | ||
718 | parse_task = GNUNET_SCHEDULER_add_now (&parse, NULL); | ||
719 | state = ZS_READY; | ||
720 | } | ||
721 | |||
722 | |||
723 | /** | ||
724 | * The main function for gnunet-namestore-dbtool. | ||
725 | * | ||
726 | * @param argc number of arguments from the command line | ||
727 | * @param argv command line arguments | ||
728 | * @return 0 ok, 1 on error | ||
729 | */ | ||
730 | int | ||
731 | main (int argc, char *const *argv) | ||
732 | { | ||
733 | struct GNUNET_GETOPT_CommandLineOption options[] = { | ||
734 | GNUNET_GETOPT_option_string ('z', | ||
735 | "zone", | ||
736 | "EGO", | ||
737 | gettext_noop ( | ||
738 | "name of the ego controlling the zone"), | ||
739 | &ego_name), | ||
740 | GNUNET_GETOPT_OPTION_END | ||
741 | }; | ||
742 | int lret; | ||
743 | |||
744 | if (GNUNET_OK != GNUNET_STRINGS_get_utf8_args (argc, argv, &argc, &argv)) | ||
745 | return 2; | ||
746 | |||
747 | GNUNET_log_setup ("gnunet-namestore-dbtool", "WARNING", NULL); | ||
748 | if (GNUNET_OK != | ||
749 | (lret = GNUNET_PROGRAM_run (argc, | ||
750 | argv, | ||
751 | "gnunet-namestore-zonefile", | ||
752 | _ ( | ||
753 | "GNUnet namestore database manipulation tool"), | ||
754 | options, | ||
755 | &run, | ||
756 | NULL))) | ||
757 | { | ||
758 | GNUNET_free_nz ((void *) argv); | ||
759 | return lret; | ||
760 | } | ||
761 | GNUNET_free_nz ((void *) argv); | ||
762 | return ret; | ||
763 | } | ||
diff --git a/src/namestore/gnunet-namestore.c b/src/namestore/gnunet-namestore.c deleted file mode 100644 index baa036ac7..000000000 --- a/src/namestore/gnunet-namestore.c +++ /dev/null | |||
@@ -1,2120 +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_identity_service.h> | ||
31 | #include <gnunet_gnsrecord_lib.h> | ||
32 | #include <gnunet_gns_service.h> | ||
33 | #include <gnunet_namestore_service.h> | ||
34 | #include <inttypes.h> | ||
35 | |||
36 | /** | ||
37 | * The upper bound for the zone iteration interval | ||
38 | * (per record). | ||
39 | */ | ||
40 | #define WARN_RELATIVE_EXPIRATION_LIMIT GNUNET_TIME_relative_multiply ( \ | ||
41 | GNUNET_TIME_UNIT_MINUTES, 15) | ||
42 | |||
43 | /** | ||
44 | * Entry in record set for bulk processing. | ||
45 | */ | ||
46 | struct RecordSetEntry | ||
47 | { | ||
48 | /** | ||
49 | * Kept in a linked list. | ||
50 | */ | ||
51 | struct RecordSetEntry *next; | ||
52 | |||
53 | /** | ||
54 | * The record to add/remove. | ||
55 | */ | ||
56 | struct GNUNET_GNSRECORD_Data record; | ||
57 | }; | ||
58 | |||
59 | /** | ||
60 | * The record marked for deletion | ||
61 | */ | ||
62 | struct MarkedRecord | ||
63 | { | ||
64 | /** | ||
65 | * DLL | ||
66 | */ | ||
67 | struct MarkedRecord *next; | ||
68 | |||
69 | /** | ||
70 | * DLL | ||
71 | */ | ||
72 | struct MarkedRecord *prev; | ||
73 | |||
74 | /** | ||
75 | * Ego Identifier | ||
76 | */ | ||
77 | char *name; | ||
78 | |||
79 | /** | ||
80 | * The zone key | ||
81 | */ | ||
82 | struct GNUNET_CRYPTO_PrivateKey key; | ||
83 | }; | ||
84 | |||
85 | /** | ||
86 | * The default namestore ego | ||
87 | */ | ||
88 | struct EgoEntry | ||
89 | { | ||
90 | /** | ||
91 | * DLL | ||
92 | */ | ||
93 | struct EgoEntry *next; | ||
94 | |||
95 | /** | ||
96 | * DLL | ||
97 | */ | ||
98 | struct EgoEntry *prev; | ||
99 | |||
100 | /** | ||
101 | * Ego Identifier | ||
102 | */ | ||
103 | char *identifier; | ||
104 | |||
105 | /** | ||
106 | * The Ego | ||
107 | */ | ||
108 | struct GNUNET_IDENTITY_Ego *ego; | ||
109 | }; | ||
110 | |||
111 | /** | ||
112 | * Handle to the namestore. | ||
113 | */ | ||
114 | static struct GNUNET_NAMESTORE_Handle *ns; | ||
115 | |||
116 | /** | ||
117 | * Private key for the our zone. | ||
118 | */ | ||
119 | static struct GNUNET_CRYPTO_PrivateKey zone_pkey; | ||
120 | |||
121 | /** | ||
122 | * Identity service handle | ||
123 | */ | ||
124 | static struct GNUNET_IDENTITY_Handle *idh; | ||
125 | |||
126 | /** | ||
127 | * Name of the ego controlling the zone. | ||
128 | */ | ||
129 | static char *ego_name; | ||
130 | |||
131 | /** | ||
132 | * Queue entry for the 'add-uri' operation. | ||
133 | */ | ||
134 | static struct GNUNET_NAMESTORE_QueueEntry *add_qe_uri; | ||
135 | |||
136 | /** | ||
137 | * Queue entry for the 'add' operation. | ||
138 | */ | ||
139 | static struct GNUNET_NAMESTORE_QueueEntry *add_qe; | ||
140 | |||
141 | /** | ||
142 | * Queue entry for the 'lookup' operation. | ||
143 | */ | ||
144 | static struct GNUNET_NAMESTORE_QueueEntry *get_qe; | ||
145 | |||
146 | /** | ||
147 | * Queue entry for the 'reverse lookup' operation (in combination with a name). | ||
148 | */ | ||
149 | static struct GNUNET_NAMESTORE_QueueEntry *reverse_qe; | ||
150 | |||
151 | /** | ||
152 | * Marked record list | ||
153 | */ | ||
154 | static struct MarkedRecord *marked_head; | ||
155 | |||
156 | /** | ||
157 | * Marked record list | ||
158 | */ | ||
159 | static struct MarkedRecord *marked_tail; | ||
160 | |||
161 | /** | ||
162 | * Configuration handle | ||
163 | */ | ||
164 | const struct GNUNET_CONFIGURATION_Handle *cfg; | ||
165 | |||
166 | /** | ||
167 | * Ego list | ||
168 | */ | ||
169 | static struct EgoEntry *ego_head; | ||
170 | |||
171 | /** | ||
172 | * Ego list | ||
173 | */ | ||
174 | static struct EgoEntry *ego_tail; | ||
175 | |||
176 | /** | ||
177 | * List iterator for the 'list' operation. | ||
178 | */ | ||
179 | static struct GNUNET_NAMESTORE_ZoneIterator *list_it; | ||
180 | |||
181 | /** | ||
182 | * Run in read from stdin mode. | ||
183 | */ | ||
184 | static int read_from_stdin; | ||
185 | |||
186 | /** | ||
187 | * Desired action is to list records. | ||
188 | */ | ||
189 | static int list; | ||
190 | |||
191 | /** | ||
192 | * Desired action is to add a record. | ||
193 | */ | ||
194 | static int add; | ||
195 | |||
196 | /** | ||
197 | * Desired action is to remove a record. | ||
198 | */ | ||
199 | static int del; | ||
200 | |||
201 | /** | ||
202 | * Is record public (opposite of #GNUNET_GNSRECORD_RF_PRIVATE) | ||
203 | */ | ||
204 | static int is_public; | ||
205 | |||
206 | /** | ||
207 | * Is record a shadow record (#GNUNET_GNSRECORD_RF_SHADOW) | ||
208 | */ | ||
209 | static int is_shadow; | ||
210 | |||
211 | /** | ||
212 | * Filter private records | ||
213 | */ | ||
214 | static int omit_private; | ||
215 | |||
216 | /** | ||
217 | * Output in recordline format | ||
218 | */ | ||
219 | static int output_recordline; | ||
220 | |||
221 | |||
222 | /** | ||
223 | * Purge zone contents | ||
224 | */ | ||
225 | static int purge_zone; | ||
226 | |||
227 | /** | ||
228 | * Do not filter maintenance records | ||
229 | */ | ||
230 | static int include_maintenance; | ||
231 | |||
232 | /** | ||
233 | * Purge orphaned records | ||
234 | */ | ||
235 | static int purge_orphaned; | ||
236 | |||
237 | /** | ||
238 | * List records and zone keys of orphaned records | ||
239 | */ | ||
240 | static int list_orphaned; | ||
241 | |||
242 | /** | ||
243 | * Queue entry for the 'del' operation. | ||
244 | */ | ||
245 | static struct GNUNET_NAMESTORE_QueueEntry *del_qe; | ||
246 | |||
247 | /** | ||
248 | * Queue entry for the 'set/replace' operation. | ||
249 | */ | ||
250 | static struct GNUNET_NAMESTORE_QueueEntry *set_qe; | ||
251 | |||
252 | /** | ||
253 | * Queue entry for begin/commit | ||
254 | */ | ||
255 | static struct GNUNET_NAMESTORE_QueueEntry *ns_qe; | ||
256 | |||
257 | /** | ||
258 | * Name of the records to add/list/remove. | ||
259 | */ | ||
260 | static char *name; | ||
261 | |||
262 | /** | ||
263 | * Value of the record to add/remove. | ||
264 | */ | ||
265 | static char *value; | ||
266 | |||
267 | /** | ||
268 | * URI to import. | ||
269 | */ | ||
270 | static char *uri; | ||
271 | |||
272 | /** | ||
273 | * Reverse lookup to perform. | ||
274 | */ | ||
275 | static char *reverse_pkey; | ||
276 | |||
277 | /** | ||
278 | * Type of the record to add/remove, NULL to remove all. | ||
279 | */ | ||
280 | static char *typestring; | ||
281 | |||
282 | /** | ||
283 | * Desired expiration time. | ||
284 | */ | ||
285 | static char *expirationstring; | ||
286 | |||
287 | /** | ||
288 | * Desired nick name. | ||
289 | */ | ||
290 | static char *nickstring; | ||
291 | |||
292 | /** | ||
293 | * Global return value | ||
294 | */ | ||
295 | static int ret; | ||
296 | |||
297 | /** | ||
298 | * Type string converted to DNS type value. | ||
299 | */ | ||
300 | static uint32_t type; | ||
301 | |||
302 | /** | ||
303 | * Value in binary format. | ||
304 | */ | ||
305 | static void *data; | ||
306 | |||
307 | /** | ||
308 | * Number of bytes in #data. | ||
309 | */ | ||
310 | static size_t data_size; | ||
311 | |||
312 | /** | ||
313 | * Expiration string converted to numeric value. | ||
314 | */ | ||
315 | static uint64_t etime; | ||
316 | |||
317 | /** | ||
318 | * Is expiration time relative or absolute time? | ||
319 | */ | ||
320 | static int etime_is_rel = GNUNET_SYSERR; | ||
321 | |||
322 | /** | ||
323 | * Monitor handle. | ||
324 | */ | ||
325 | static struct GNUNET_NAMESTORE_ZoneMonitor *zm; | ||
326 | |||
327 | /** | ||
328 | * Enables monitor mode. | ||
329 | */ | ||
330 | static int monitor; | ||
331 | |||
332 | /** | ||
333 | * Entry in record set for processing records in bulk. | ||
334 | */ | ||
335 | static struct RecordSetEntry *recordset; | ||
336 | |||
337 | /** | ||
338 | * Purge task | ||
339 | */ | ||
340 | static struct GNUNET_SCHEDULER_Task *purge_task; | ||
341 | |||
342 | /** | ||
343 | * Parse expiration time. | ||
344 | * | ||
345 | * @param expirationstring text to parse | ||
346 | * @param[out] etime_is_rel set to #GNUNET_YES if time is relative | ||
347 | * @param[out] etime set to expiration time (abs or rel) | ||
348 | * @return #GNUNET_OK on success | ||
349 | */ | ||
350 | static int | ||
351 | parse_expiration (const char *expirationstring, | ||
352 | int *etime_is_rel, | ||
353 | uint64_t *etime) | ||
354 | { | ||
355 | struct GNUNET_TIME_Relative etime_rel; | ||
356 | struct GNUNET_TIME_Absolute etime_abs; | ||
357 | |||
358 | if (0 == strcmp (expirationstring, "never")) | ||
359 | { | ||
360 | *etime = GNUNET_TIME_UNIT_FOREVER_ABS.abs_value_us; | ||
361 | *etime_is_rel = GNUNET_NO; | ||
362 | return GNUNET_OK; | ||
363 | } | ||
364 | if (GNUNET_OK == | ||
365 | GNUNET_STRINGS_fancy_time_to_relative (expirationstring, &etime_rel)) | ||
366 | { | ||
367 | *etime_is_rel = GNUNET_YES; | ||
368 | *etime = etime_rel.rel_value_us; | ||
369 | if (GNUNET_TIME_relative_cmp (etime_rel, <, WARN_RELATIVE_EXPIRATION_LIMIT)) | ||
370 | { | ||
371 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, | ||
372 | "Relative expiration times of less than %s are not recommended. To improve availability, consider increasing this value.\n", | ||
373 | GNUNET_STRINGS_relative_time_to_string ( | ||
374 | WARN_RELATIVE_EXPIRATION_LIMIT, GNUNET_NO)); | ||
375 | } | ||
376 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
377 | "Storing record with relative expiration time of %s\n", | ||
378 | GNUNET_STRINGS_relative_time_to_string (etime_rel, GNUNET_NO)); | ||
379 | return GNUNET_OK; | ||
380 | } | ||
381 | if (GNUNET_OK == | ||
382 | GNUNET_STRINGS_fancy_time_to_absolute (expirationstring, &etime_abs)) | ||
383 | { | ||
384 | *etime_is_rel = GNUNET_NO; | ||
385 | *etime = etime_abs.abs_value_us; | ||
386 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
387 | "Storing record with absolute expiration time of %s\n", | ||
388 | GNUNET_STRINGS_absolute_time_to_string (etime_abs)); | ||
389 | return GNUNET_OK; | ||
390 | } | ||
391 | return GNUNET_SYSERR; | ||
392 | } | ||
393 | |||
394 | |||
395 | static int | ||
396 | parse_recordline (const char *line) | ||
397 | { | ||
398 | struct RecordSetEntry **head = &recordset; | ||
399 | struct RecordSetEntry *r; | ||
400 | struct GNUNET_GNSRECORD_Data record; | ||
401 | char *cp; | ||
402 | char *tok; | ||
403 | char *saveptr; | ||
404 | void *raw_data; | ||
405 | |||
406 | cp = GNUNET_strdup (line); | ||
407 | tok = strtok_r (cp, " ", &saveptr); | ||
408 | if (NULL == tok) | ||
409 | { | ||
410 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
411 | _ ("Missing entries in record line `%s'.\n"), | ||
412 | line); | ||
413 | GNUNET_free (cp); | ||
414 | return GNUNET_SYSERR; | ||
415 | } | ||
416 | record.record_type = GNUNET_GNSRECORD_typename_to_number (tok); | ||
417 | if (UINT32_MAX == record.record_type) | ||
418 | { | ||
419 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _ ("Unknown record type `%s'\n"), tok); | ||
420 | GNUNET_free (cp); | ||
421 | return GNUNET_SYSERR; | ||
422 | } | ||
423 | tok = strtok_r (NULL, " ", &saveptr); | ||
424 | if (NULL == tok) | ||
425 | { | ||
426 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
427 | _ ("Empty record line argument is not allowed.\n")); | ||
428 | GNUNET_free (cp); | ||
429 | return GNUNET_SYSERR; | ||
430 | } | ||
431 | if (1 != sscanf (tok, "%" SCNu64, &record.expiration_time)) | ||
432 | { | ||
433 | fprintf (stderr, | ||
434 | _ ("Error parsing expiration time %s.\n"), tok); | ||
435 | GNUNET_free (cp); | ||
436 | return GNUNET_SYSERR; | ||
437 | } | ||
438 | tok = strtok_r (NULL, " ", &saveptr); | ||
439 | if (NULL == tok) | ||
440 | { | ||
441 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
442 | _ ("Empty record line argument is not allowed.\n")); | ||
443 | GNUNET_free (cp); | ||
444 | return GNUNET_SYSERR; | ||
445 | } | ||
446 | record.flags = GNUNET_GNSRECORD_RF_NONE; | ||
447 | if (NULL != strchr (tok, (unsigned char) 'r')) | ||
448 | record.flags |= GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION; | ||
449 | if (NULL == strchr (tok, (unsigned char) 'p')) /* p = public */ | ||
450 | record.flags |= GNUNET_GNSRECORD_RF_PRIVATE; | ||
451 | if (NULL != strchr (tok, (unsigned char) 'S')) | ||
452 | record.flags |= GNUNET_GNSRECORD_RF_SUPPLEMENTAL; | ||
453 | if (NULL != strchr (tok, (unsigned char) 's')) | ||
454 | record.flags |= GNUNET_GNSRECORD_RF_SHADOW; | ||
455 | if (NULL != strchr (tok, (unsigned char) 'C')) | ||
456 | record.flags |= GNUNET_GNSRECORD_RF_CRITICAL; | ||
457 | tok += strlen (tok) + 1; | ||
458 | if (GNUNET_OK != GNUNET_GNSRECORD_string_to_value (record.record_type, | ||
459 | tok, | ||
460 | &raw_data, | ||
461 | &record.data_size)) | ||
462 | { | ||
463 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
464 | _ ("Invalid record data for type %s: `%s'.\n"), | ||
465 | GNUNET_GNSRECORD_number_to_typename (record.record_type), | ||
466 | tok); | ||
467 | GNUNET_free (cp); | ||
468 | return GNUNET_SYSERR; | ||
469 | } | ||
470 | GNUNET_free (cp); | ||
471 | |||
472 | r = GNUNET_malloc (sizeof(struct RecordSetEntry) + record.data_size); | ||
473 | r->next = *head; | ||
474 | record.data = &r[1]; | ||
475 | memcpy (&r[1], raw_data, record.data_size); | ||
476 | GNUNET_free (raw_data); | ||
477 | r->record = record; | ||
478 | *head = r; | ||
479 | return GNUNET_OK; | ||
480 | } | ||
481 | |||
482 | static void | ||
483 | reset_handles (void) | ||
484 | { | ||
485 | struct MarkedRecord *mrec; | ||
486 | struct MarkedRecord *mrec_tmp; | ||
487 | struct RecordSetEntry *rs_entry; | ||
488 | |||
489 | rs_entry = recordset; | ||
490 | while (NULL != (rs_entry = recordset)) | ||
491 | { | ||
492 | recordset = recordset->next; | ||
493 | GNUNET_free (rs_entry); | ||
494 | } | ||
495 | recordset = NULL; | ||
496 | if (NULL != ego_name) | ||
497 | { | ||
498 | GNUNET_free (ego_name); | ||
499 | ego_name = NULL; | ||
500 | } | ||
501 | if (NULL != name) | ||
502 | { | ||
503 | GNUNET_free (name); | ||
504 | name = NULL; | ||
505 | } | ||
506 | if (NULL != value) | ||
507 | { | ||
508 | GNUNET_free (value); | ||
509 | value = NULL; | ||
510 | } | ||
511 | if (NULL != uri) | ||
512 | { | ||
513 | GNUNET_free (uri); | ||
514 | uri = NULL; | ||
515 | } | ||
516 | if (NULL != expirationstring) | ||
517 | { | ||
518 | GNUNET_free (expirationstring); | ||
519 | expirationstring = NULL; | ||
520 | } | ||
521 | if (NULL != purge_task) | ||
522 | { | ||
523 | GNUNET_SCHEDULER_cancel (purge_task); | ||
524 | purge_task = NULL; | ||
525 | } | ||
526 | for (mrec = marked_head; NULL != mrec;) | ||
527 | { | ||
528 | mrec_tmp = mrec; | ||
529 | mrec = mrec->next; | ||
530 | GNUNET_free (mrec_tmp->name); | ||
531 | GNUNET_free (mrec_tmp); | ||
532 | } | ||
533 | if (NULL != list_it) | ||
534 | { | ||
535 | GNUNET_NAMESTORE_zone_iteration_stop (list_it); | ||
536 | list_it = NULL; | ||
537 | } | ||
538 | if (NULL != add_qe) | ||
539 | { | ||
540 | GNUNET_NAMESTORE_cancel (add_qe); | ||
541 | add_qe = NULL; | ||
542 | } | ||
543 | if (NULL != set_qe) | ||
544 | { | ||
545 | GNUNET_NAMESTORE_cancel (set_qe); | ||
546 | set_qe = NULL; | ||
547 | } | ||
548 | if (NULL != add_qe_uri) | ||
549 | { | ||
550 | GNUNET_NAMESTORE_cancel (add_qe_uri); | ||
551 | add_qe_uri = NULL; | ||
552 | } | ||
553 | if (NULL != get_qe) | ||
554 | { | ||
555 | GNUNET_NAMESTORE_cancel (get_qe); | ||
556 | get_qe = NULL; | ||
557 | } | ||
558 | if (NULL != del_qe) | ||
559 | { | ||
560 | GNUNET_NAMESTORE_cancel (del_qe); | ||
561 | del_qe = NULL; | ||
562 | } | ||
563 | if (NULL != reverse_qe) | ||
564 | { | ||
565 | GNUNET_NAMESTORE_cancel (reverse_qe); | ||
566 | reverse_qe = NULL; | ||
567 | } | ||
568 | memset (&zone_pkey, 0, sizeof(zone_pkey)); | ||
569 | if (NULL != zm) | ||
570 | { | ||
571 | GNUNET_NAMESTORE_zone_monitor_stop (zm); | ||
572 | zm = NULL; | ||
573 | } | ||
574 | if (NULL != data) | ||
575 | { | ||
576 | GNUNET_free (data); | ||
577 | data = NULL; | ||
578 | } | ||
579 | if (NULL != typestring) | ||
580 | { | ||
581 | GNUNET_free (typestring); | ||
582 | typestring = NULL; | ||
583 | } | ||
584 | list = 0; | ||
585 | is_public = 0; | ||
586 | is_shadow = 0; | ||
587 | purge_zone = 0; | ||
588 | } | ||
589 | |||
590 | |||
591 | |||
592 | /** | ||
593 | * Task run on shutdown. Cleans up everything. | ||
594 | * | ||
595 | * @param cls unused | ||
596 | */ | ||
597 | static void | ||
598 | do_shutdown (void *cls) | ||
599 | { | ||
600 | struct EgoEntry *ego_entry; | ||
601 | struct EgoEntry *ego_tmp; | ||
602 | (void) cls; | ||
603 | |||
604 | reset_handles (); | ||
605 | if (NULL != ns_qe) | ||
606 | { | ||
607 | GNUNET_NAMESTORE_cancel (ns_qe); | ||
608 | ns_qe = NULL; | ||
609 | } | ||
610 | if (NULL != ns) | ||
611 | { | ||
612 | GNUNET_NAMESTORE_disconnect (ns); | ||
613 | ns = NULL; | ||
614 | } | ||
615 | if (NULL != idh) | ||
616 | { | ||
617 | GNUNET_IDENTITY_disconnect (idh); | ||
618 | idh = NULL; | ||
619 | } | ||
620 | for (ego_entry = ego_head; NULL != ego_entry;) | ||
621 | { | ||
622 | ego_tmp = ego_entry; | ||
623 | ego_entry = ego_entry->next; | ||
624 | GNUNET_free (ego_tmp->identifier); | ||
625 | GNUNET_free (ego_tmp); | ||
626 | } | ||
627 | } | ||
628 | |||
629 | static void | ||
630 | commit_cb (void *cls, enum GNUNET_ErrorCode ec) | ||
631 | { | ||
632 | ns_qe = NULL; | ||
633 | if (GNUNET_EC_NONE != ec) | ||
634 | { | ||
635 | fprintf (stderr, "Failed to commit to namestore: `%s'\n", | ||
636 | GNUNET_ErrorCode_get_hint (ec)); | ||
637 | ret = 1; | ||
638 | } | ||
639 | GNUNET_SCHEDULER_shutdown (); | ||
640 | } | ||
641 | |||
642 | static void | ||
643 | process_command_stdin (); | ||
644 | |||
645 | |||
646 | static void | ||
647 | finish_command (void) | ||
648 | { | ||
649 | reset_handles (); | ||
650 | if (read_from_stdin) | ||
651 | { | ||
652 | process_command_stdin (); | ||
653 | return; | ||
654 | } | ||
655 | ns_qe = GNUNET_NAMESTORE_transaction_commit (ns, &commit_cb, NULL); | ||
656 | } | ||
657 | |||
658 | |||
659 | static void | ||
660 | add_continuation (void *cls, enum GNUNET_ErrorCode ec) | ||
661 | { | ||
662 | struct GNUNET_NAMESTORE_QueueEntry **qe = cls; | ||
663 | |||
664 | *qe = NULL; | ||
665 | if (GNUNET_EC_NONE != ec) | ||
666 | { | ||
667 | fprintf (stderr, | ||
668 | _ ("Adding record failed: %s\n"), | ||
669 | GNUNET_ErrorCode_get_hint (ec)); | ||
670 | if (GNUNET_EC_NAMESTORE_RECORD_EXISTS != ec) | ||
671 | ret = 1; | ||
672 | } | ||
673 | ret = 0; | ||
674 | finish_command (); | ||
675 | } | ||
676 | |||
677 | |||
678 | static void | ||
679 | del_continuation (void *cls, enum GNUNET_ErrorCode ec) | ||
680 | { | ||
681 | (void) cls; | ||
682 | del_qe = NULL; | ||
683 | if (GNUNET_EC_NAMESTORE_RECORD_NOT_FOUND == ec) | ||
684 | { | ||
685 | fprintf (stderr, | ||
686 | _ ("Deleting record failed: %s\n"), GNUNET_ErrorCode_get_hint ( | ||
687 | ec)); | ||
688 | } | ||
689 | finish_command (); | ||
690 | } | ||
691 | |||
692 | static void | ||
693 | purge_next_record (void *cls); | ||
694 | |||
695 | static void | ||
696 | marked_deleted (void *cls, enum GNUNET_ErrorCode ec) | ||
697 | { | ||
698 | del_qe = NULL; | ||
699 | if (GNUNET_EC_NONE != ec) | ||
700 | { | ||
701 | fprintf (stderr, | ||
702 | _ ("Deleting record failed: %s\n"), | ||
703 | GNUNET_ErrorCode_get_hint (ec)); | ||
704 | } | ||
705 | purge_task = GNUNET_SCHEDULER_add_now (&purge_next_record, NULL); | ||
706 | } | ||
707 | |||
708 | |||
709 | static void | ||
710 | purge_next_record (void *cls) | ||
711 | { | ||
712 | struct MarkedRecord *mrec; | ||
713 | purge_task = NULL; | ||
714 | |||
715 | if (NULL == marked_head) | ||
716 | { | ||
717 | ret = 0; | ||
718 | finish_command (); | ||
719 | return; | ||
720 | } | ||
721 | mrec = marked_head; | ||
722 | GNUNET_CONTAINER_DLL_remove (marked_head, | ||
723 | marked_tail, | ||
724 | mrec); | ||
725 | del_qe = GNUNET_NAMESTORE_records_store (ns, | ||
726 | &mrec->key, | ||
727 | mrec->name, | ||
728 | 0, NULL, | ||
729 | &marked_deleted, | ||
730 | NULL); | ||
731 | GNUNET_free (mrec->name); | ||
732 | GNUNET_free (mrec); | ||
733 | } | ||
734 | |||
735 | /** | ||
736 | * Function called when we are done with a zone iteration. | ||
737 | */ | ||
738 | static void | ||
739 | zone_iteration_finished (void *cls) | ||
740 | { | ||
741 | (void) cls; | ||
742 | list_it = NULL; | ||
743 | if (purge_orphaned || purge_zone) | ||
744 | { | ||
745 | purge_task = GNUNET_SCHEDULER_add_now (&purge_next_record, NULL); | ||
746 | return; | ||
747 | } | ||
748 | ret = 0; | ||
749 | finish_command (); | ||
750 | } | ||
751 | |||
752 | |||
753 | /** | ||
754 | * Function called when we encountered an error in a zone iteration. | ||
755 | */ | ||
756 | static void | ||
757 | zone_iteration_error_cb (void *cls) | ||
758 | { | ||
759 | (void) cls; | ||
760 | list_it = NULL; | ||
761 | fprintf (stderr, "Error iterating over zone\n"); | ||
762 | ret = 1; | ||
763 | finish_command (); | ||
764 | } | ||
765 | |||
766 | static void | ||
767 | collect_zone_records_to_purge (const struct | ||
768 | GNUNET_CRYPTO_PrivateKey *zone_key, | ||
769 | const char *rname, | ||
770 | unsigned int rd_len, | ||
771 | const struct GNUNET_GNSRECORD_Data *rd) | ||
772 | { | ||
773 | struct MarkedRecord *mrec; | ||
774 | |||
775 | mrec = GNUNET_new (struct MarkedRecord); | ||
776 | mrec->key = *zone_key; | ||
777 | mrec->name = GNUNET_strdup (rname); | ||
778 | GNUNET_CONTAINER_DLL_insert (marked_head, | ||
779 | marked_tail, | ||
780 | mrec); | ||
781 | } | ||
782 | |||
783 | |||
784 | static void | ||
785 | collect_orphans (const struct GNUNET_CRYPTO_PrivateKey *zone_key, | ||
786 | const char *rname, | ||
787 | unsigned int rd_len, | ||
788 | const struct GNUNET_GNSRECORD_Data *rd) | ||
789 | { | ||
790 | struct EgoEntry *ego; | ||
791 | struct MarkedRecord *orphan; | ||
792 | int is_orphaned = 1; | ||
793 | |||
794 | for (ego = ego_head; NULL != ego; ego = ego->next) | ||
795 | { | ||
796 | if (0 == memcmp (GNUNET_IDENTITY_ego_get_private_key (ego->ego), | ||
797 | zone_key, | ||
798 | sizeof (*zone_key))) | ||
799 | { | ||
800 | is_orphaned = 0; | ||
801 | break; | ||
802 | } | ||
803 | } | ||
804 | if (is_orphaned) | ||
805 | { | ||
806 | orphan = GNUNET_new (struct MarkedRecord); | ||
807 | orphan->key = *zone_key; | ||
808 | orphan->name = GNUNET_strdup (rname); | ||
809 | GNUNET_CONTAINER_DLL_insert (marked_head, | ||
810 | marked_tail, | ||
811 | orphan); | ||
812 | } | ||
813 | } | ||
814 | |||
815 | /** | ||
816 | * Process a record that was stored in the namestore. | ||
817 | * | ||
818 | * @param rname name that is being mapped (at most 255 characters long) | ||
819 | * @param rd_len number of entries in @a rd array | ||
820 | * @param rd array of records with data to store | ||
821 | */ | ||
822 | static void | ||
823 | display_record (const struct GNUNET_CRYPTO_PrivateKey *zone_key, | ||
824 | const char *rname, | ||
825 | unsigned int rd_len, | ||
826 | const struct GNUNET_GNSRECORD_Data *rd) | ||
827 | { | ||
828 | const char *typestr; | ||
829 | char *s; | ||
830 | const char *ets; | ||
831 | struct GNUNET_TIME_Absolute at; | ||
832 | struct GNUNET_TIME_Relative rt; | ||
833 | struct EgoEntry *ego; | ||
834 | int have_record; | ||
835 | int is_orphaned = 1; | ||
836 | char *orphaned_str; | ||
837 | |||
838 | if ((NULL != name) && (0 != strcmp (name, rname))) | ||
839 | return; | ||
840 | have_record = GNUNET_NO; | ||
841 | for (unsigned int i = 0; i < rd_len; i++) | ||
842 | { | ||
843 | if ((GNUNET_GNSRECORD_TYPE_NICK == rd[i].record_type) && | ||
844 | (0 != strcmp (rname, GNUNET_GNS_EMPTY_LABEL_AT))) | ||
845 | continue; | ||
846 | if ((type != rd[i].record_type) && (GNUNET_GNSRECORD_TYPE_ANY != type)) | ||
847 | continue; | ||
848 | have_record = GNUNET_YES; | ||
849 | break; | ||
850 | } | ||
851 | if (GNUNET_NO == have_record) | ||
852 | return; | ||
853 | for (ego = ego_head; NULL != ego; ego = ego->next) | ||
854 | { | ||
855 | if (0 == memcmp (GNUNET_IDENTITY_ego_get_private_key (ego->ego), | ||
856 | zone_key, | ||
857 | sizeof (*zone_key))) | ||
858 | { | ||
859 | is_orphaned = 0; | ||
860 | break; | ||
861 | } | ||
862 | } | ||
863 | if (list_orphaned && ! is_orphaned) | ||
864 | return; | ||
865 | if (! list_orphaned && is_orphaned) | ||
866 | return; | ||
867 | orphaned_str = GNUNET_CRYPTO_private_key_to_string (zone_key); | ||
868 | fprintf (stdout, "%s.%s:\n", rname, is_orphaned ? orphaned_str : | ||
869 | ego->identifier); | ||
870 | GNUNET_free (orphaned_str); | ||
871 | if (NULL != typestring) | ||
872 | type = GNUNET_GNSRECORD_typename_to_number (typestring); | ||
873 | else | ||
874 | type = GNUNET_GNSRECORD_TYPE_ANY; | ||
875 | for (unsigned int i = 0; i < rd_len; i++) | ||
876 | { | ||
877 | if ((GNUNET_GNSRECORD_TYPE_NICK == rd[i].record_type) && | ||
878 | (0 != strcmp (rname, GNUNET_GNS_EMPTY_LABEL_AT))) | ||
879 | continue; | ||
880 | if ((type != rd[i].record_type) && (GNUNET_GNSRECORD_TYPE_ANY != type)) | ||
881 | continue; | ||
882 | typestr = GNUNET_GNSRECORD_number_to_typename (rd[i].record_type); | ||
883 | s = GNUNET_GNSRECORD_value_to_string (rd[i].record_type, | ||
884 | rd[i].data, | ||
885 | rd[i].data_size); | ||
886 | if (NULL == s) | ||
887 | { | ||
888 | fprintf (stdout, | ||
889 | _ ("\tCorrupt or unsupported record of type %u\n"), | ||
890 | (unsigned int) rd[i].record_type); | ||
891 | continue; | ||
892 | } | ||
893 | if (0 != (rd[i].flags & GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION)) | ||
894 | { | ||
895 | rt.rel_value_us = rd[i].expiration_time; | ||
896 | ets = GNUNET_STRINGS_relative_time_to_string (rt, GNUNET_YES); | ||
897 | } | ||
898 | else | ||
899 | { | ||
900 | at.abs_value_us = rd[i].expiration_time; | ||
901 | ets = GNUNET_STRINGS_absolute_time_to_string (at); | ||
902 | } | ||
903 | char flgstr[16]; | ||
904 | sprintf (flgstr, "[%s%s%s%s%s]", | ||
905 | (rd[i].flags & GNUNET_GNSRECORD_RF_PRIVATE) ? "" : "p", | ||
906 | (rd[i].flags & GNUNET_GNSRECORD_RF_SUPPLEMENTAL) ? "S" : "", | ||
907 | (rd[i].flags & GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION) ? "r" : "", | ||
908 | (rd[i].flags & GNUNET_GNSRECORD_RF_SHADOW) ? "S" : "", | ||
909 | (rd[i].flags & GNUNET_GNSRECORD_RF_CRITICAL) ? "C" : ""); | ||
910 | if (output_recordline) | ||
911 | fprintf (stdout, | ||
912 | " %s %" PRIu64 " %s %s\n", | ||
913 | typestr, | ||
914 | rd[i].expiration_time, | ||
915 | flgstr, | ||
916 | s); | ||
917 | else | ||
918 | fprintf (stdout, | ||
919 | "\t%s: %s (%s)\t%s\t%s\n", | ||
920 | typestr, | ||
921 | s, | ||
922 | ets, | ||
923 | (0 != (rd[i].flags & GNUNET_GNSRECORD_RF_PRIVATE)) ? "PRIVATE" | ||
924 | : "PUBLIC", | ||
925 | (0 != (rd[i].flags & GNUNET_GNSRECORD_RF_SHADOW)) ? "SHADOW" | ||
926 | : ""); | ||
927 | GNUNET_free (s); | ||
928 | } | ||
929 | // fprintf (stdout, "%s", "\n"); | ||
930 | } | ||
931 | |||
932 | static void | ||
933 | purge_zone_iterator (void *cls, | ||
934 | const struct GNUNET_CRYPTO_PrivateKey *zone_key, | ||
935 | const char *rname, | ||
936 | unsigned int rd_len, | ||
937 | const struct GNUNET_GNSRECORD_Data *rd, | ||
938 | struct GNUNET_TIME_Absolute expiry) | ||
939 | { | ||
940 | (void) cls; | ||
941 | (void) zone_key; | ||
942 | (void) expiry; | ||
943 | collect_zone_records_to_purge (zone_key, rname, rd_len, rd); | ||
944 | GNUNET_NAMESTORE_zone_iterator_next (list_it, 1); | ||
945 | } | ||
946 | |||
947 | |||
948 | static void | ||
949 | purge_orphans_iterator (void *cls, | ||
950 | const struct GNUNET_CRYPTO_PrivateKey *zone_key, | ||
951 | const char *rname, | ||
952 | unsigned int rd_len, | ||
953 | const struct GNUNET_GNSRECORD_Data *rd, | ||
954 | struct GNUNET_TIME_Absolute expiry) | ||
955 | { | ||
956 | (void) cls; | ||
957 | (void) zone_key; | ||
958 | (void) expiry; | ||
959 | collect_orphans (zone_key, rname, rd_len, rd); | ||
960 | GNUNET_NAMESTORE_zone_iterator_next (list_it, 1); | ||
961 | } | ||
962 | |||
963 | |||
964 | /** | ||
965 | * Process a record that was stored in the namestore. | ||
966 | * | ||
967 | * @param cls closure | ||
968 | * @param zone_key private key of the zone | ||
969 | * @param rname name that is being mapped (at most 255 characters long) | ||
970 | * @param rd_len number of entries in @a rd array | ||
971 | * @param rd array of records with data to store | ||
972 | */ | ||
973 | static void | ||
974 | display_record_iterator (void *cls, | ||
975 | const struct GNUNET_CRYPTO_PrivateKey *zone_key, | ||
976 | const char *rname, | ||
977 | unsigned int rd_len, | ||
978 | const struct GNUNET_GNSRECORD_Data *rd, | ||
979 | struct GNUNET_TIME_Absolute expiry) | ||
980 | { | ||
981 | (void) cls; | ||
982 | (void) zone_key; | ||
983 | (void) expiry; | ||
984 | display_record (zone_key, rname, rd_len, rd); | ||
985 | GNUNET_NAMESTORE_zone_iterator_next (list_it, 1); | ||
986 | } | ||
987 | |||
988 | |||
989 | /** | ||
990 | * Process a record that was stored in the namestore. | ||
991 | * | ||
992 | * @param cls closure | ||
993 | * @param zone_key private key of the zone | ||
994 | * @param rname name that is being mapped (at most 255 characters long) | ||
995 | * @param rd_len number of entries in @a rd array | ||
996 | * @param rd array of records with data to store | ||
997 | */ | ||
998 | static void | ||
999 | display_record_monitor (void *cls, | ||
1000 | const struct GNUNET_CRYPTO_PrivateKey *zone_key, | ||
1001 | const char *rname, | ||
1002 | unsigned int rd_len, | ||
1003 | const struct GNUNET_GNSRECORD_Data *rd, | ||
1004 | struct GNUNET_TIME_Absolute expiry) | ||
1005 | { | ||
1006 | (void) cls; | ||
1007 | (void) zone_key; | ||
1008 | (void) expiry; | ||
1009 | display_record (zone_key, rname, rd_len, rd); | ||
1010 | GNUNET_NAMESTORE_zone_monitor_next (zm, 1); | ||
1011 | } | ||
1012 | |||
1013 | |||
1014 | /** | ||
1015 | * Process a record that was stored in the namestore. | ||
1016 | * | ||
1017 | * @param cls closure | ||
1018 | * @param zone_key private key of the zone | ||
1019 | * @param rname name that is being mapped (at most 255 characters long) | ||
1020 | * @param rd_len number of entries in @a rd array | ||
1021 | * @param rd array of records with data to store | ||
1022 | */ | ||
1023 | static void | ||
1024 | display_record_lookup (void *cls, | ||
1025 | const struct GNUNET_CRYPTO_PrivateKey *zone_key, | ||
1026 | const char *rname, | ||
1027 | unsigned int rd_len, | ||
1028 | const struct GNUNET_GNSRECORD_Data *rd) | ||
1029 | { | ||
1030 | (void) cls; | ||
1031 | (void) zone_key; | ||
1032 | get_qe = NULL; | ||
1033 | display_record (zone_key, rname, rd_len, rd); | ||
1034 | finish_command (); | ||
1035 | } | ||
1036 | |||
1037 | |||
1038 | /** | ||
1039 | * Function called once we are in sync in monitor mode. | ||
1040 | * | ||
1041 | * @param cls NULL | ||
1042 | */ | ||
1043 | static void | ||
1044 | sync_cb (void *cls) | ||
1045 | { | ||
1046 | (void) cls; | ||
1047 | fprintf (stdout, "%s", "Monitor is now in sync.\n"); | ||
1048 | } | ||
1049 | |||
1050 | |||
1051 | /** | ||
1052 | * Function called on errors while monitoring. | ||
1053 | * | ||
1054 | * @param cls NULL | ||
1055 | */ | ||
1056 | static void | ||
1057 | monitor_error_cb (void *cls) | ||
1058 | { | ||
1059 | (void) cls; | ||
1060 | fprintf (stderr, "%s", "Monitor disconnected and out of sync.\n"); | ||
1061 | } | ||
1062 | |||
1063 | |||
1064 | /** | ||
1065 | * Function called on errors while monitoring. | ||
1066 | * | ||
1067 | * @param cls NULL | ||
1068 | */ | ||
1069 | static void | ||
1070 | lookup_error_cb (void *cls) | ||
1071 | { | ||
1072 | (void) cls; | ||
1073 | get_qe = NULL; | ||
1074 | fprintf (stderr, "%s", "Failed to lookup record.\n"); | ||
1075 | finish_command (); | ||
1076 | } | ||
1077 | |||
1078 | |||
1079 | /** | ||
1080 | * Function called if lookup fails. | ||
1081 | */ | ||
1082 | static void | ||
1083 | add_error_cb (void *cls) | ||
1084 | { | ||
1085 | (void) cls; | ||
1086 | add_qe = NULL; | ||
1087 | GNUNET_break (0); | ||
1088 | ret = 1; | ||
1089 | finish_command (); | ||
1090 | } | ||
1091 | |||
1092 | |||
1093 | /** | ||
1094 | * We're storing a record; this function is given the existing record | ||
1095 | * so that we can merge the information. | ||
1096 | * | ||
1097 | * @param cls closure, unused | ||
1098 | * @param zone_key private key of the zone | ||
1099 | * @param rec_name name that is being mapped (at most 255 characters long) | ||
1100 | * @param rd_count number of entries in @a rd array | ||
1101 | * @param rd array of records with data to store | ||
1102 | */ | ||
1103 | static void | ||
1104 | get_existing_record (void *cls, | ||
1105 | const struct GNUNET_CRYPTO_PrivateKey *zone_key, | ||
1106 | const char *rec_name, | ||
1107 | unsigned int rd_count, | ||
1108 | const struct GNUNET_GNSRECORD_Data *rd) | ||
1109 | { | ||
1110 | struct GNUNET_GNSRECORD_Data rdn[rd_count + 1]; | ||
1111 | struct GNUNET_GNSRECORD_Data *rde; | ||
1112 | |||
1113 | (void) cls; | ||
1114 | (void) zone_key; | ||
1115 | add_qe = NULL; | ||
1116 | if (0 != strcmp (rec_name, name)) | ||
1117 | { | ||
1118 | GNUNET_break (0); | ||
1119 | ret = 1; | ||
1120 | finish_command (); | ||
1121 | return; | ||
1122 | } | ||
1123 | |||
1124 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
1125 | "Received %u records for name `%s'\n", | ||
1126 | rd_count, | ||
1127 | rec_name); | ||
1128 | for (unsigned int i = 0; i < rd_count; i++) | ||
1129 | { | ||
1130 | switch (rd[i].record_type) | ||
1131 | { | ||
1132 | case GNUNET_DNSPARSER_TYPE_SOA: | ||
1133 | if (GNUNET_DNSPARSER_TYPE_SOA == type) | ||
1134 | { | ||
1135 | fprintf ( | ||
1136 | stderr, | ||
1137 | _ ( | ||
1138 | "A SOA record exists already under `%s', cannot add a second SOA to the same zone.\n"), | ||
1139 | rec_name); | ||
1140 | ret = 1; | ||
1141 | finish_command (); | ||
1142 | return; | ||
1143 | } | ||
1144 | break; | ||
1145 | } | ||
1146 | } | ||
1147 | memset (rdn, 0, sizeof(struct GNUNET_GNSRECORD_Data)); | ||
1148 | GNUNET_memcpy (&rdn[1], rd, rd_count * sizeof(struct GNUNET_GNSRECORD_Data)); | ||
1149 | rde = &rdn[0]; | ||
1150 | rde->data = data; | ||
1151 | rde->data_size = data_size; | ||
1152 | rde->record_type = type; | ||
1153 | if (1 == is_shadow) | ||
1154 | rde->flags |= GNUNET_GNSRECORD_RF_SHADOW; | ||
1155 | if (1 != is_public) | ||
1156 | rde->flags |= GNUNET_GNSRECORD_RF_PRIVATE; | ||
1157 | rde->expiration_time = etime; | ||
1158 | if (GNUNET_YES == etime_is_rel) | ||
1159 | rde->flags |= GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION; | ||
1160 | else if (GNUNET_NO != etime_is_rel) | ||
1161 | rde->expiration_time = GNUNET_TIME_UNIT_FOREVER_ABS.abs_value_us; | ||
1162 | GNUNET_assert (NULL != name); | ||
1163 | add_qe = GNUNET_NAMESTORE_records_store (ns, | ||
1164 | &zone_pkey, | ||
1165 | name, | ||
1166 | rd_count + 1, | ||
1167 | rde, | ||
1168 | &add_continuation, | ||
1169 | &add_qe); | ||
1170 | } | ||
1171 | |||
1172 | |||
1173 | /** | ||
1174 | * Function called if we encountered an error in zone-to-name. | ||
1175 | */ | ||
1176 | static void | ||
1177 | reverse_error_cb (void *cls) | ||
1178 | { | ||
1179 | (void) cls; | ||
1180 | reverse_qe = NULL; | ||
1181 | fprintf (stdout, "%s.zkey\n", reverse_pkey); | ||
1182 | } | ||
1183 | |||
1184 | |||
1185 | /** | ||
1186 | * Function called with the result of our attempt to obtain a name for a given | ||
1187 | * public key. | ||
1188 | * | ||
1189 | * @param cls NULL | ||
1190 | * @param zone private key of the zone; NULL on disconnect | ||
1191 | * @param label label of the records; NULL on disconnect | ||
1192 | * @param rd_count number of entries in @a rd array, 0 if label was deleted | ||
1193 | * @param rd array of records with data to store | ||
1194 | */ | ||
1195 | static void | ||
1196 | handle_reverse_lookup (void *cls, | ||
1197 | const struct GNUNET_CRYPTO_PrivateKey *zone, | ||
1198 | const char *label, | ||
1199 | unsigned int rd_count, | ||
1200 | const struct GNUNET_GNSRECORD_Data *rd) | ||
1201 | { | ||
1202 | (void) cls; | ||
1203 | (void) zone; | ||
1204 | (void) rd_count; | ||
1205 | (void) rd; | ||
1206 | reverse_qe = NULL; | ||
1207 | if (NULL == label) | ||
1208 | fprintf (stdout, "%s\n", reverse_pkey); | ||
1209 | else | ||
1210 | fprintf (stdout, "%s.%s\n", label, ego_name); | ||
1211 | finish_command (); | ||
1212 | } | ||
1213 | |||
1214 | |||
1215 | /** | ||
1216 | * Function called if lookup for deletion fails. | ||
1217 | */ | ||
1218 | static void | ||
1219 | del_lookup_error_cb (void *cls) | ||
1220 | { | ||
1221 | (void) cls; | ||
1222 | del_qe = NULL; | ||
1223 | GNUNET_break (0); | ||
1224 | ret = 1; | ||
1225 | finish_command (); | ||
1226 | } | ||
1227 | |||
1228 | |||
1229 | /** | ||
1230 | * We were asked to delete something; this function is called with | ||
1231 | * the existing records. Now we should determine what should be | ||
1232 | * deleted and then issue the deletion operation. | ||
1233 | * | ||
1234 | * @param cls NULL | ||
1235 | * @param zone private key of the zone we are deleting from | ||
1236 | * @param label name of the records we are editing | ||
1237 | * @param rd_count size of the @a rd array | ||
1238 | * @param rd existing records | ||
1239 | */ | ||
1240 | static void | ||
1241 | del_monitor (void *cls, | ||
1242 | const struct GNUNET_CRYPTO_PrivateKey *zone, | ||
1243 | const char *label, | ||
1244 | unsigned int rd_count, | ||
1245 | const struct GNUNET_GNSRECORD_Data *rd) | ||
1246 | { | ||
1247 | struct GNUNET_GNSRECORD_Data rdx[rd_count]; | ||
1248 | unsigned int rd_left; | ||
1249 | uint32_t type; | ||
1250 | char *vs; | ||
1251 | |||
1252 | (void) cls; | ||
1253 | (void) zone; | ||
1254 | del_qe = NULL; | ||
1255 | if (0 == rd_count) | ||
1256 | { | ||
1257 | fprintf (stderr, | ||
1258 | _ ( | ||
1259 | "There are no records under label `%s' that could be deleted.\n"), | ||
1260 | label); | ||
1261 | ret = 1; | ||
1262 | finish_command (); | ||
1263 | return; | ||
1264 | } | ||
1265 | if ((NULL == value) && (NULL == typestring)) | ||
1266 | { | ||
1267 | /* delete everything */ | ||
1268 | del_qe = GNUNET_NAMESTORE_records_store (ns, | ||
1269 | &zone_pkey, | ||
1270 | name, | ||
1271 | 0, | ||
1272 | NULL, | ||
1273 | &del_continuation, | ||
1274 | NULL); | ||
1275 | return; | ||
1276 | } | ||
1277 | rd_left = 0; | ||
1278 | if (NULL != typestring) | ||
1279 | type = GNUNET_GNSRECORD_typename_to_number (typestring); | ||
1280 | else | ||
1281 | type = GNUNET_GNSRECORD_TYPE_ANY; | ||
1282 | for (unsigned int i = 0; i < rd_count; i++) | ||
1283 | { | ||
1284 | vs = NULL; | ||
1285 | if (! (((GNUNET_GNSRECORD_TYPE_ANY == type) || | ||
1286 | (rd[i].record_type == type)) && | ||
1287 | ((NULL == value) || | ||
1288 | (NULL == | ||
1289 | (vs = (GNUNET_GNSRECORD_value_to_string (rd[i].record_type, | ||
1290 | rd[i].data, | ||
1291 | rd[i].data_size)))) || | ||
1292 | (0 == strcmp (vs, value))))) | ||
1293 | rdx[rd_left++] = rd[i]; | ||
1294 | GNUNET_free (vs); | ||
1295 | } | ||
1296 | if (rd_count == rd_left) | ||
1297 | { | ||
1298 | /* nothing got deleted */ | ||
1299 | fprintf ( | ||
1300 | stderr, | ||
1301 | _ ( | ||
1302 | "There are no records under label `%s' that match the request for deletion.\n"), | ||
1303 | label); | ||
1304 | finish_command (); | ||
1305 | return; | ||
1306 | } | ||
1307 | /* delete everything but what we copied to 'rdx' */ | ||
1308 | del_qe = GNUNET_NAMESTORE_records_store (ns, | ||
1309 | &zone_pkey, | ||
1310 | name, | ||
1311 | rd_left, | ||
1312 | rdx, | ||
1313 | &del_continuation, | ||
1314 | NULL); | ||
1315 | } | ||
1316 | |||
1317 | |||
1318 | static void | ||
1319 | replace_cont (void *cls, enum GNUNET_ErrorCode ec) | ||
1320 | { | ||
1321 | (void) cls; | ||
1322 | |||
1323 | set_qe = NULL; | ||
1324 | if (GNUNET_EC_NONE != ec) | ||
1325 | { | ||
1326 | GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE, | ||
1327 | _ ("%s\n"), | ||
1328 | GNUNET_ErrorCode_get_hint (ec)); | ||
1329 | ret = 1; /* fail from 'main' */ | ||
1330 | } | ||
1331 | finish_command (); | ||
1332 | } | ||
1333 | |||
1334 | |||
1335 | /** | ||
1336 | * We have obtained the zone's private key, so now process | ||
1337 | * the main commands using it. | ||
1338 | * | ||
1339 | * @param cfg configuration to use | ||
1340 | */ | ||
1341 | static void | ||
1342 | run_with_zone_pkey (const struct GNUNET_CONFIGURATION_Handle *cfg) | ||
1343 | { | ||
1344 | struct GNUNET_GNSRECORD_Data rd; | ||
1345 | enum GNUNET_GNSRECORD_Filter filter_flags = GNUNET_GNSRECORD_FILTER_NONE; | ||
1346 | |||
1347 | if (omit_private) | ||
1348 | filter_flags |= GNUNET_GNSRECORD_FILTER_OMIT_PRIVATE; | ||
1349 | if (include_maintenance) | ||
1350 | filter_flags |= GNUNET_GNSRECORD_FILTER_INCLUDE_MAINTENANCE; | ||
1351 | if (! (add | del | list | (NULL != nickstring) | (NULL != uri) | ||
1352 | | (NULL != reverse_pkey) | (NULL != recordset) | (monitor) | ||
1353 | | (purge_orphaned) | (list_orphaned) | (purge_zone)) ) | ||
1354 | { | ||
1355 | /* nothing more to be done */ | ||
1356 | fprintf (stderr, _ ("No options given\n")); | ||
1357 | finish_command (); | ||
1358 | return; | ||
1359 | } | ||
1360 | |||
1361 | if (NULL != recordset) | ||
1362 | { | ||
1363 | /* replace entire record set */ | ||
1364 | unsigned int rd_count; | ||
1365 | struct GNUNET_GNSRECORD_Data *rd; | ||
1366 | |||
1367 | /* FIXME: We could easily support append and delete with this as well */ | ||
1368 | if (! add) | ||
1369 | { | ||
1370 | fprintf (stderr, _ ("Recordlines only work with option `%s'\n"), | ||
1371 | "-a"); | ||
1372 | ret = 1; | ||
1373 | finish_command (); | ||
1374 | return; | ||
1375 | } | ||
1376 | if (NULL == name) | ||
1377 | { | ||
1378 | fprintf (stderr, | ||
1379 | _ ("Missing option `%s' for operation `%s'\n"), | ||
1380 | "-n", | ||
1381 | _ ("name")); | ||
1382 | ret = 1; | ||
1383 | finish_command (); | ||
1384 | return; | ||
1385 | } | ||
1386 | rd_count = 0; | ||
1387 | for (struct RecordSetEntry *e = recordset; NULL != e; e = e->next) | ||
1388 | rd_count++; | ||
1389 | rd = GNUNET_new_array (rd_count, struct GNUNET_GNSRECORD_Data); | ||
1390 | rd_count = 0; | ||
1391 | for (struct RecordSetEntry *e = recordset; NULL != e; e = e->next) | ||
1392 | { | ||
1393 | rd[rd_count] = e->record; | ||
1394 | rd_count++; | ||
1395 | } | ||
1396 | set_qe = GNUNET_NAMESTORE_records_store (ns, | ||
1397 | &zone_pkey, | ||
1398 | name, | ||
1399 | rd_count, | ||
1400 | rd, | ||
1401 | &replace_cont, | ||
1402 | NULL); | ||
1403 | GNUNET_free (rd); | ||
1404 | return; | ||
1405 | } | ||
1406 | if (NULL != nickstring) | ||
1407 | { | ||
1408 | if (0 == strlen (nickstring)) | ||
1409 | { | ||
1410 | fprintf (stderr, _ ("Invalid nick `%s'\n"), nickstring); | ||
1411 | ret = 1; | ||
1412 | finish_command (); | ||
1413 | return; | ||
1414 | } | ||
1415 | add = 1; | ||
1416 | typestring = GNUNET_strdup (GNUNET_GNSRECORD_number_to_typename ( | ||
1417 | GNUNET_GNSRECORD_TYPE_NICK)); | ||
1418 | name = GNUNET_strdup (GNUNET_GNS_EMPTY_LABEL_AT); | ||
1419 | value = GNUNET_strdup (nickstring); | ||
1420 | is_public = 0; | ||
1421 | expirationstring = GNUNET_strdup ("never"); | ||
1422 | GNUNET_free (nickstring); | ||
1423 | nickstring = NULL; | ||
1424 | } | ||
1425 | |||
1426 | if (add) | ||
1427 | { | ||
1428 | if (NULL == ego_name) | ||
1429 | { | ||
1430 | fprintf (stderr, | ||
1431 | _ ("Missing option `%s' for operation `%s'\n"), | ||
1432 | "-z", | ||
1433 | _ ("add")); | ||
1434 | ret = 1; | ||
1435 | finish_command (); | ||
1436 | return; | ||
1437 | } | ||
1438 | if (NULL == name) | ||
1439 | { | ||
1440 | fprintf (stderr, | ||
1441 | _ ("Missing option `%s' for operation `%s'\n"), | ||
1442 | "-n", | ||
1443 | _ ("add")); | ||
1444 | ret = 1; | ||
1445 | finish_command (); | ||
1446 | return; | ||
1447 | } | ||
1448 | if (NULL == typestring) | ||
1449 | { | ||
1450 | fprintf (stderr, | ||
1451 | _ ("Missing option `%s' for operation `%s'\n"), | ||
1452 | "-t", | ||
1453 | _ ("add")); | ||
1454 | ret = 1; | ||
1455 | finish_command (); | ||
1456 | return; | ||
1457 | } | ||
1458 | type = GNUNET_GNSRECORD_typename_to_number (typestring); | ||
1459 | if (UINT32_MAX == type) | ||
1460 | { | ||
1461 | fprintf (stderr, _ ("Unsupported type `%s'\n"), typestring); | ||
1462 | ret = 1; | ||
1463 | finish_command (); | ||
1464 | return; | ||
1465 | } | ||
1466 | if ((GNUNET_DNSPARSER_TYPE_SRV == type) || | ||
1467 | (GNUNET_DNSPARSER_TYPE_TLSA == type) || | ||
1468 | (GNUNET_DNSPARSER_TYPE_OPENPGPKEY == type)) | ||
1469 | { | ||
1470 | fprintf (stderr, | ||
1471 | _ ("For DNS record types `SRV', `TLSA' and `OPENPGPKEY'")); | ||
1472 | fprintf (stderr, ", please use a `BOX' record instead\n"); | ||
1473 | ret = 1; | ||
1474 | finish_command (); | ||
1475 | return; | ||
1476 | } | ||
1477 | if (NULL == value) | ||
1478 | { | ||
1479 | fprintf (stderr, | ||
1480 | _ ("Missing option `%s' for operation `%s'\n"), | ||
1481 | "-V", | ||
1482 | _ ("add")); | ||
1483 | ret = 1; | ||
1484 | finish_command (); | ||
1485 | return; | ||
1486 | } | ||
1487 | if (GNUNET_OK != | ||
1488 | GNUNET_GNSRECORD_string_to_value (type, value, &data, &data_size)) | ||
1489 | { | ||
1490 | fprintf (stderr, | ||
1491 | _ ("Value `%s' invalid for record type `%s'\n"), | ||
1492 | value, | ||
1493 | typestring); | ||
1494 | ret = 1; | ||
1495 | finish_command (); | ||
1496 | return; | ||
1497 | } | ||
1498 | if (NULL == expirationstring) | ||
1499 | { | ||
1500 | fprintf (stderr, | ||
1501 | _ ("Missing option `%s' for operation `%s'\n"), | ||
1502 | "-e", | ||
1503 | _ ("add")); | ||
1504 | ret = 1; | ||
1505 | finish_command (); | ||
1506 | return; | ||
1507 | } | ||
1508 | if (GNUNET_OK != parse_expiration (expirationstring, &etime_is_rel, &etime)) | ||
1509 | { | ||
1510 | fprintf (stderr, _ ("Invalid time format `%s'\n"), expirationstring); | ||
1511 | ret = 1; | ||
1512 | finish_command (); | ||
1513 | return; | ||
1514 | } | ||
1515 | add_qe = GNUNET_NAMESTORE_records_lookup (ns, | ||
1516 | &zone_pkey, | ||
1517 | name, | ||
1518 | &add_error_cb, | ||
1519 | NULL, | ||
1520 | &get_existing_record, | ||
1521 | NULL); | ||
1522 | } | ||
1523 | if (del) | ||
1524 | { | ||
1525 | if (NULL == ego_name) | ||
1526 | { | ||
1527 | fprintf (stderr, | ||
1528 | _ ("Missing option `%s' for operation `%s'\n"), | ||
1529 | "-z", | ||
1530 | _ ("del")); | ||
1531 | ret = 1; | ||
1532 | finish_command (); | ||
1533 | return; | ||
1534 | } | ||
1535 | if (NULL == name) | ||
1536 | { | ||
1537 | fprintf (stderr, | ||
1538 | _ ("Missing option `%s' for operation `%s'\n"), | ||
1539 | "-n", | ||
1540 | _ ("del")); | ||
1541 | ret = 1; | ||
1542 | finish_command (); | ||
1543 | return; | ||
1544 | } | ||
1545 | del_qe = GNUNET_NAMESTORE_records_lookup (ns, | ||
1546 | &zone_pkey, | ||
1547 | name, | ||
1548 | &del_lookup_error_cb, | ||
1549 | NULL, | ||
1550 | &del_monitor, | ||
1551 | NULL); | ||
1552 | } | ||
1553 | if (purge_orphaned) | ||
1554 | { | ||
1555 | list_it = GNUNET_NAMESTORE_zone_iteration_start2 (ns, | ||
1556 | NULL, | ||
1557 | &zone_iteration_error_cb, | ||
1558 | NULL, | ||
1559 | &purge_orphans_iterator, | ||
1560 | NULL, | ||
1561 | &zone_iteration_finished, | ||
1562 | NULL, | ||
1563 | filter_flags); | ||
1564 | |||
1565 | } | ||
1566 | else if (purge_zone) | ||
1567 | { | ||
1568 | if (NULL == ego_name) | ||
1569 | { | ||
1570 | fprintf (stderr, | ||
1571 | _ ("Missing option `%s' for operation `%s'\n"), | ||
1572 | "-z", | ||
1573 | _ ("purge-zone")); | ||
1574 | ret = 1; | ||
1575 | finish_command (); | ||
1576 | return; | ||
1577 | } | ||
1578 | list_it = GNUNET_NAMESTORE_zone_iteration_start2 (ns, | ||
1579 | &zone_pkey, | ||
1580 | &zone_iteration_error_cb, | ||
1581 | NULL, | ||
1582 | &purge_zone_iterator, | ||
1583 | NULL, | ||
1584 | &zone_iteration_finished, | ||
1585 | NULL, | ||
1586 | filter_flags); | ||
1587 | |||
1588 | } | ||
1589 | else if (list || list_orphaned) | ||
1590 | { | ||
1591 | if (NULL != name) | ||
1592 | { | ||
1593 | if (NULL == ego_name) | ||
1594 | { | ||
1595 | fprintf (stderr, | ||
1596 | _ ("Missing option `%s' for operation `%s'\n"), | ||
1597 | "-z", | ||
1598 | _ ("list")); | ||
1599 | ret = 1; | ||
1600 | finish_command (); | ||
1601 | return; | ||
1602 | } | ||
1603 | get_qe = GNUNET_NAMESTORE_records_lookup (ns, | ||
1604 | &zone_pkey, | ||
1605 | name, | ||
1606 | &lookup_error_cb, | ||
1607 | NULL, | ||
1608 | &display_record_lookup, | ||
1609 | NULL); | ||
1610 | } | ||
1611 | else | ||
1612 | list_it = GNUNET_NAMESTORE_zone_iteration_start2 (ns, | ||
1613 | (NULL == ego_name) ? | ||
1614 | NULL : &zone_pkey, | ||
1615 | &zone_iteration_error_cb, | ||
1616 | NULL, | ||
1617 | &display_record_iterator, | ||
1618 | NULL, | ||
1619 | &zone_iteration_finished, | ||
1620 | NULL, | ||
1621 | filter_flags); | ||
1622 | } | ||
1623 | if (NULL != reverse_pkey) | ||
1624 | { | ||
1625 | struct GNUNET_CRYPTO_PublicKey pubkey; | ||
1626 | |||
1627 | if (NULL == ego_name) | ||
1628 | { | ||
1629 | fprintf (stderr, | ||
1630 | _ ("Missing option `%s' for operation `%s'\n"), | ||
1631 | "-z", | ||
1632 | _ ("reverse-pkey")); | ||
1633 | ret = 1; | ||
1634 | finish_command (); | ||
1635 | return; | ||
1636 | } | ||
1637 | if (GNUNET_OK != | ||
1638 | GNUNET_CRYPTO_public_key_from_string (reverse_pkey, | ||
1639 | &pubkey)) | ||
1640 | { | ||
1641 | fprintf (stderr, | ||
1642 | _ ("Invalid public key for reverse lookup `%s'\n"), | ||
1643 | reverse_pkey); | ||
1644 | ret = 1; | ||
1645 | finish_command (); | ||
1646 | return; | ||
1647 | } | ||
1648 | reverse_qe = GNUNET_NAMESTORE_zone_to_name (ns, | ||
1649 | &zone_pkey, | ||
1650 | &pubkey, | ||
1651 | &reverse_error_cb, | ||
1652 | NULL, | ||
1653 | &handle_reverse_lookup, | ||
1654 | NULL); | ||
1655 | } | ||
1656 | if (NULL != uri) | ||
1657 | { | ||
1658 | char sh[105]; | ||
1659 | char sname[64]; | ||
1660 | struct GNUNET_CRYPTO_PublicKey pkey; | ||
1661 | if (NULL == ego_name) | ||
1662 | { | ||
1663 | fprintf (stderr, | ||
1664 | _ ("Missing option `%s' for operation `%s'\n"), | ||
1665 | "-z", | ||
1666 | _ ("uri")); | ||
1667 | ret = 1; | ||
1668 | finish_command (); | ||
1669 | return; | ||
1670 | } | ||
1671 | |||
1672 | memset (sh, 0, 105); | ||
1673 | memset (sname, 0, 64); | ||
1674 | |||
1675 | if ((2 != (sscanf (uri, "gnunet://gns/%58s/%63s", sh, sname))) || | ||
1676 | (GNUNET_OK != | ||
1677 | GNUNET_CRYPTO_public_key_from_string (sh, &pkey))) | ||
1678 | { | ||
1679 | fprintf (stderr, _ ("Invalid URI `%s'\n"), uri); | ||
1680 | ret = 1; | ||
1681 | finish_command (); | ||
1682 | return; | ||
1683 | } | ||
1684 | if (NULL == expirationstring) | ||
1685 | { | ||
1686 | fprintf (stderr, | ||
1687 | _ ("Missing option `%s' for operation `%s'\n"), | ||
1688 | "-e", | ||
1689 | _ ("add")); | ||
1690 | ret = 1; | ||
1691 | finish_command (); | ||
1692 | return; | ||
1693 | } | ||
1694 | if (GNUNET_OK != parse_expiration (expirationstring, &etime_is_rel, &etime)) | ||
1695 | { | ||
1696 | fprintf (stderr, _ ("Invalid time format `%s'\n"), expirationstring); | ||
1697 | ret = 1; | ||
1698 | finish_command (); | ||
1699 | return; | ||
1700 | } | ||
1701 | memset (&rd, 0, sizeof(rd)); | ||
1702 | rd.data = &pkey; | ||
1703 | rd.data_size = GNUNET_CRYPTO_public_key_get_length (&pkey); | ||
1704 | rd.record_type = ntohl (pkey.type); | ||
1705 | rd.expiration_time = etime; | ||
1706 | if (GNUNET_YES == etime_is_rel) | ||
1707 | rd.flags |= GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION; | ||
1708 | if (1 == is_shadow) | ||
1709 | rd.flags |= GNUNET_GNSRECORD_RF_SHADOW; | ||
1710 | add_qe_uri = GNUNET_NAMESTORE_records_store (ns, | ||
1711 | &zone_pkey, | ||
1712 | sname, | ||
1713 | 1, | ||
1714 | &rd, | ||
1715 | &add_continuation, | ||
1716 | &add_qe_uri); | ||
1717 | } | ||
1718 | if (monitor) | ||
1719 | { | ||
1720 | zm = GNUNET_NAMESTORE_zone_monitor_start2 (cfg, | ||
1721 | (NULL != ego_name) ? | ||
1722 | &zone_pkey : NULL, | ||
1723 | GNUNET_YES, | ||
1724 | &monitor_error_cb, | ||
1725 | NULL, | ||
1726 | &display_record_monitor, | ||
1727 | NULL, | ||
1728 | &sync_cb, | ||
1729 | NULL, | ||
1730 | filter_flags); | ||
1731 | } | ||
1732 | } | ||
1733 | |||
1734 | #define MAX_LINE_LEN 4086 | ||
1735 | |||
1736 | #define MAX_ARGS 20 | ||
1737 | |||
1738 | static int | ||
1739 | get_identity_for_string (const char *str, | ||
1740 | struct GNUNET_CRYPTO_PrivateKey *zk) | ||
1741 | { | ||
1742 | const struct GNUNET_CRYPTO_PrivateKey *privkey; | ||
1743 | struct GNUNET_CRYPTO_PublicKey pubkey; | ||
1744 | struct GNUNET_CRYPTO_PublicKey ego_pubkey; | ||
1745 | struct EgoEntry *ego_entry; | ||
1746 | |||
1747 | if (GNUNET_OK == GNUNET_CRYPTO_public_key_from_string (str, | ||
1748 | &pubkey)) | ||
1749 | { | ||
1750 | for (ego_entry = ego_head; | ||
1751 | NULL != ego_entry; ego_entry = ego_entry->next) | ||
1752 | { | ||
1753 | privkey = GNUNET_IDENTITY_ego_get_private_key (ego_entry->ego); | ||
1754 | GNUNET_IDENTITY_ego_get_public_key (ego_entry->ego, &ego_pubkey); | ||
1755 | if (0 == memcmp (&ego_pubkey, &pubkey, sizeof (pubkey))) | ||
1756 | { | ||
1757 | *zk = *privkey; | ||
1758 | return GNUNET_OK; | ||
1759 | } | ||
1760 | } | ||
1761 | } | ||
1762 | else | ||
1763 | { | ||
1764 | for (ego_entry = ego_head; NULL != ego_entry; ego_entry = ego_entry->next) | ||
1765 | { | ||
1766 | /** FIXME: Check for zTLD? **/ | ||
1767 | if (0 != strcmp (str, ego_entry->identifier)) | ||
1768 | continue; | ||
1769 | *zk = *GNUNET_IDENTITY_ego_get_private_key (ego_entry->ego); | ||
1770 | return GNUNET_OK; | ||
1771 | } | ||
1772 | } | ||
1773 | return GNUNET_NO; | ||
1774 | } | ||
1775 | |||
1776 | static void | ||
1777 | process_command_stdin () | ||
1778 | { | ||
1779 | char buf[MAX_LINE_LEN]; | ||
1780 | static struct GNUNET_CRYPTO_PrivateKey next_zone_key; | ||
1781 | static char next_name[GNUNET_DNSPARSER_MAX_NAME_LENGTH]; | ||
1782 | static int finished = GNUNET_NO; | ||
1783 | static int have_next_zonekey = GNUNET_NO; | ||
1784 | int zonekey_set = GNUNET_NO; | ||
1785 | char *tmp; | ||
1786 | |||
1787 | |||
1788 | if (GNUNET_YES == have_next_zonekey) | ||
1789 | { | ||
1790 | zone_pkey = next_zone_key; | ||
1791 | if (NULL != name) | ||
1792 | GNUNET_free (name); | ||
1793 | name = GNUNET_strdup (next_name); | ||
1794 | zonekey_set = GNUNET_YES; | ||
1795 | } | ||
1796 | while (NULL != fgets (buf, sizeof (buf), stdin)) | ||
1797 | { | ||
1798 | if (1 >= strlen (buf)) | ||
1799 | continue; | ||
1800 | if (buf[strlen (buf) - 1] == '\n') | ||
1801 | buf[strlen (buf) - 1] = '\0'; | ||
1802 | /** | ||
1803 | * Check if this is a new name. If yes, and we have records, store them. | ||
1804 | */ | ||
1805 | if (buf[strlen (buf) - 1] == ':') | ||
1806 | { | ||
1807 | memset (next_name, 0, sizeof (next_name)); | ||
1808 | strncpy (next_name, buf, strlen (buf) - 1); | ||
1809 | tmp = strchr (next_name, '.'); | ||
1810 | if (NULL == tmp) | ||
1811 | { | ||
1812 | fprintf (stderr, "Error parsing name `%s'\n", next_name); | ||
1813 | ns_qe = GNUNET_NAMESTORE_transaction_commit (ns, &commit_cb, NULL); | ||
1814 | ret = 1; | ||
1815 | return; | ||
1816 | } | ||
1817 | if (GNUNET_OK != get_identity_for_string (tmp + 1, &next_zone_key)) | ||
1818 | { | ||
1819 | fprintf (stderr, "Error parsing zone name `%s'\n", tmp + 1); | ||
1820 | ret = 1; | ||
1821 | GNUNET_SCHEDULER_shutdown (); | ||
1822 | return; | ||
1823 | } | ||
1824 | *tmp = '\0'; | ||
1825 | have_next_zonekey = GNUNET_YES; | ||
1826 | /* Run a command for the previous record set */ | ||
1827 | if (NULL != recordset) | ||
1828 | { | ||
1829 | run_with_zone_pkey (cfg); | ||
1830 | return; | ||
1831 | } | ||
1832 | zone_pkey = next_zone_key; | ||
1833 | if (NULL != name) | ||
1834 | GNUNET_free (name); | ||
1835 | name = GNUNET_strdup (next_name); | ||
1836 | zonekey_set = GNUNET_YES; | ||
1837 | continue; | ||
1838 | } | ||
1839 | if (GNUNET_NO == zonekey_set) | ||
1840 | { | ||
1841 | fprintf (stderr, "Warning, encountered recordline without zone\n"); | ||
1842 | continue; | ||
1843 | } | ||
1844 | parse_recordline (buf); | ||
1845 | } | ||
1846 | if (GNUNET_NO == finished) | ||
1847 | { | ||
1848 | if (NULL != recordset) | ||
1849 | { | ||
1850 | if (GNUNET_YES == zonekey_set) | ||
1851 | { | ||
1852 | run_with_zone_pkey (cfg); /** one last time **/ | ||
1853 | finished = GNUNET_YES; | ||
1854 | return; | ||
1855 | } | ||
1856 | fprintf (stderr, "Warning, encountered recordline without zone\n"); | ||
1857 | } | ||
1858 | } | ||
1859 | ns_qe = GNUNET_NAMESTORE_transaction_commit (ns, &commit_cb, NULL); | ||
1860 | return; | ||
1861 | } | ||
1862 | |||
1863 | |||
1864 | static void | ||
1865 | begin_cb (void *cls, enum GNUNET_ErrorCode ec) | ||
1866 | { | ||
1867 | ns_qe = NULL; | ||
1868 | if (GNUNET_EC_NONE != ec) | ||
1869 | { | ||
1870 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
1871 | "Failed to start transaction: %s\n", | ||
1872 | GNUNET_ErrorCode_get_hint (ec)); | ||
1873 | GNUNET_SCHEDULER_shutdown (); | ||
1874 | return; | ||
1875 | } | ||
1876 | if (read_from_stdin) | ||
1877 | { | ||
1878 | process_command_stdin (); | ||
1879 | return; | ||
1880 | } | ||
1881 | run_with_zone_pkey (cfg); | ||
1882 | } | ||
1883 | |||
1884 | |||
1885 | /** | ||
1886 | * Function called with ALL of the egos known to the | ||
1887 | * identity service, used on startup if the user did | ||
1888 | * not specify a zone on the command-line. | ||
1889 | * Once the iteration is done (@a ego is NULL), we | ||
1890 | * ask for the default ego for "namestore". | ||
1891 | * | ||
1892 | * @param cls a `struct GNUNET_CONFIGURATION_Handle` | ||
1893 | * @param ego an ego, NULL for end of iteration | ||
1894 | * @param ctx NULL | ||
1895 | * @param name name associated with @a ego | ||
1896 | */ | ||
1897 | static void | ||
1898 | id_connect_cb (void *cls, | ||
1899 | struct GNUNET_IDENTITY_Ego *ego, | ||
1900 | void **ctx, | ||
1901 | const char *name) | ||
1902 | { | ||
1903 | struct GNUNET_CRYPTO_PublicKey pk; | ||
1904 | struct EgoEntry *ego_entry; | ||
1905 | |||
1906 | (void) ctx; | ||
1907 | (void) name; | ||
1908 | if ((NULL != name) && (NULL != ego)) | ||
1909 | { | ||
1910 | ego_entry = GNUNET_new (struct EgoEntry); | ||
1911 | GNUNET_IDENTITY_ego_get_public_key (ego, &pk); | ||
1912 | ego_entry->ego = ego; | ||
1913 | ego_entry->identifier = GNUNET_strdup (name); | ||
1914 | GNUNET_CONTAINER_DLL_insert_tail (ego_head, | ||
1915 | ego_tail, | ||
1916 | ego_entry); | ||
1917 | if ((NULL != ego_name) && | ||
1918 | (0 == strcmp (name, ego_name))) | ||
1919 | zone_pkey = *GNUNET_IDENTITY_ego_get_private_key (ego); | ||
1920 | return; | ||
1921 | } | ||
1922 | if (NULL != ego) | ||
1923 | return; | ||
1924 | ns_qe = GNUNET_NAMESTORE_transaction_begin (ns, &begin_cb, (void *) cfg); | ||
1925 | } | ||
1926 | |||
1927 | |||
1928 | |||
1929 | |||
1930 | |||
1931 | /** | ||
1932 | * Main function that will be run. | ||
1933 | * | ||
1934 | * @param cls closure | ||
1935 | * @param args remaining command-line arguments | ||
1936 | * @param cfgfile name of the configuration file used (for saving, can be NULL!) | ||
1937 | * @param cfg configuration | ||
1938 | */ | ||
1939 | static void | ||
1940 | run (void *cls, | ||
1941 | char *const *args, | ||
1942 | const char *cfgfile, | ||
1943 | const struct GNUNET_CONFIGURATION_Handle *_cfg) | ||
1944 | { | ||
1945 | (void) cls; | ||
1946 | (void) args; | ||
1947 | (void) cfgfile; | ||
1948 | cfg = _cfg; | ||
1949 | if (NULL != args[0]) | ||
1950 | GNUNET_log ( | ||
1951 | GNUNET_ERROR_TYPE_WARNING, | ||
1952 | _ ("Superfluous command line arguments (starting with `%s') ignored\n"), | ||
1953 | args[0]); | ||
1954 | |||
1955 | GNUNET_SCHEDULER_add_shutdown (&do_shutdown, (void *) cfg); | ||
1956 | ns = GNUNET_NAMESTORE_connect (cfg); | ||
1957 | if (NULL == ns) | ||
1958 | { | ||
1959 | fprintf (stderr, _ ("Failed to connect to namestore\n")); | ||
1960 | GNUNET_SCHEDULER_shutdown (); | ||
1961 | return; | ||
1962 | } | ||
1963 | idh = GNUNET_IDENTITY_connect (cfg, &id_connect_cb, (void *) cfg); | ||
1964 | if (NULL == idh) | ||
1965 | { | ||
1966 | ret = -1; | ||
1967 | fprintf (stderr, _ ("Cannot connect to identity service\n")); | ||
1968 | GNUNET_SCHEDULER_shutdown (); | ||
1969 | } | ||
1970 | } | ||
1971 | |||
1972 | |||
1973 | |||
1974 | /** | ||
1975 | * The main function for gnunet-namestore. | ||
1976 | * | ||
1977 | * @param argc number of arguments from the command line | ||
1978 | * @param argv command line arguments | ||
1979 | * @return 0 ok, 1 on error | ||
1980 | */ | ||
1981 | int | ||
1982 | main (int argc, char *const *argv) | ||
1983 | { | ||
1984 | int lret; | ||
1985 | struct GNUNET_GETOPT_CommandLineOption options[] = | ||
1986 | { GNUNET_GETOPT_option_flag ('a', "add", gettext_noop ("add record"), &add), | ||
1987 | GNUNET_GETOPT_option_flag ('d', | ||
1988 | "delete", | ||
1989 | gettext_noop ("delete record"), | ||
1990 | &del), | ||
1991 | GNUNET_GETOPT_option_flag ('D', | ||
1992 | "display", | ||
1993 | gettext_noop ("display records"), | ||
1994 | &list), | ||
1995 | GNUNET_GETOPT_option_flag ('S', | ||
1996 | "from-stdin", | ||
1997 | gettext_noop ("read commands from stdin"), | ||
1998 | &read_from_stdin), | ||
1999 | GNUNET_GETOPT_option_string ( | ||
2000 | 'e', | ||
2001 | "expiration", | ||
2002 | "TIME", | ||
2003 | gettext_noop ( | ||
2004 | "expiration time for record to use (for adding only), \"never\" is possible"), | ||
2005 | &expirationstring), | ||
2006 | GNUNET_GETOPT_option_string ('i', | ||
2007 | "nick", | ||
2008 | "NICKNAME", | ||
2009 | gettext_noop ( | ||
2010 | "set the desired nick name for the zone"), | ||
2011 | &nickstring), | ||
2012 | GNUNET_GETOPT_option_flag ('m', | ||
2013 | "monitor", | ||
2014 | gettext_noop ( | ||
2015 | "monitor changes in the namestore"), | ||
2016 | &monitor), | ||
2017 | GNUNET_GETOPT_option_string ('n', | ||
2018 | "name", | ||
2019 | "NAME", | ||
2020 | gettext_noop ( | ||
2021 | "name of the record to add/delete/display"), | ||
2022 | &name), | ||
2023 | GNUNET_GETOPT_option_flag ('r', | ||
2024 | "recordline", | ||
2025 | gettext_noop ("Output in recordline format"), | ||
2026 | &output_recordline), | ||
2027 | GNUNET_GETOPT_option_string ('Z', | ||
2028 | "zone-to-name", | ||
2029 | "KEY", | ||
2030 | gettext_noop ( | ||
2031 | "determine our name for the given KEY"), | ||
2032 | &reverse_pkey), | ||
2033 | GNUNET_GETOPT_option_string ('t', | ||
2034 | "type", | ||
2035 | "TYPE", | ||
2036 | gettext_noop ( | ||
2037 | "type of the record to add/delete/display"), | ||
2038 | &typestring), | ||
2039 | GNUNET_GETOPT_option_string ('u', | ||
2040 | "uri", | ||
2041 | "URI", | ||
2042 | gettext_noop ("URI to import into our zone"), | ||
2043 | &uri), | ||
2044 | GNUNET_GETOPT_option_string ('V', | ||
2045 | "value", | ||
2046 | "VALUE", | ||
2047 | gettext_noop ( | ||
2048 | "value of the record to add/delete"), | ||
2049 | &value), | ||
2050 | GNUNET_GETOPT_option_flag ('p', | ||
2051 | "public", | ||
2052 | gettext_noop ("create or list public record"), | ||
2053 | &is_public), | ||
2054 | GNUNET_GETOPT_option_flag ('o', | ||
2055 | "omit-private", | ||
2056 | gettext_noop ("omit private records"), | ||
2057 | &omit_private), | ||
2058 | GNUNET_GETOPT_option_flag ('T', | ||
2059 | "include-maintenance", | ||
2060 | gettext_noop ( | ||
2061 | "do not filter maintenance records"), | ||
2062 | &include_maintenance), | ||
2063 | GNUNET_GETOPT_option_flag ('P', | ||
2064 | "purge-orphans", | ||
2065 | gettext_noop ( | ||
2066 | "purge namestore of all orphans"), | ||
2067 | &purge_orphaned), | ||
2068 | GNUNET_GETOPT_option_flag ('O', | ||
2069 | "list-orphans", | ||
2070 | gettext_noop ( | ||
2071 | "show private key for orphaned records for recovery using `gnunet-identity -C -P <key>'. Use in combination with --display"), | ||
2072 | &list_orphaned), | ||
2073 | GNUNET_GETOPT_option_flag ('X', | ||
2074 | "purge-zone-records", | ||
2075 | gettext_noop ( | ||
2076 | "delete all records in specified zone"), | ||
2077 | &purge_zone), | ||
2078 | GNUNET_GETOPT_option_flag ( | ||
2079 | 's', | ||
2080 | "shadow", | ||
2081 | gettext_noop ( | ||
2082 | "create shadow record (only valid if all other records of the same type have expired"), | ||
2083 | &is_shadow), | ||
2084 | GNUNET_GETOPT_option_string ('z', | ||
2085 | "zone", | ||
2086 | "EGO", | ||
2087 | gettext_noop ( | ||
2088 | "name of the ego controlling the zone"), | ||
2089 | &ego_name), | ||
2090 | GNUNET_GETOPT_OPTION_END }; | ||
2091 | |||
2092 | |||
2093 | if (GNUNET_OK != GNUNET_STRINGS_get_utf8_args (argc, argv, &argc, &argv)) | ||
2094 | return 2; | ||
2095 | |||
2096 | is_public = -1; | ||
2097 | is_shadow = -1; | ||
2098 | GNUNET_log_setup ("gnunet-namestore", "WARNING", NULL); | ||
2099 | if (GNUNET_OK != | ||
2100 | (lret = GNUNET_PROGRAM_run (argc, | ||
2101 | argv, | ||
2102 | "gnunet-namestore", | ||
2103 | _ ("GNUnet zone manipulation tool"), | ||
2104 | options, | ||
2105 | &run, | ||
2106 | NULL))) | ||
2107 | { | ||
2108 | GNUNET_free_nz ((void *) argv); | ||
2109 | // FIXME | ||
2110 | // GNUNET_CRYPTO_ecdsa_key_clear (&zone_pkey); | ||
2111 | return lret; | ||
2112 | } | ||
2113 | GNUNET_free_nz ((void *) argv); | ||
2114 | // FIXME | ||
2115 | // GNUNET_CRYPTO_ecdsa_key_clear (&zone_pkey); | ||
2116 | return ret; | ||
2117 | } | ||
2118 | |||
2119 | |||
2120 | /* 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 26de295bf..000000000 --- a/src/namestore/gnunet-service-namestore.c +++ /dev/null | |||
@@ -1,2752 +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_gns_service.h" | ||
30 | #include "gnunet_namestore_service.h" | ||
31 | #include "gnunet_namestore_plugin.h" | ||
32 | #include "gnunet_statistics_service.h" | ||
33 | #include "gnunet_signatures.h" | ||
34 | #include "namestore.h" | ||
35 | |||
36 | #define LOG_STRERROR_FILE(kind, syscall, filename) \ | ||
37 | GNUNET_log_from_strerror_file (kind, "util", syscall, filename) | ||
38 | |||
39 | /** | ||
40 | * If a monitor takes more than 1 minute to process an event, print a warning. | ||
41 | */ | ||
42 | #define MONITOR_STALL_WARN_DELAY GNUNET_TIME_UNIT_MINUTES | ||
43 | |||
44 | /** | ||
45 | * Size of the cache used by #get_nick_record() | ||
46 | */ | ||
47 | #define NC_SIZE 16 | ||
48 | |||
49 | /** | ||
50 | * A namestore client | ||
51 | */ | ||
52 | struct NamestoreClient; | ||
53 | |||
54 | |||
55 | /** | ||
56 | * A namestore iteration operation. | ||
57 | */ | ||
58 | struct ZoneIteration | ||
59 | { | ||
60 | /** | ||
61 | * Next element in the DLL | ||
62 | */ | ||
63 | struct ZoneIteration *next; | ||
64 | |||
65 | /** | ||
66 | * Previous element in the DLL | ||
67 | */ | ||
68 | struct ZoneIteration *prev; | ||
69 | |||
70 | /** | ||
71 | * Namestore client which intiated this zone iteration | ||
72 | */ | ||
73 | struct NamestoreClient *nc; | ||
74 | |||
75 | /** | ||
76 | * The nick to add to the records | ||
77 | */ | ||
78 | struct GNUNET_GNSRECORD_Data *nick; | ||
79 | |||
80 | /** | ||
81 | * Key of the zone we are iterating over. | ||
82 | */ | ||
83 | struct GNUNET_CRYPTO_PrivateKey zone; | ||
84 | |||
85 | /** | ||
86 | * The record set filter | ||
87 | */ | ||
88 | enum GNUNET_GNSRECORD_Filter filter; | ||
89 | |||
90 | /** | ||
91 | * Last sequence number in the zone iteration used to address next | ||
92 | * result of the zone iteration in the store | ||
93 | * | ||
94 | * Initially set to 0. | ||
95 | * Updated in #zone_iterate_proc() | ||
96 | */ | ||
97 | uint64_t seq; | ||
98 | |||
99 | /** | ||
100 | * The operation id for the zone iteration in the response for the client | ||
101 | */ | ||
102 | uint32_t request_id; | ||
103 | |||
104 | /** | ||
105 | * Offset of the zone iteration used to address next result of the zone | ||
106 | * iteration in the store | ||
107 | * | ||
108 | * Initially set to 0 in #handle_iteration_start | ||
109 | * Incremented with by every call to #handle_iteration_next | ||
110 | */ | ||
111 | uint32_t offset; | ||
112 | |||
113 | /** | ||
114 | * Number of pending cache operations triggered by this zone iteration which we | ||
115 | * need to wait for before allowing the client to continue. | ||
116 | */ | ||
117 | unsigned int cache_ops; | ||
118 | |||
119 | /** | ||
120 | * Set to #GNUNET_YES if the last iteration exhausted the limit set by the | ||
121 | * client and we should send the #GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_RESULT_END | ||
122 | * message and free the data structure once @e cache_ops is zero. | ||
123 | */ | ||
124 | int send_end; | ||
125 | }; | ||
126 | |||
127 | /** | ||
128 | * A namestore client | ||
129 | */ | ||
130 | struct NamestoreClient | ||
131 | { | ||
132 | /** | ||
133 | * The client | ||
134 | */ | ||
135 | struct GNUNET_SERVICE_Client *client; | ||
136 | |||
137 | /** | ||
138 | * Database handle for client | ||
139 | */ | ||
140 | struct GNUNET_NAMESTORE_PluginFunctions *GSN_database; | ||
141 | |||
142 | /** | ||
143 | * Name of loaded plugin (neeed for cleanup) | ||
144 | */ | ||
145 | char *db_lib_name; | ||
146 | |||
147 | /** | ||
148 | * GNUNET_YES if this nc has begun a transaction which is uncommited. | ||
149 | */ | ||
150 | int in_transaction; | ||
151 | |||
152 | /** | ||
153 | * Message queue for transmission to @e client | ||
154 | */ | ||
155 | struct GNUNET_MQ_Handle *mq; | ||
156 | |||
157 | /** | ||
158 | * Head of the DLL of | ||
159 | * Zone iteration operations in progress initiated by this client | ||
160 | */ | ||
161 | struct ZoneIteration *op_head; | ||
162 | |||
163 | /** | ||
164 | * Tail of the DLL of | ||
165 | * Zone iteration operations in progress initiated by this client | ||
166 | */ | ||
167 | struct ZoneIteration *op_tail; | ||
168 | }; | ||
169 | |||
170 | |||
171 | /** | ||
172 | * A namestore monitor. | ||
173 | */ | ||
174 | struct ZoneMonitor | ||
175 | { | ||
176 | /** | ||
177 | * Next element in the DLL | ||
178 | */ | ||
179 | struct ZoneMonitor *next; | ||
180 | |||
181 | /** | ||
182 | * Previous element in the DLL | ||
183 | */ | ||
184 | struct ZoneMonitor *prev; | ||
185 | |||
186 | /** | ||
187 | * Namestore client which intiated this zone monitor | ||
188 | */ | ||
189 | struct NamestoreClient *nc; | ||
190 | |||
191 | /** | ||
192 | * Private key of the zone. | ||
193 | */ | ||
194 | struct GNUNET_CRYPTO_PrivateKey zone; | ||
195 | |||
196 | /** | ||
197 | * The record set filter | ||
198 | */ | ||
199 | enum GNUNET_GNSRECORD_Filter filter; | ||
200 | |||
201 | /** | ||
202 | * Task active during initial iteration. | ||
203 | */ | ||
204 | struct GNUNET_SCHEDULER_Task *task; | ||
205 | |||
206 | /** | ||
207 | * Task to warn about slow monitors. | ||
208 | */ | ||
209 | struct GNUNET_SCHEDULER_Task *sa_wait_warning; | ||
210 | |||
211 | /** | ||
212 | * Since when are we blocked on this monitor? | ||
213 | */ | ||
214 | struct GNUNET_TIME_Absolute sa_waiting_start; | ||
215 | |||
216 | /** | ||
217 | * Last sequence number in the zone iteration used to address next | ||
218 | * result of the zone iteration in the store | ||
219 | * | ||
220 | * Initially set to 0. | ||
221 | * Updated in #monitor_iterate_cb() | ||
222 | */ | ||
223 | uint64_t seq; | ||
224 | |||
225 | /** | ||
226 | * Current limit of how many more messages we are allowed | ||
227 | * to queue to this monitor. | ||
228 | */ | ||
229 | uint64_t limit; | ||
230 | |||
231 | /** | ||
232 | * How many more requests may we receive from the iterator | ||
233 | * before it is at the limit we gave it? Will be below or | ||
234 | * equal to @e limit. The effective limit for monitor | ||
235 | * events is thus @e iteration_cnt - @e limit! | ||
236 | */ | ||
237 | uint64_t iteration_cnt; | ||
238 | |||
239 | /** | ||
240 | * Are we (still) in the initial iteration pass? | ||
241 | */ | ||
242 | int in_first_iteration; | ||
243 | |||
244 | /** | ||
245 | * Run again because we skipped an orphan | ||
246 | */ | ||
247 | int run_again; | ||
248 | |||
249 | /** | ||
250 | * Is there a store activity waiting for this monitor? We only raise the | ||
251 | * flag when it happens and search the DLL for the store activity when we | ||
252 | * had a limit increase. If we cannot find any waiting store activity at | ||
253 | * that time, we clear the flag again. | ||
254 | */ | ||
255 | int sa_waiting; | ||
256 | }; | ||
257 | |||
258 | |||
259 | |||
260 | /** | ||
261 | * Information for an ongoing #handle_record_store() operation. | ||
262 | * Needed as we may wait for monitors to be ready for the notification. | ||
263 | */ | ||
264 | struct StoreActivity | ||
265 | { | ||
266 | /** | ||
267 | * Kept in a DLL. | ||
268 | */ | ||
269 | struct StoreActivity *next; | ||
270 | |||
271 | /** | ||
272 | * Kept in a DLL. | ||
273 | */ | ||
274 | struct StoreActivity *prev; | ||
275 | |||
276 | /** | ||
277 | * Which client triggered the store activity? | ||
278 | */ | ||
279 | struct NamestoreClient *nc; | ||
280 | |||
281 | /** | ||
282 | * The request ID | ||
283 | */ | ||
284 | uint32_t rid; | ||
285 | |||
286 | /** | ||
287 | * The currently processed record | ||
288 | */ | ||
289 | uint16_t rd_set_pos; | ||
290 | |||
291 | /** | ||
292 | * The number of records in this activity | ||
293 | */ | ||
294 | uint16_t rd_set_count; | ||
295 | |||
296 | /** | ||
297 | * Wheather or not this store action is already commited. | ||
298 | * The store activity will not be processed unless this field is GNUNET_YES | ||
299 | */ | ||
300 | int uncommited; | ||
301 | |||
302 | /** | ||
303 | * The zone private key | ||
304 | */ | ||
305 | struct GNUNET_CRYPTO_PrivateKey private_key; | ||
306 | |||
307 | /** | ||
308 | * Copy of the original record set (as data fields in @e rd will | ||
309 | * point into it!). | ||
310 | */ | ||
311 | const struct RecordSet *rs; | ||
312 | |||
313 | /** | ||
314 | * Next zone monitor that still needs to be notified about this PUT. | ||
315 | */ | ||
316 | struct ZoneMonitor *zm_pos; | ||
317 | |||
318 | }; | ||
319 | |||
320 | |||
321 | /** | ||
322 | * Entry in list of cached nick resolutions. | ||
323 | */ | ||
324 | struct NickCache | ||
325 | { | ||
326 | /** | ||
327 | * Zone the cache entry is for. | ||
328 | */ | ||
329 | struct GNUNET_CRYPTO_PrivateKey zone; | ||
330 | |||
331 | /** | ||
332 | * Cached record data. | ||
333 | */ | ||
334 | struct GNUNET_GNSRECORD_Data *rd; | ||
335 | |||
336 | /** | ||
337 | * Timestamp when this cache entry was used last. | ||
338 | */ | ||
339 | struct GNUNET_TIME_Absolute last_used; | ||
340 | }; | ||
341 | |||
342 | /** | ||
343 | * We cache nick records to reduce DB load. | ||
344 | */ | ||
345 | static struct NickCache nick_cache[NC_SIZE]; | ||
346 | |||
347 | /** | ||
348 | * Public key of all zeros. | ||
349 | */ | ||
350 | static const struct GNUNET_CRYPTO_PrivateKey zero; | ||
351 | |||
352 | /** | ||
353 | * Configuration handle. | ||
354 | */ | ||
355 | static const struct GNUNET_CONFIGURATION_Handle *GSN_cfg; | ||
356 | |||
357 | /** | ||
358 | * Handle to the statistics service | ||
359 | */ | ||
360 | static struct GNUNET_STATISTICS_Handle *statistics; | ||
361 | |||
362 | /** | ||
363 | * Name of the database plugin | ||
364 | */ | ||
365 | static char *db_lib_name; | ||
366 | |||
367 | /** | ||
368 | * Database handle for service | ||
369 | */ | ||
370 | struct GNUNET_NAMESTORE_PluginFunctions *GSN_database; | ||
371 | |||
372 | |||
373 | /** | ||
374 | * First active zone monitor. | ||
375 | */ | ||
376 | static struct ZoneMonitor *monitor_head; | ||
377 | |||
378 | /** | ||
379 | * Last active zone monitor. | ||
380 | */ | ||
381 | static struct ZoneMonitor *monitor_tail; | ||
382 | |||
383 | /** | ||
384 | * Head of DLL of monitor-blocked store activities. | ||
385 | */ | ||
386 | static struct StoreActivity *sa_head; | ||
387 | |||
388 | /** | ||
389 | * Tail of DLL of monitor-blocked store activities. | ||
390 | */ | ||
391 | static struct StoreActivity *sa_tail; | ||
392 | |||
393 | /** | ||
394 | * Notification context shared by all monitors. | ||
395 | */ | ||
396 | static struct GNUNET_NotificationContext *monitor_nc; | ||
397 | |||
398 | /** | ||
399 | * Returned orphaned records? | ||
400 | */ | ||
401 | static int return_orphaned; | ||
402 | |||
403 | /** | ||
404 | * Task run during shutdown. | ||
405 | * | ||
406 | * @param cls unused | ||
407 | */ | ||
408 | static void | ||
409 | cleanup_task (void *cls) | ||
410 | { | ||
411 | (void) cls; | ||
412 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Stopping namestore service\n"); | ||
413 | if (NULL != monitor_nc) | ||
414 | { | ||
415 | GNUNET_notification_context_destroy (monitor_nc); | ||
416 | monitor_nc = NULL; | ||
417 | } | ||
418 | if (NULL != statistics) | ||
419 | { | ||
420 | GNUNET_STATISTICS_destroy (statistics, GNUNET_NO); | ||
421 | statistics = NULL; | ||
422 | } | ||
423 | GNUNET_break (NULL == GNUNET_PLUGIN_unload (db_lib_name, GSN_database)); | ||
424 | GNUNET_free (db_lib_name); | ||
425 | db_lib_name = NULL; | ||
426 | } | ||
427 | |||
428 | |||
429 | /** | ||
430 | * Release memory used by @a sa. | ||
431 | * | ||
432 | * @param sa activity to free | ||
433 | */ | ||
434 | static void | ||
435 | free_store_activity (struct StoreActivity *sa) | ||
436 | { | ||
437 | GNUNET_CONTAINER_DLL_remove (sa_head, sa_tail, sa); | ||
438 | GNUNET_free (sa); | ||
439 | } | ||
440 | |||
441 | /** | ||
442 | * Function called with the records for the #GNUNET_GNS_EMPTY_LABEL_AT | ||
443 | * label in the zone. Used to locate the #GNUNET_GNSRECORD_TYPE_NICK | ||
444 | * record, which (if found) is then copied to @a cls for future use. | ||
445 | * | ||
446 | * @param cls a `struct GNUNET_GNSRECORD_Data **` for storing the nick (if found) | ||
447 | * @param seq sequence number of the record, MUST NOT BE ZERO | ||
448 | * @param private_key the private key of the zone (unused) | ||
449 | * @param label should be #GNUNET_GNS_EMPTY_LABEL_AT | ||
450 | * @param rd_count number of records in @a rd | ||
451 | * @param rd records stored under @a label in the zone | ||
452 | */ | ||
453 | static void | ||
454 | lookup_nick_it (void *cls, | ||
455 | uint64_t seq, | ||
456 | const struct GNUNET_CRYPTO_PrivateKey *private_key, | ||
457 | const char *label, | ||
458 | unsigned int rd_count, | ||
459 | const struct GNUNET_GNSRECORD_Data *rd) | ||
460 | { | ||
461 | struct GNUNET_GNSRECORD_Data **res = cls; | ||
462 | |||
463 | (void) private_key; | ||
464 | GNUNET_assert (0 != seq); | ||
465 | if (0 != strcmp (label, GNUNET_GNS_EMPTY_LABEL_AT)) | ||
466 | { | ||
467 | GNUNET_break (0); | ||
468 | return; | ||
469 | } | ||
470 | for (unsigned int c = 0; c < rd_count; c++) | ||
471 | { | ||
472 | if (GNUNET_GNSRECORD_TYPE_NICK == rd[c].record_type) | ||
473 | { | ||
474 | (*res) = | ||
475 | GNUNET_malloc (rd[c].data_size + sizeof(struct GNUNET_GNSRECORD_Data)); | ||
476 | (*res)->data = &(*res)[1]; | ||
477 | GNUNET_memcpy ((void *) (*res)->data, rd[c].data, rd[c].data_size); | ||
478 | (*res)->data_size = rd[c].data_size; | ||
479 | (*res)->expiration_time = rd[c].expiration_time; | ||
480 | (*res)->flags = rd[c].flags; | ||
481 | (*res)->record_type = GNUNET_GNSRECORD_TYPE_NICK; | ||
482 | return; | ||
483 | } | ||
484 | } | ||
485 | (*res) = NULL; | ||
486 | } | ||
487 | |||
488 | |||
489 | /** | ||
490 | * Add entry to the cache for @a zone and @a nick | ||
491 | * | ||
492 | * @param zone zone key to cache under | ||
493 | * @param nick nick entry to cache | ||
494 | */ | ||
495 | static void | ||
496 | cache_nick (const struct GNUNET_CRYPTO_PrivateKey *zone, | ||
497 | const struct GNUNET_GNSRECORD_Data *nick) | ||
498 | { | ||
499 | struct NickCache *oldest; | ||
500 | |||
501 | oldest = NULL; | ||
502 | for (unsigned int i = 0; i < NC_SIZE; i++) | ||
503 | { | ||
504 | struct NickCache *pos = &nick_cache[i]; | ||
505 | |||
506 | if ((NULL == oldest) || | ||
507 | (oldest->last_used.abs_value_us > pos->last_used.abs_value_us)) | ||
508 | oldest = pos; | ||
509 | if (0 == GNUNET_memcmp (zone, &pos->zone)) | ||
510 | { | ||
511 | oldest = pos; | ||
512 | break; | ||
513 | } | ||
514 | } | ||
515 | GNUNET_free (oldest->rd); | ||
516 | oldest->zone = *zone; | ||
517 | if (NULL != nick) | ||
518 | { | ||
519 | oldest->rd = GNUNET_malloc (sizeof(*nick) + nick->data_size); | ||
520 | *oldest->rd = *nick; | ||
521 | oldest->rd->data = &oldest->rd[1]; | ||
522 | memcpy (&oldest->rd[1], nick->data, nick->data_size); | ||
523 | } | ||
524 | else | ||
525 | { | ||
526 | oldest->rd = NULL; | ||
527 | } | ||
528 | oldest->last_used = GNUNET_TIME_absolute_get (); | ||
529 | } | ||
530 | |||
531 | |||
532 | /** | ||
533 | * Return the NICK record for the zone (if it exists). | ||
534 | * | ||
535 | * @param nc the namestore client | ||
536 | * @param zone private key for the zone to look for nick | ||
537 | * @return NULL if no NICK record was found | ||
538 | */ | ||
539 | static struct GNUNET_GNSRECORD_Data * | ||
540 | get_nick_record (const struct GNUNET_CRYPTO_PrivateKey *zone) | ||
541 | { | ||
542 | struct GNUNET_CRYPTO_PublicKey pub; | ||
543 | struct GNUNET_GNSRECORD_Data *nick; | ||
544 | int res; | ||
545 | |||
546 | /* check cache first */ | ||
547 | for (unsigned int i = 0; i < NC_SIZE; i++) | ||
548 | { | ||
549 | struct NickCache *pos = &nick_cache[i]; | ||
550 | if ((NULL != pos->rd) && (0 == GNUNET_memcmp (zone, &pos->zone))) | ||
551 | { | ||
552 | if (NULL == pos->rd) | ||
553 | return NULL; | ||
554 | nick = GNUNET_malloc (sizeof(*nick) + pos->rd->data_size); | ||
555 | *nick = *pos->rd; | ||
556 | nick->data = &nick[1]; | ||
557 | memcpy (&nick[1], pos->rd->data, pos->rd->data_size); | ||
558 | pos->last_used = GNUNET_TIME_absolute_get (); | ||
559 | return nick; | ||
560 | } | ||
561 | } | ||
562 | |||
563 | nick = NULL; | ||
564 | res = GSN_database->lookup_records (GSN_database->cls, | ||
565 | zone, | ||
566 | GNUNET_GNS_EMPTY_LABEL_AT, | ||
567 | &lookup_nick_it, | ||
568 | &nick); | ||
569 | if ((GNUNET_OK != res) || (NULL == nick)) | ||
570 | { | ||
571 | #if ! defined(GNUNET_CULL_LOGGING) | ||
572 | static int do_log = GNUNET_LOG_CALL_STATUS; | ||
573 | |||
574 | if (0 == do_log) | ||
575 | do_log = GNUNET_get_log_call_status (GNUNET_ERROR_TYPE_DEBUG, | ||
576 | "namestore", | ||
577 | __FILE__, | ||
578 | __FUNCTION__, | ||
579 | __LINE__); | ||
580 | if (1 == do_log) | ||
581 | { | ||
582 | GNUNET_CRYPTO_key_get_public (zone, &pub); | ||
583 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG | GNUNET_ERROR_TYPE_BULK, | ||
584 | "No nick name set for zone `%s'\n", | ||
585 | GNUNET_GNSRECORD_z2s (&pub)); | ||
586 | } | ||
587 | #endif | ||
588 | /* update cache */ | ||
589 | cache_nick (zone, NULL); | ||
590 | return NULL; | ||
591 | } | ||
592 | |||
593 | /* update cache */ | ||
594 | cache_nick (zone, nick); | ||
595 | return nick; | ||
596 | } | ||
597 | |||
598 | |||
599 | /** | ||
600 | * Merge the nick record @a nick_rd with the rest of the | ||
601 | * record set given in @a rd2. Store the result in @a rdc_res | ||
602 | * and @a rd_res. The @a nick_rd's expiration time is set to | ||
603 | * the maximum expiration time of all of the records in @a rd2. | ||
604 | * | ||
605 | * @param nick_rd the nick record to integrate | ||
606 | * @param rd2_length length of the @a rd2 array | ||
607 | * @param rd2 array of records | ||
608 | * @param[out] rdc_res length of the resulting @a rd_res array | ||
609 | * @param[out] rd_res set to an array of records, | ||
610 | * including @a nick_rd and @a rd2; | ||
611 | * all of the variable-size 'data' fields in @a rd2 are | ||
612 | * allocated in the same chunk of memory! | ||
613 | */ | ||
614 | static void | ||
615 | merge_with_nick_records (const struct GNUNET_GNSRECORD_Data *nick_rd, | ||
616 | unsigned int rd2_length, | ||
617 | const struct GNUNET_GNSRECORD_Data *rd2, | ||
618 | unsigned int *rdc_res, | ||
619 | struct GNUNET_GNSRECORD_Data **rd_res) | ||
620 | { | ||
621 | uint64_t latest_expiration; | ||
622 | size_t req; | ||
623 | char *data; | ||
624 | size_t data_offset; | ||
625 | struct GNUNET_GNSRECORD_Data *target; | ||
626 | |||
627 | (*rdc_res) = 1 + rd2_length; | ||
628 | if (0 == 1 + rd2_length) | ||
629 | { | ||
630 | GNUNET_break (0); | ||
631 | (*rd_res) = NULL; | ||
632 | return; | ||
633 | } | ||
634 | req = sizeof(struct GNUNET_GNSRECORD_Data) + nick_rd->data_size; | ||
635 | for (unsigned int i = 0; i < rd2_length; i++) | ||
636 | { | ||
637 | const struct GNUNET_GNSRECORD_Data *orig = &rd2[i]; | ||
638 | |||
639 | if (req + sizeof(struct GNUNET_GNSRECORD_Data) + orig->data_size < req) | ||
640 | { | ||
641 | GNUNET_break (0); | ||
642 | (*rd_res) = NULL; | ||
643 | return; | ||
644 | } | ||
645 | req += sizeof(struct GNUNET_GNSRECORD_Data) + orig->data_size; | ||
646 | } | ||
647 | target = GNUNET_malloc (req); | ||
648 | (*rd_res) = target; | ||
649 | data = (char *) &target[1 + rd2_length]; | ||
650 | data_offset = 0; | ||
651 | latest_expiration = 0; | ||
652 | for (unsigned int i = 0; i < rd2_length; i++) | ||
653 | { | ||
654 | const struct GNUNET_GNSRECORD_Data *orig = &rd2[i]; | ||
655 | |||
656 | if (0 != (orig->flags & GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION)) | ||
657 | { | ||
658 | if ((GNUNET_TIME_absolute_get ().abs_value_us + orig->expiration_time) > | ||
659 | latest_expiration) | ||
660 | latest_expiration = orig->expiration_time; | ||
661 | } | ||
662 | else if (orig->expiration_time > latest_expiration) | ||
663 | latest_expiration = orig->expiration_time; | ||
664 | target[i] = *orig; | ||
665 | target[i].data = (void *) &data[data_offset]; | ||
666 | GNUNET_memcpy (&data[data_offset], orig->data, orig->data_size); | ||
667 | data_offset += orig->data_size; | ||
668 | } | ||
669 | /* append nick */ | ||
670 | target[rd2_length] = *nick_rd; | ||
671 | /* Mark as supplemental */ | ||
672 | target[rd2_length].flags = nick_rd->flags | GNUNET_GNSRECORD_RF_SUPPLEMENTAL; | ||
673 | target[rd2_length].expiration_time = latest_expiration; | ||
674 | target[rd2_length].data = (void *) &data[data_offset]; | ||
675 | GNUNET_memcpy (&data[data_offset], nick_rd->data, nick_rd->data_size); | ||
676 | data_offset += nick_rd->data_size; | ||
677 | GNUNET_assert (req == (sizeof(struct GNUNET_GNSRECORD_Data)) * (*rdc_res) | ||
678 | + data_offset); | ||
679 | } | ||
680 | |||
681 | |||
682 | /** | ||
683 | * Generate a `struct LookupNameResponseMessage` and send it to the | ||
684 | * given client using the given notification context. | ||
685 | * | ||
686 | * @param nc client to unicast to | ||
687 | * @param request_id request ID to use | ||
688 | * @param zone_key zone key of the zone | ||
689 | * @param name name | ||
690 | * @param rd_count number of records in @a rd | ||
691 | * @param rd array of records | ||
692 | * @param filter record set filter | ||
693 | */ | ||
694 | static int | ||
695 | send_lookup_response_with_filter (struct NamestoreClient *nc, | ||
696 | uint32_t request_id, | ||
697 | const struct | ||
698 | GNUNET_CRYPTO_PrivateKey *zone_key, | ||
699 | const char *name, | ||
700 | unsigned int rd_count, | ||
701 | const struct GNUNET_GNSRECORD_Data *rd, | ||
702 | enum GNUNET_GNSRECORD_Filter filter) | ||
703 | { | ||
704 | struct GNUNET_MQ_Envelope *env; | ||
705 | struct RecordResultMessage *zir_msg; | ||
706 | struct GNUNET_GNSRECORD_Data *nick; | ||
707 | struct GNUNET_GNSRECORD_Data *res; | ||
708 | struct GNUNET_GNSRECORD_Data rd_nf[rd_count]; | ||
709 | struct GNUNET_TIME_Absolute block_exp = GNUNET_TIME_UNIT_ZERO_ABS;; | ||
710 | unsigned int res_count; | ||
711 | unsigned int rd_nf_count; | ||
712 | size_t name_len; | ||
713 | size_t key_len; | ||
714 | ssize_t rd_ser_len; | ||
715 | char *name_tmp; | ||
716 | char *rd_ser; | ||
717 | char *emsg; | ||
718 | |||
719 | nick = get_nick_record (zone_key); | ||
720 | GNUNET_assert (-1 != GNUNET_GNSRECORD_records_get_size (rd_count, rd)); | ||
721 | |||
722 | if (GNUNET_OK != GNUNET_GNSRECORD_normalize_record_set (name, | ||
723 | rd, | ||
724 | rd_count, | ||
725 | rd_nf, | ||
726 | &rd_nf_count, | ||
727 | &block_exp, | ||
728 | filter, | ||
729 | &emsg)) | ||
730 | { | ||
731 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "%s\n", emsg); | ||
732 | GNUNET_free (emsg); | ||
733 | GNUNET_assert (0); | ||
734 | } | ||
735 | |||
736 | /** | ||
737 | * FIXME if we ever support GNUNET_NAMESTORE_OMIT_PUBLIC, | ||
738 | * we need to omit adding this public record here | ||
739 | */ | ||
740 | if ((NULL != nick) && (0 != strcmp (name, GNUNET_GNS_EMPTY_LABEL_AT))) | ||
741 | { | ||
742 | nick->flags = | ||
743 | (nick->flags | GNUNET_GNSRECORD_RF_PRIVATE) ^ GNUNET_GNSRECORD_RF_PRIVATE; | ||
744 | merge_with_nick_records (nick, rd_nf_count, rd_nf, &res_count, &res); | ||
745 | } | ||
746 | else | ||
747 | { | ||
748 | res_count = rd_nf_count; | ||
749 | res = (struct GNUNET_GNSRECORD_Data *) rd_nf; | ||
750 | } | ||
751 | if (NULL != nick) | ||
752 | GNUNET_free (nick); | ||
753 | |||
754 | if (0 == res_count) | ||
755 | { | ||
756 | if (rd_nf != res) | ||
757 | GNUNET_free (res); | ||
758 | return 0; | ||
759 | } | ||
760 | GNUNET_assert (-1 != GNUNET_GNSRECORD_records_get_size (res_count, res)); | ||
761 | |||
762 | |||
763 | name_len = strlen (name) + 1; | ||
764 | rd_ser_len = GNUNET_GNSRECORD_records_get_size (res_count, res); | ||
765 | if (rd_ser_len < 0) | ||
766 | { | ||
767 | if (rd_nf != res) | ||
768 | GNUNET_free (res); | ||
769 | GNUNET_break (0); | ||
770 | GNUNET_SERVICE_client_drop (nc->client); | ||
771 | return 0; | ||
772 | } | ||
773 | if (((size_t) rd_ser_len) >= UINT16_MAX - name_len - sizeof(*zir_msg)) | ||
774 | { | ||
775 | if (rd_nf != res) | ||
776 | GNUNET_free (res); | ||
777 | GNUNET_break (0); | ||
778 | GNUNET_SERVICE_client_drop (nc->client); | ||
779 | return 0; | ||
780 | } | ||
781 | key_len = GNUNET_CRYPTO_private_key_get_length (zone_key); | ||
782 | env = GNUNET_MQ_msg_extra (zir_msg, | ||
783 | name_len + rd_ser_len + key_len, | ||
784 | GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_RESULT); | ||
785 | zir_msg->gns_header.r_id = htonl (request_id); | ||
786 | zir_msg->name_len = htons (name_len); | ||
787 | zir_msg->rd_count = htons (res_count); | ||
788 | zir_msg->rd_len = htons ((uint16_t) rd_ser_len); | ||
789 | zir_msg->key_len = htons (key_len); | ||
790 | GNUNET_CRYPTO_write_private_key_to_buffer (zone_key, | ||
791 | &zir_msg[1], | ||
792 | key_len); | ||
793 | zir_msg->expire = GNUNET_TIME_absolute_hton (block_exp); | ||
794 | name_tmp = (char *) &zir_msg[1] + key_len; | ||
795 | GNUNET_memcpy (name_tmp, name, name_len); | ||
796 | rd_ser = &name_tmp[name_len]; | ||
797 | GNUNET_assert ( | ||
798 | rd_ser_len == | ||
799 | GNUNET_GNSRECORD_records_serialize (res_count, res, rd_ser_len, rd_ser)); | ||
800 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
801 | "Sending RECORD_RESULT message with %u records\n", | ||
802 | res_count); | ||
803 | GNUNET_STATISTICS_update (statistics, | ||
804 | "Record sets sent to clients", | ||
805 | 1, | ||
806 | GNUNET_NO); | ||
807 | GNUNET_MQ_send (nc->mq, env); | ||
808 | if (rd_nf != res) | ||
809 | GNUNET_free (res); | ||
810 | return res_count; | ||
811 | } | ||
812 | |||
813 | /** | ||
814 | * Send response to the store request to the client. | ||
815 | * | ||
816 | * @param nc client to talk to | ||
817 | * @param ec status of the operation | ||
818 | * @param rid client's request ID | ||
819 | */ | ||
820 | static void | ||
821 | send_store_response (struct NamestoreClient *nc, | ||
822 | enum GNUNET_ErrorCode ec, | ||
823 | uint32_t rid) | ||
824 | { | ||
825 | struct GNUNET_MQ_Envelope *env; | ||
826 | struct RecordStoreResponseMessage *rcr_msg; | ||
827 | |||
828 | GNUNET_assert (NULL != nc); | ||
829 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
830 | "Sending RECORD_STORE_RESPONSE message\n"); | ||
831 | GNUNET_STATISTICS_update (statistics, | ||
832 | "Store requests completed", | ||
833 | 1, | ||
834 | GNUNET_NO); | ||
835 | env = GNUNET_MQ_msg (rcr_msg, | ||
836 | GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_STORE_RESPONSE); | ||
837 | rcr_msg->gns_header.r_id = htonl (rid); | ||
838 | rcr_msg->ec = htonl (ec); | ||
839 | GNUNET_MQ_send (nc->mq, env); | ||
840 | } | ||
841 | |||
842 | |||
843 | /** | ||
844 | * Function called once we are done with the zone iteration and | ||
845 | * allow the zone iteration client to send us more messages. | ||
846 | * | ||
847 | * @param zi zone iteration we are processing | ||
848 | */ | ||
849 | static void | ||
850 | zone_iteration_done_client_continue (struct ZoneIteration *zi) | ||
851 | { | ||
852 | struct GNUNET_MQ_Envelope *env; | ||
853 | struct GNUNET_NAMESTORE_Header *em; | ||
854 | |||
855 | GNUNET_SERVICE_client_continue (zi->nc->client); | ||
856 | if (! zi->send_end) | ||
857 | return; | ||
858 | /* send empty response to indicate end of list */ | ||
859 | env = GNUNET_MQ_msg (em, GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_RESULT_END); | ||
860 | em->r_id = htonl (zi->request_id); | ||
861 | GNUNET_MQ_send (zi->nc->mq, env); | ||
862 | |||
863 | GNUNET_CONTAINER_DLL_remove (zi->nc->op_head, zi->nc->op_tail, zi); | ||
864 | GNUNET_free (zi); | ||
865 | } | ||
866 | |||
867 | |||
868 | |||
869 | |||
870 | /** | ||
871 | * Print a warning that one of our monitors is no longer reacting. | ||
872 | * | ||
873 | * @param cls a `struct ZoneMonitor` to warn about | ||
874 | */ | ||
875 | static void | ||
876 | warn_monitor_slow (void *cls) | ||
877 | { | ||
878 | struct ZoneMonitor *zm = cls; | ||
879 | |||
880 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, | ||
881 | "No response from monitor since %s\n", | ||
882 | GNUNET_STRINGS_absolute_time_to_string (zm->sa_waiting_start)); | ||
883 | zm->sa_wait_warning = GNUNET_SCHEDULER_add_delayed (MONITOR_STALL_WARN_DELAY, | ||
884 | &warn_monitor_slow, | ||
885 | zm); | ||
886 | } | ||
887 | |||
888 | |||
889 | /** | ||
890 | * Continue processing the @a sa. | ||
891 | * | ||
892 | * @param sa store activity to process | ||
893 | */ | ||
894 | static int | ||
895 | continue_store_activity (struct StoreActivity *sa, | ||
896 | int call_continue) | ||
897 | { | ||
898 | const struct RecordSet *rd_set = sa->rs; | ||
899 | unsigned int rd_count; | ||
900 | size_t name_len; | ||
901 | size_t rd_ser_len; | ||
902 | const char *name_tmp; | ||
903 | const char *rd_ser; | ||
904 | const char *buf; | ||
905 | char *conv_name; | ||
906 | |||
907 | // If we are in a transaction, do not notify monitors or update | ||
908 | // cached. This will be done when we are commiting. | ||
909 | if (GNUNET_YES == sa->uncommited) | ||
910 | { | ||
911 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
912 | "Transaction not yet committed, delaying monitor and cache updates\n"); | ||
913 | send_store_response (sa->nc, GNUNET_EC_NONE, sa->rid); | ||
914 | if (GNUNET_YES == call_continue) | ||
915 | GNUNET_SERVICE_client_continue (sa->nc->client); | ||
916 | return GNUNET_OK; | ||
917 | } | ||
918 | buf = (const char *) &sa[1]; | ||
919 | for (int i = sa->rd_set_pos; i < sa->rd_set_count; i++) | ||
920 | { | ||
921 | rd_set = (struct RecordSet *) buf; | ||
922 | name_len = ntohs (rd_set->name_len); | ||
923 | rd_count = ntohs (rd_set->rd_count); | ||
924 | rd_ser_len = ntohs (rd_set->rd_len); | ||
925 | name_tmp = (const char *) &rd_set[1]; | ||
926 | rd_ser = &name_tmp[name_len]; | ||
927 | conv_name = GNUNET_GNSRECORD_string_normalize (name_tmp); | ||
928 | GNUNET_assert (NULL != conv_name); | ||
929 | { | ||
930 | struct GNUNET_GNSRECORD_Data rd[GNUNET_NZL (rd_count)]; | ||
931 | |||
932 | /* We did this before, must succeed again */ | ||
933 | GNUNET_assert ( | ||
934 | GNUNET_OK == | ||
935 | GNUNET_GNSRECORD_records_deserialize (rd_ser_len, rd_ser, rd_count, | ||
936 | rd)); | ||
937 | |||
938 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
939 | "Checking monitors watching for `%s'\n", | ||
940 | conv_name); | ||
941 | for (struct ZoneMonitor *zm = sa->zm_pos; NULL != zm; zm = sa->zm_pos) | ||
942 | { | ||
943 | if ((0 != GNUNET_memcmp (&sa->private_key, &zm->zone)) && | ||
944 | (0 != GNUNET_memcmp (&zm->zone, &zero))) | ||
945 | { | ||
946 | sa->zm_pos = zm->next; /* not interesting to this monitor */ | ||
947 | continue; | ||
948 | } | ||
949 | if (zm->limit == zm->iteration_cnt) | ||
950 | { | ||
951 | zm->sa_waiting = GNUNET_YES; | ||
952 | zm->sa_waiting_start = GNUNET_TIME_absolute_get (); | ||
953 | if (NULL != zm->sa_wait_warning) | ||
954 | GNUNET_SCHEDULER_cancel (zm->sa_wait_warning); | ||
955 | zm->sa_wait_warning = | ||
956 | GNUNET_SCHEDULER_add_delayed (MONITOR_STALL_WARN_DELAY, | ||
957 | &warn_monitor_slow, | ||
958 | zm); | ||
959 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
960 | "Monitor is blocking client for `%s'\n", | ||
961 | conv_name); | ||
962 | GNUNET_free (conv_name); | ||
963 | return GNUNET_NO; /* blocked on zone monitor */ | ||
964 | } | ||
965 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
966 | "Notifying monitor about changes under label `%s'\n", | ||
967 | conv_name); | ||
968 | if (0 < send_lookup_response_with_filter (zm->nc, | ||
969 | 0, | ||
970 | &sa->private_key, | ||
971 | conv_name, | ||
972 | rd_count, | ||
973 | rd, | ||
974 | zm->filter)) | ||
975 | zm->limit--; | ||
976 | sa->zm_pos = zm->next; | ||
977 | } | ||
978 | sa->rd_set_pos++; | ||
979 | GNUNET_free (conv_name); | ||
980 | } | ||
981 | } | ||
982 | if (GNUNET_YES == call_continue) | ||
983 | GNUNET_SERVICE_client_continue (sa->nc->client); | ||
984 | send_store_response (sa->nc, GNUNET_EC_NONE, sa->rid); | ||
985 | free_store_activity (sa); | ||
986 | return GNUNET_OK; | ||
987 | } | ||
988 | |||
989 | |||
990 | /** | ||
991 | * Called whenever a client is disconnected. | ||
992 | * Frees our resources associated with that client. | ||
993 | * | ||
994 | * @param cls closure | ||
995 | * @param client identification of the client | ||
996 | * @param app_ctx the `struct NamestoreClient` of @a client | ||
997 | */ | ||
998 | static void | ||
999 | client_disconnect_cb (void *cls, | ||
1000 | struct GNUNET_SERVICE_Client *client, | ||
1001 | void *app_ctx) | ||
1002 | { | ||
1003 | struct NamestoreClient *nc = app_ctx; | ||
1004 | struct ZoneIteration *no; | ||
1005 | struct StoreActivity *sa = sa_head; | ||
1006 | struct StoreActivity *sn; | ||
1007 | char *emsg; | ||
1008 | |||
1009 | (void) cls; | ||
1010 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Client %p disconnected\n", client); | ||
1011 | if (GNUNET_YES == nc->in_transaction) | ||
1012 | { | ||
1013 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, | ||
1014 | "Client in transaction, rolling back...\n"); | ||
1015 | if (GNUNET_SYSERR == nc->GSN_database->transaction_rollback ( | ||
1016 | nc->GSN_database->cls, | ||
1017 | &emsg)) | ||
1018 | { | ||
1019 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
1020 | "Unable to roll back: %s\n", emsg); | ||
1021 | GNUNET_free (emsg); | ||
1022 | } | ||
1023 | else | ||
1024 | { | ||
1025 | nc->in_transaction = GNUNET_NO; | ||
1026 | while (NULL != sa) | ||
1027 | { | ||
1028 | if ((nc != sa->nc) || | ||
1029 | (GNUNET_NO == sa->uncommited)) | ||
1030 | { | ||
1031 | sa = sa->next; | ||
1032 | continue; | ||
1033 | } | ||
1034 | sn = sa->next; | ||
1035 | free_store_activity (sa); | ||
1036 | sa = sn; | ||
1037 | } | ||
1038 | } | ||
1039 | } | ||
1040 | for (struct ZoneMonitor *zm = monitor_head; NULL != zm; zm = zm->next) | ||
1041 | { | ||
1042 | if (nc != zm->nc) | ||
1043 | continue; | ||
1044 | GNUNET_CONTAINER_DLL_remove (monitor_head, monitor_tail, zm); | ||
1045 | if (NULL != zm->task) | ||
1046 | { | ||
1047 | GNUNET_SCHEDULER_cancel (zm->task); | ||
1048 | zm->task = NULL; | ||
1049 | } | ||
1050 | if (NULL != zm->sa_wait_warning) | ||
1051 | { | ||
1052 | GNUNET_SCHEDULER_cancel (zm->sa_wait_warning); | ||
1053 | zm->sa_wait_warning = NULL; | ||
1054 | } | ||
1055 | for (sa = sa_head; NULL != sa; sa = sn) | ||
1056 | { | ||
1057 | sn = sa->next; | ||
1058 | if (zm == sa->zm_pos) | ||
1059 | { | ||
1060 | sa->zm_pos = zm->next; | ||
1061 | /* this may free sa */ | ||
1062 | continue_store_activity (sa, GNUNET_YES); | ||
1063 | } | ||
1064 | } | ||
1065 | GNUNET_free (zm); | ||
1066 | break; | ||
1067 | } | ||
1068 | sa = sa_head; | ||
1069 | while (NULL != sa) | ||
1070 | { | ||
1071 | if (nc != sa->nc) | ||
1072 | { | ||
1073 | sa = sa->next; | ||
1074 | continue; | ||
1075 | } | ||
1076 | sn = sa->next; | ||
1077 | free_store_activity (sa); | ||
1078 | sa = sn; | ||
1079 | } | ||
1080 | while (NULL != (no = nc->op_head)) | ||
1081 | { | ||
1082 | GNUNET_CONTAINER_DLL_remove (nc->op_head, nc->op_tail, no); | ||
1083 | GNUNET_free (no); | ||
1084 | } | ||
1085 | GNUNET_break (NULL == GNUNET_PLUGIN_unload (nc->db_lib_name, | ||
1086 | nc->GSN_database)); | ||
1087 | GNUNET_free (nc->db_lib_name); | ||
1088 | GNUNET_free (nc); | ||
1089 | } | ||
1090 | |||
1091 | |||
1092 | /** | ||
1093 | * Add a client to our list of active clients. | ||
1094 | * | ||
1095 | * @param cls NULL | ||
1096 | * @param client client to add | ||
1097 | * @param mq message queue for @a client | ||
1098 | * @return internal namestore client structure for this client | ||
1099 | */ | ||
1100 | static void * | ||
1101 | client_connect_cb (void *cls, | ||
1102 | struct GNUNET_SERVICE_Client *client, | ||
1103 | struct GNUNET_MQ_Handle *mq) | ||
1104 | { | ||
1105 | struct NamestoreClient *nc; | ||
1106 | char *database; | ||
1107 | |||
1108 | (void) cls; | ||
1109 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Client %p connected\n", client); | ||
1110 | nc = GNUNET_new (struct NamestoreClient); | ||
1111 | nc->client = client; | ||
1112 | nc->mq = mq; | ||
1113 | /* Loading database plugin */ | ||
1114 | if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_string (GSN_cfg, | ||
1115 | "namestore", | ||
1116 | "database", | ||
1117 | &database)) | ||
1118 | { | ||
1119 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "No database backend configured\n"); | ||
1120 | GNUNET_free (nc); | ||
1121 | return NULL; | ||
1122 | } | ||
1123 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Loading %s\n", db_lib_name); | ||
1124 | nc->GSN_database = GNUNET_PLUGIN_load (db_lib_name, (void *) GSN_cfg); | ||
1125 | GNUNET_free (database); | ||
1126 | if (NULL == nc->GSN_database) | ||
1127 | { | ||
1128 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
1129 | "Could not load database backend `%s'\n", | ||
1130 | db_lib_name); | ||
1131 | GNUNET_free (nc); | ||
1132 | return NULL; | ||
1133 | } | ||
1134 | nc->db_lib_name = GNUNET_strdup (db_lib_name); | ||
1135 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Loaded %s\n", db_lib_name); | ||
1136 | return nc; | ||
1137 | } | ||
1138 | |||
1139 | |||
1140 | /** | ||
1141 | * Closure for #lookup_it(). | ||
1142 | */ | ||
1143 | struct RecordLookupContext | ||
1144 | { | ||
1145 | /** | ||
1146 | * The label to look up. | ||
1147 | */ | ||
1148 | const char *label; | ||
1149 | |||
1150 | /** | ||
1151 | * The record result. | ||
1152 | */ | ||
1153 | char *res_rd; | ||
1154 | |||
1155 | /** | ||
1156 | * The nick for the zone. | ||
1157 | */ | ||
1158 | struct GNUNET_GNSRECORD_Data *nick; | ||
1159 | |||
1160 | /** | ||
1161 | * If a record set was found or not. | ||
1162 | */ | ||
1163 | int found; | ||
1164 | |||
1165 | /** | ||
1166 | * The record filter | ||
1167 | */ | ||
1168 | enum GNUNET_GNSRECORD_Filter filter; | ||
1169 | |||
1170 | /** | ||
1171 | * The number of found records. | ||
1172 | */ | ||
1173 | unsigned int res_rd_count; | ||
1174 | |||
1175 | /** | ||
1176 | * The length of the serialized records. | ||
1177 | */ | ||
1178 | ssize_t rd_ser_len; | ||
1179 | }; | ||
1180 | |||
1181 | |||
1182 | /** | ||
1183 | * Function called by the namestore plugin when we are trying to lookup | ||
1184 | * a record as part of #handle_record_lookup(). Merges all results into | ||
1185 | * the context. | ||
1186 | * | ||
1187 | * @param cls closure with a `struct RecordLookupContext` | ||
1188 | * @param seq unique serial number of the record, MUST NOT BE ZERO | ||
1189 | * @param private_key private key of the zone | ||
1190 | * @param label name that is being mapped (at most 255 characters long) | ||
1191 | * @param rd_count number of entries in @a rd array | ||
1192 | * @param rd array of records with data to store | ||
1193 | */ | ||
1194 | static void | ||
1195 | lookup_it (void *cls, | ||
1196 | uint64_t seq, | ||
1197 | const struct GNUNET_CRYPTO_PrivateKey *private_key, | ||
1198 | const char *label, | ||
1199 | unsigned int rd_count_nf, | ||
1200 | const struct GNUNET_GNSRECORD_Data *rd_nf) | ||
1201 | { | ||
1202 | struct RecordLookupContext *rlc = cls; | ||
1203 | struct GNUNET_GNSRECORD_Data rd[rd_count_nf]; | ||
1204 | struct GNUNET_TIME_Absolute block_exp; | ||
1205 | unsigned int rd_count = 0; | ||
1206 | char *emsg; | ||
1207 | |||
1208 | (void) private_key; | ||
1209 | GNUNET_assert (0 != seq); | ||
1210 | if (0 != strcmp (label, rlc->label)) | ||
1211 | return; | ||
1212 | rlc->found = GNUNET_YES; | ||
1213 | |||
1214 | if (GNUNET_OK != GNUNET_GNSRECORD_normalize_record_set (rlc->label, | ||
1215 | rd_nf, | ||
1216 | rd_count_nf, | ||
1217 | rd, | ||
1218 | &rd_count, | ||
1219 | &block_exp, | ||
1220 | rlc->filter, | ||
1221 | &emsg)) | ||
1222 | { | ||
1223 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "%s\n", emsg); | ||
1224 | GNUNET_free (emsg); | ||
1225 | GNUNET_assert (0); | ||
1226 | } | ||
1227 | |||
1228 | if (0 == rd_count) | ||
1229 | { | ||
1230 | rlc->rd_ser_len = 0; | ||
1231 | rlc->res_rd_count = 0; | ||
1232 | rlc->res_rd = NULL; | ||
1233 | return; | ||
1234 | } | ||
1235 | if ((NULL != rlc->nick) && (0 != strcmp (label, GNUNET_GNS_EMPTY_LABEL_AT))) | ||
1236 | { | ||
1237 | /* Merge */ | ||
1238 | struct GNUNET_GNSRECORD_Data *rd_res; | ||
1239 | unsigned int rdc_res; | ||
1240 | |||
1241 | rd_res = NULL; | ||
1242 | rdc_res = 0; | ||
1243 | rlc->nick->flags = (rlc->nick->flags | GNUNET_GNSRECORD_RF_PRIVATE) | ||
1244 | ^ GNUNET_GNSRECORD_RF_PRIVATE; | ||
1245 | merge_with_nick_records (rlc->nick, rd_count, rd, &rdc_res, &rd_res); | ||
1246 | rlc->rd_ser_len = GNUNET_GNSRECORD_records_get_size (rdc_res, rd_res); | ||
1247 | if (rlc->rd_ser_len < 0) | ||
1248 | { | ||
1249 | GNUNET_break (0); | ||
1250 | GNUNET_free (rd_res); | ||
1251 | rlc->found = GNUNET_NO; | ||
1252 | rlc->rd_ser_len = 0; | ||
1253 | return; | ||
1254 | } | ||
1255 | rlc->res_rd_count = rdc_res; | ||
1256 | rlc->res_rd = GNUNET_malloc (rlc->rd_ser_len); | ||
1257 | if (rlc->rd_ser_len != GNUNET_GNSRECORD_records_serialize (rdc_res, | ||
1258 | rd_res, | ||
1259 | rlc->rd_ser_len, | ||
1260 | rlc->res_rd)) | ||
1261 | { | ||
1262 | GNUNET_break (0); | ||
1263 | GNUNET_free (rlc->res_rd); | ||
1264 | rlc->res_rd = NULL; | ||
1265 | rlc->res_rd_count = 0; | ||
1266 | rlc->rd_ser_len = 0; | ||
1267 | GNUNET_free (rd_res); | ||
1268 | rlc->found = GNUNET_NO; | ||
1269 | return; | ||
1270 | } | ||
1271 | GNUNET_free (rd_res); | ||
1272 | GNUNET_free (rlc->nick); | ||
1273 | rlc->nick = NULL; | ||
1274 | } | ||
1275 | else | ||
1276 | { | ||
1277 | rlc->rd_ser_len = GNUNET_GNSRECORD_records_get_size (rd_count, rd); | ||
1278 | if (rlc->rd_ser_len < 0) | ||
1279 | { | ||
1280 | GNUNET_break (0); | ||
1281 | rlc->found = GNUNET_NO; | ||
1282 | rlc->rd_ser_len = 0; | ||
1283 | return; | ||
1284 | } | ||
1285 | rlc->res_rd_count = rd_count; | ||
1286 | rlc->res_rd = GNUNET_malloc (rlc->rd_ser_len); | ||
1287 | if (rlc->rd_ser_len != GNUNET_GNSRECORD_records_serialize (rd_count, | ||
1288 | rd, | ||
1289 | rlc->rd_ser_len, | ||
1290 | rlc->res_rd)) | ||
1291 | { | ||
1292 | GNUNET_break (0); | ||
1293 | GNUNET_free (rlc->res_rd); | ||
1294 | rlc->res_rd = NULL; | ||
1295 | rlc->res_rd_count = 0; | ||
1296 | rlc->rd_ser_len = 0; | ||
1297 | rlc->found = GNUNET_NO; | ||
1298 | return; | ||
1299 | } | ||
1300 | } | ||
1301 | } | ||
1302 | |||
1303 | |||
1304 | /** | ||
1305 | * Handles a #GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_LOOKUP message | ||
1306 | * | ||
1307 | * @param cls client sending the message | ||
1308 | * @param ll_msg message of type `struct LabelLookupMessage` | ||
1309 | * @return #GNUNET_OK if @a ll_msg is well-formed | ||
1310 | */ | ||
1311 | static int | ||
1312 | check_record_lookup (void *cls, const struct LabelLookupMessage *ll_msg) | ||
1313 | { | ||
1314 | uint32_t name_len; | ||
1315 | size_t src_size; | ||
1316 | size_t key_len; | ||
1317 | |||
1318 | (void) cls; | ||
1319 | name_len = ntohs (ll_msg->label_len); | ||
1320 | key_len = ntohs (ll_msg->key_len); | ||
1321 | src_size = ntohs (ll_msg->gns_header.header.size); | ||
1322 | if (name_len + key_len != src_size - sizeof(struct LabelLookupMessage)) | ||
1323 | { | ||
1324 | GNUNET_break (0); | ||
1325 | return GNUNET_SYSERR; | ||
1326 | } | ||
1327 | return GNUNET_OK; | ||
1328 | } | ||
1329 | |||
1330 | |||
1331 | /** | ||
1332 | * Handles a #GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_LOOKUP message | ||
1333 | * | ||
1334 | * @param cls client sending the message | ||
1335 | * @param ll_msg message of type `struct LabelLookupMessage` | ||
1336 | */ | ||
1337 | static void | ||
1338 | handle_record_lookup (void *cls, const struct LabelLookupMessage *ll_msg) | ||
1339 | { | ||
1340 | struct GNUNET_CRYPTO_PrivateKey zone; | ||
1341 | struct NamestoreClient *nc = cls; | ||
1342 | struct GNUNET_MQ_Envelope *env; | ||
1343 | struct LabelLookupResponseMessage *llr_msg; | ||
1344 | struct RecordLookupContext rlc; | ||
1345 | const char *name_tmp; | ||
1346 | char *res_name; | ||
1347 | char *conv_name; | ||
1348 | uint32_t name_len; | ||
1349 | int res; | ||
1350 | size_t key_len; | ||
1351 | size_t kb_read; | ||
1352 | |||
1353 | key_len = ntohs (ll_msg->key_len); | ||
1354 | if ((GNUNET_SYSERR == | ||
1355 | GNUNET_CRYPTO_read_private_key_from_buffer (&ll_msg[1], | ||
1356 | key_len, | ||
1357 | &zone, | ||
1358 | &kb_read)) || | ||
1359 | (kb_read != key_len)) | ||
1360 | { | ||
1361 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
1362 | "Error reading private key\n"); | ||
1363 | GNUNET_SERVICE_client_drop (nc->client); | ||
1364 | return; | ||
1365 | } | ||
1366 | name_tmp = (const char *) &ll_msg[1] + key_len; | ||
1367 | GNUNET_SERVICE_client_continue (nc->client); | ||
1368 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
1369 | "Received NAMESTORE_RECORD_LOOKUP message for name `%s'\n", | ||
1370 | name_tmp); | ||
1371 | |||
1372 | conv_name = GNUNET_GNSRECORD_string_normalize (name_tmp); | ||
1373 | if (NULL == conv_name) | ||
1374 | { | ||
1375 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
1376 | "Error converting name `%s'\n", | ||
1377 | name_tmp); | ||
1378 | GNUNET_SERVICE_client_drop (nc->client); | ||
1379 | return; | ||
1380 | } | ||
1381 | name_len = strlen (conv_name) + 1; | ||
1382 | rlc.label = conv_name; | ||
1383 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
1384 | "Looking up with filter %u\n", ntohs (ll_msg->filter)); | ||
1385 | rlc.filter = ntohs (ll_msg->filter); | ||
1386 | rlc.found = GNUNET_NO; | ||
1387 | rlc.res_rd_count = 0; | ||
1388 | rlc.res_rd = NULL; | ||
1389 | rlc.rd_ser_len = 0; | ||
1390 | rlc.nick = get_nick_record (&zone); | ||
1391 | if (GNUNET_YES != ntohs (ll_msg->is_edit_request)) | ||
1392 | res = nc->GSN_database->lookup_records (nc->GSN_database->cls, | ||
1393 | &zone, | ||
1394 | conv_name, | ||
1395 | &lookup_it, | ||
1396 | &rlc); | ||
1397 | else | ||
1398 | res = nc->GSN_database->edit_records (nc->GSN_database->cls, | ||
1399 | &zone, | ||
1400 | conv_name, | ||
1401 | &lookup_it, | ||
1402 | &rlc); | ||
1403 | |||
1404 | env = | ||
1405 | GNUNET_MQ_msg_extra (llr_msg, | ||
1406 | key_len + name_len + rlc.rd_ser_len, | ||
1407 | GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_LOOKUP_RESPONSE); | ||
1408 | llr_msg->gns_header.r_id = ll_msg->gns_header.r_id; | ||
1409 | GNUNET_memcpy (&llr_msg[1], &ll_msg[1], key_len); | ||
1410 | llr_msg->key_len = ll_msg->key_len; | ||
1411 | llr_msg->name_len = htons (name_len); | ||
1412 | llr_msg->rd_count = htons (rlc.res_rd_count); | ||
1413 | llr_msg->rd_len = htons (rlc.rd_ser_len); | ||
1414 | llr_msg->reserved = htons (0); | ||
1415 | res_name = ((char *) &llr_msg[1]) + key_len; | ||
1416 | if (GNUNET_YES == rlc.found) | ||
1417 | llr_msg->found = htons (GNUNET_YES); | ||
1418 | else if (GNUNET_SYSERR == res) | ||
1419 | llr_msg->found = htons (GNUNET_SYSERR); | ||
1420 | else | ||
1421 | llr_msg->found = htons (GNUNET_NO); | ||
1422 | GNUNET_memcpy (res_name, conv_name, name_len); | ||
1423 | GNUNET_memcpy (&res_name[name_len], rlc.res_rd, rlc.rd_ser_len); | ||
1424 | GNUNET_MQ_send (nc->mq, env); | ||
1425 | GNUNET_free (rlc.res_rd); | ||
1426 | GNUNET_free (conv_name); | ||
1427 | } | ||
1428 | |||
1429 | |||
1430 | |||
1431 | /** | ||
1432 | * Checks a #GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_STORE message | ||
1433 | * | ||
1434 | * @param cls client sending the message | ||
1435 | * @param rp_msg message of type `struct RecordStoreMessage` | ||
1436 | * @return #GNUNET_OK if @a rp_msg is well-formed | ||
1437 | */ | ||
1438 | static int | ||
1439 | check_record_store (void *cls, const struct RecordStoreMessage *rp_msg) | ||
1440 | { | ||
1441 | size_t msg_size; | ||
1442 | size_t min_size_exp; | ||
1443 | size_t rd_set_count; | ||
1444 | size_t key_len; | ||
1445 | |||
1446 | (void) cls; | ||
1447 | msg_size = ntohs (rp_msg->gns_header.header.size); | ||
1448 | rd_set_count = ntohs (rp_msg->rd_set_count); | ||
1449 | key_len = ntohs (rp_msg->key_len); | ||
1450 | |||
1451 | min_size_exp = sizeof(*rp_msg) + key_len + sizeof (struct RecordSet) | ||
1452 | * rd_set_count; | ||
1453 | if (msg_size < min_size_exp) | ||
1454 | { | ||
1455 | GNUNET_break (0); | ||
1456 | return GNUNET_SYSERR; | ||
1457 | } | ||
1458 | return GNUNET_OK; | ||
1459 | } | ||
1460 | |||
1461 | struct LookupExistingRecordsContext | ||
1462 | { | ||
1463 | |||
1464 | /** | ||
1465 | * The expiration of the existing records or tombstone | ||
1466 | */ | ||
1467 | struct GNUNET_TIME_Absolute exp; | ||
1468 | |||
1469 | /** | ||
1470 | * Whether the existing record set consists only of a tombstone | ||
1471 | * (e.g. is "empty") | ||
1472 | */ | ||
1473 | int only_tombstone; | ||
1474 | |||
1475 | }; | ||
1476 | |||
1477 | |||
1478 | /** | ||
1479 | * Check if set contains a tombstone, store if necessary | ||
1480 | * | ||
1481 | * @param cls a `struct GNUNET_GNSRECORD_Data **` for storing the nick (if found) | ||
1482 | * @param seq sequence number of the record, MUST NOT BE ZERO | ||
1483 | * @param private_key the private key of the zone (unused) | ||
1484 | * @param label should be #GNUNET_GNS_EMPTY_LABEL_AT | ||
1485 | * @param rd_count number of records in @a rd | ||
1486 | * @param rd records stored under @a label in the zone | ||
1487 | */ | ||
1488 | static void | ||
1489 | get_existing_rd_exp (void *cls, | ||
1490 | uint64_t seq, | ||
1491 | const struct | ||
1492 | GNUNET_CRYPTO_PrivateKey *private_key, | ||
1493 | const char *label, | ||
1494 | unsigned int rd_count, | ||
1495 | const struct GNUNET_GNSRECORD_Data *rd) | ||
1496 | { | ||
1497 | struct LookupExistingRecordsContext *lctx = cls; | ||
1498 | struct GNUNET_GNSRECORD_Data rd_pub[rd_count]; | ||
1499 | unsigned int rd_pub_count; | ||
1500 | char *emsg; | ||
1501 | |||
1502 | if ((1 == rd_count) && | ||
1503 | (GNUNET_GNSRECORD_TYPE_TOMBSTONE == rd[0].record_type)) | ||
1504 | { | ||
1505 | /* This record set contains only a tombstone! */ | ||
1506 | lctx->only_tombstone = GNUNET_YES; | ||
1507 | } | ||
1508 | if (GNUNET_OK != | ||
1509 | GNUNET_GNSRECORD_normalize_record_set (label, | ||
1510 | rd, | ||
1511 | rd_count, | ||
1512 | rd_pub, | ||
1513 | &rd_pub_count, | ||
1514 | &lctx->exp, | ||
1515 | GNUNET_GNSRECORD_FILTER_OMIT_PRIVATE, | ||
1516 | &emsg)) | ||
1517 | { | ||
1518 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
1519 | "%s\n", emsg); | ||
1520 | GNUNET_free (emsg); | ||
1521 | } | ||
1522 | } | ||
1523 | |||
1524 | static enum GNUNET_ErrorCode | ||
1525 | store_record_set (struct NamestoreClient *nc, | ||
1526 | const struct GNUNET_CRYPTO_PrivateKey *private_key, | ||
1527 | const struct RecordSet *rd_set, | ||
1528 | ssize_t *len) | ||
1529 | { | ||
1530 | size_t name_len; | ||
1531 | size_t rd_ser_len; | ||
1532 | const char *name_tmp; | ||
1533 | const char *rd_ser; | ||
1534 | char *conv_name; | ||
1535 | char *emsg; | ||
1536 | unsigned int rd_count; | ||
1537 | int res; | ||
1538 | enum GNUNET_ErrorCode ec; | ||
1539 | struct GNUNET_TIME_Absolute new_block_exp; | ||
1540 | struct LookupExistingRecordsContext lctx; | ||
1541 | *len = sizeof (struct RecordSet); | ||
1542 | |||
1543 | ec = GNUNET_EC_NONE; | ||
1544 | lctx.only_tombstone = GNUNET_NO; | ||
1545 | lctx.exp = GNUNET_TIME_UNIT_ZERO_ABS; | ||
1546 | new_block_exp = GNUNET_TIME_UNIT_ZERO_ABS; | ||
1547 | name_len = ntohs (rd_set->name_len); | ||
1548 | *len += name_len; | ||
1549 | rd_count = ntohs (rd_set->rd_count); | ||
1550 | rd_ser_len = ntohs (rd_set->rd_len); | ||
1551 | *len += rd_ser_len; | ||
1552 | name_tmp = (const char *) &rd_set[1]; | ||
1553 | rd_ser = &name_tmp[name_len]; | ||
1554 | { | ||
1555 | struct GNUNET_GNSRECORD_Data rd[GNUNET_NZL (rd_count)]; | ||
1556 | |||
1557 | /* Extracting and converting private key */ | ||
1558 | conv_name = GNUNET_GNSRECORD_string_normalize (name_tmp); | ||
1559 | if (NULL == conv_name) | ||
1560 | { | ||
1561 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
1562 | "Error normalizing name `%s'\n", | ||
1563 | name_tmp); | ||
1564 | return GNUNET_EC_NAMESTORE_LABEL_INVALID; | ||
1565 | } | ||
1566 | |||
1567 | /* Check name for validity */ | ||
1568 | if (GNUNET_OK != GNUNET_GNSRECORD_label_check (conv_name, &emsg)) | ||
1569 | { | ||
1570 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
1571 | "Label invalid: `%s'\n", | ||
1572 | emsg); | ||
1573 | GNUNET_free (emsg); | ||
1574 | GNUNET_free (conv_name); | ||
1575 | return GNUNET_EC_NAMESTORE_LABEL_INVALID; | ||
1576 | } | ||
1577 | |||
1578 | if (GNUNET_OK != | ||
1579 | GNUNET_GNSRECORD_records_deserialize (rd_ser_len, rd_ser, rd_count, | ||
1580 | rd)) | ||
1581 | { | ||
1582 | GNUNET_free (conv_name); | ||
1583 | return GNUNET_EC_NAMESTORE_RECORD_DATA_INVALID; | ||
1584 | } | ||
1585 | |||
1586 | GNUNET_STATISTICS_update (statistics, | ||
1587 | "Well-formed store requests received", | ||
1588 | 1, | ||
1589 | GNUNET_NO); | ||
1590 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
1591 | "Creating %u records for name `%s'\n", | ||
1592 | (unsigned int) rd_count, | ||
1593 | conv_name); | ||
1594 | if ((GNUNET_NO == nc->GSN_database->lookup_records (nc->GSN_database->cls, | ||
1595 | private_key, | ||
1596 | conv_name, | ||
1597 | &get_existing_rd_exp, | ||
1598 | &lctx)) | ||
1599 | && | ||
1600 | (rd_count == 0)) | ||
1601 | { | ||
1602 | /* This name does not exist, so cannot be removed */ | ||
1603 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
1604 | "Name `%s' does not exist, no deletion required\n", | ||
1605 | conv_name); | ||
1606 | res = GNUNET_NO; | ||
1607 | ec = GNUNET_EC_NAMESTORE_RECORD_NOT_FOUND; | ||
1608 | } | ||
1609 | else | ||
1610 | { | ||
1611 | /* remove "NICK" records, unless this is for the | ||
1612 | #GNUNET_GNS_EMPTY_LABEL_AT label | ||
1613 | We may need one additional record later for tombstone. | ||
1614 | FIXME: Since we must normalize the record set (check for | ||
1615 | consistency etc) we have to iterate the set twice. | ||
1616 | May be inefficient. | ||
1617 | We cannot really move the nick caching into GNSRECORD. | ||
1618 | */ | ||
1619 | struct GNUNET_GNSRECORD_Data rd_clean[GNUNET_NZL (rd_count)]; | ||
1620 | struct GNUNET_GNSRECORD_Data rd_nf[GNUNET_NZL (rd_count) + 1]; | ||
1621 | unsigned int rd_clean_off; | ||
1622 | unsigned int rd_nf_count; | ||
1623 | int have_nick; | ||
1624 | |||
1625 | rd_clean_off = 0; | ||
1626 | have_nick = GNUNET_NO; | ||
1627 | for (unsigned int i = 0; i < rd_count; i++) | ||
1628 | { | ||
1629 | rd_clean[rd_clean_off] = rd[i]; | ||
1630 | |||
1631 | if ((0 == strcmp (GNUNET_GNS_EMPTY_LABEL_AT, conv_name)) || | ||
1632 | (GNUNET_GNSRECORD_TYPE_NICK != rd[i].record_type)) | ||
1633 | rd_clean_off++; | ||
1634 | |||
1635 | if ((0 == strcmp (GNUNET_GNS_EMPTY_LABEL_AT, conv_name)) && | ||
1636 | (GNUNET_GNSRECORD_TYPE_NICK == rd[i].record_type)) | ||
1637 | { | ||
1638 | // FIXME: In case this is an uncommited transaction, | ||
1639 | // we should not do this here. Can we do this in the store activity? | ||
1640 | cache_nick (private_key, &rd[i]); | ||
1641 | have_nick = GNUNET_YES; | ||
1642 | } | ||
1643 | } | ||
1644 | if (GNUNET_OK != | ||
1645 | GNUNET_GNSRECORD_normalize_record_set (conv_name, | ||
1646 | rd_clean, | ||
1647 | rd_clean_off, | ||
1648 | rd_nf, | ||
1649 | &rd_nf_count, | ||
1650 | &new_block_exp, | ||
1651 | GNUNET_GNSRECORD_FILTER_NONE, | ||
1652 | &emsg)) | ||
1653 | { | ||
1654 | GNUNET_free (conv_name); | ||
1655 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
1656 | "Error normalizing record set: `%s'\n", | ||
1657 | emsg); | ||
1658 | GNUNET_free (emsg); | ||
1659 | return GNUNET_EC_NAMESTORE_RECORD_DATA_INVALID; | ||
1660 | } | ||
1661 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
1662 | "%u/%u records before tombstone\n", rd_nf_count, | ||
1663 | rd_clean_off); | ||
1664 | /* | ||
1665 | * If existing_block_exp is 0, then there was no record set | ||
1666 | * and no tombstone. | ||
1667 | * Otherwise, if the existing block expiration is after the | ||
1668 | * new block expiration would be, we need to add a tombstone | ||
1669 | * or update it. | ||
1670 | */ | ||
1671 | if (GNUNET_TIME_absolute_cmp (new_block_exp, <=, lctx.exp)) | ||
1672 | { | ||
1673 | rd_nf[rd_nf_count].record_type = GNUNET_GNSRECORD_TYPE_TOMBSTONE; | ||
1674 | rd_nf[rd_nf_count].expiration_time = | ||
1675 | lctx.exp.abs_value_us; | ||
1676 | rd_nf[rd_nf_count].data = NULL; | ||
1677 | rd_nf[rd_nf_count].data_size = 0; | ||
1678 | rd_nf[rd_nf_count].flags = GNUNET_GNSRECORD_RF_PRIVATE; | ||
1679 | rd_nf_count++; | ||
1680 | } | ||
1681 | if ((0 == strcmp (GNUNET_GNS_EMPTY_LABEL_AT, conv_name)) && | ||
1682 | (GNUNET_NO == have_nick)) | ||
1683 | { | ||
1684 | /* remove nick record from cache, in case we have one there */ | ||
1685 | // FIXME: In case this is an uncommited transaction, | ||
1686 | // we should not do this here. Can we do this in the store activity? | ||
1687 | cache_nick (private_key, NULL); | ||
1688 | } | ||
1689 | res = nc->GSN_database->store_records (nc->GSN_database->cls, | ||
1690 | private_key, | ||
1691 | conv_name, | ||
1692 | rd_nf_count, | ||
1693 | rd_nf); | ||
1694 | /* If after a store there is only a TOMBSTONE left, and | ||
1695 | * there was >1 record under this label found (the tombstone; indicated | ||
1696 | * through res != GNUNET_NO) then we should return "NOT FOUND" == GNUNET_NO | ||
1697 | */ | ||
1698 | if ((GNUNET_SYSERR != res) && | ||
1699 | (0 == rd_count) && | ||
1700 | (1 == rd_nf_count) && | ||
1701 | (GNUNET_GNSRECORD_TYPE_TOMBSTONE == rd_nf[0].record_type) && | ||
1702 | (GNUNET_YES == lctx.only_tombstone)) | ||
1703 | { | ||
1704 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
1705 | "Client tried to remove non-existant record\n"); | ||
1706 | ec = GNUNET_EC_NAMESTORE_RECORD_NOT_FOUND; | ||
1707 | } | ||
1708 | } | ||
1709 | |||
1710 | if (GNUNET_SYSERR == res) | ||
1711 | { | ||
1712 | /* store not successful, no need to tell monitors */ | ||
1713 | GNUNET_free (conv_name); | ||
1714 | return GNUNET_EC_NAMESTORE_STORE_FAILED; | ||
1715 | } | ||
1716 | } | ||
1717 | GNUNET_free (conv_name); | ||
1718 | return ec; | ||
1719 | } | ||
1720 | |||
1721 | /** | ||
1722 | * Handles a #GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_STORE message | ||
1723 | * | ||
1724 | * @param cls client sending the message | ||
1725 | * @param rp_msg message of type `struct RecordStoreMessage` | ||
1726 | */ | ||
1727 | static void | ||
1728 | handle_record_store (void *cls, const struct RecordStoreMessage *rp_msg) | ||
1729 | { | ||
1730 | struct GNUNET_CRYPTO_PrivateKey zone; | ||
1731 | struct NamestoreClient *nc = cls; | ||
1732 | uint32_t rid; | ||
1733 | uint16_t rd_set_count; | ||
1734 | const char *buf; | ||
1735 | ssize_t read; | ||
1736 | size_t key_len; | ||
1737 | size_t kb_read; | ||
1738 | size_t rp_msg_len; | ||
1739 | size_t rs_len; | ||
1740 | size_t rs_off; | ||
1741 | struct StoreActivity *sa; | ||
1742 | struct RecordSet *rs; | ||
1743 | enum GNUNET_ErrorCode res; | ||
1744 | |||
1745 | key_len = ntohs (rp_msg->key_len); | ||
1746 | rp_msg_len = ntohs (rp_msg->gns_header.header.size); | ||
1747 | rs_off = sizeof (*rp_msg) + key_len; | ||
1748 | rs_len = rp_msg_len - rs_off; | ||
1749 | if ((GNUNET_SYSERR == | ||
1750 | GNUNET_CRYPTO_read_private_key_from_buffer (&rp_msg[1], | ||
1751 | key_len, | ||
1752 | &zone, | ||
1753 | &kb_read)) || | ||
1754 | (kb_read != key_len)) | ||
1755 | { | ||
1756 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
1757 | "Error reading private key\n"); | ||
1758 | GNUNET_SERVICE_client_drop (nc->client); | ||
1759 | return; | ||
1760 | } | ||
1761 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
1762 | "Received NAMESTORE_RECORD_STORE message\n"); | ||
1763 | rid = ntohl (rp_msg->gns_header.r_id); | ||
1764 | rd_set_count = ntohs (rp_msg->rd_set_count); | ||
1765 | buf = (const char *) rp_msg + rs_off; | ||
1766 | for (int i = 0; i < rd_set_count; i++) | ||
1767 | { | ||
1768 | rs = (struct RecordSet *) buf; | ||
1769 | res = store_record_set (nc, &zone, | ||
1770 | rs, &read); | ||
1771 | if (GNUNET_EC_NONE != res) | ||
1772 | { | ||
1773 | send_store_response (nc, res, rid); | ||
1774 | GNUNET_SERVICE_client_continue (nc->client); | ||
1775 | return; | ||
1776 | } | ||
1777 | buf += read; | ||
1778 | } | ||
1779 | sa = GNUNET_malloc (sizeof(struct StoreActivity) + rs_len); | ||
1780 | GNUNET_CONTAINER_DLL_insert (sa_head, sa_tail, sa); | ||
1781 | sa->nc = nc; | ||
1782 | sa->rs = (struct RecordSet *) &sa[1]; | ||
1783 | sa->rd_set_count = rd_set_count; | ||
1784 | GNUNET_memcpy (&sa[1], (char *) rp_msg + rs_off, rs_len); | ||
1785 | sa->rid = rid; | ||
1786 | sa->rd_set_pos = 0; | ||
1787 | sa->private_key = zone; | ||
1788 | sa->zm_pos = monitor_head; | ||
1789 | sa->uncommited = nc->in_transaction; | ||
1790 | continue_store_activity (sa, GNUNET_YES); | ||
1791 | } | ||
1792 | |||
1793 | static void | ||
1794 | send_tx_response (int rid, enum GNUNET_ErrorCode ec, struct NamestoreClient *nc) | ||
1795 | { | ||
1796 | struct TxControlResultMessage *txr_msg; | ||
1797 | struct GNUNET_MQ_Envelope *env; | ||
1798 | |||
1799 | env = | ||
1800 | GNUNET_MQ_msg (txr_msg, GNUNET_MESSAGE_TYPE_NAMESTORE_TX_CONTROL_RESULT); | ||
1801 | txr_msg->gns_header.r_id = rid; | ||
1802 | txr_msg->ec = htonl (ec); | ||
1803 | GNUNET_MQ_send (nc->mq, env); | ||
1804 | } | ||
1805 | |||
1806 | /** | ||
1807 | * Handles a #GNUNET_MESSAGE_TYPE_NAMESTORE_TX_CONTROL message | ||
1808 | * | ||
1809 | * @param cls client sending the message | ||
1810 | * @param tx_msg message of type `struct TxControlMessage` | ||
1811 | */ | ||
1812 | static void | ||
1813 | handle_tx_control (void *cls, const struct TxControlMessage *tx_msg) | ||
1814 | { | ||
1815 | struct NamestoreClient *nc = cls; | ||
1816 | struct StoreActivity *sa = sa_head; | ||
1817 | struct StoreActivity *sn; | ||
1818 | enum GNUNET_GenericReturnValue ret; | ||
1819 | char *emsg = NULL; | ||
1820 | int blocked = GNUNET_NO; | ||
1821 | |||
1822 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received TX_CONTROL message\n"); | ||
1823 | |||
1824 | switch (ntohs (tx_msg->control)) | ||
1825 | { | ||
1826 | case GNUNET_NAMESTORE_TX_BEGIN: | ||
1827 | ret = nc->GSN_database->transaction_begin (nc->GSN_database->cls, | ||
1828 | &emsg); | ||
1829 | send_tx_response (tx_msg->gns_header.r_id, | ||
1830 | (GNUNET_SYSERR == ret) ? | ||
1831 | GNUNET_EC_NAMESTORE_BACKEND_FAILED : GNUNET_EC_NONE, nc); | ||
1832 | if (GNUNET_SYSERR == ret) | ||
1833 | { | ||
1834 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
1835 | "Databse backend error: `%s'", emsg); | ||
1836 | GNUNET_free (emsg); | ||
1837 | } | ||
1838 | GNUNET_SERVICE_client_continue (nc->client); | ||
1839 | nc->in_transaction = GNUNET_YES; | ||
1840 | break; | ||
1841 | case GNUNET_NAMESTORE_TX_COMMIT: | ||
1842 | ret = nc->GSN_database->transaction_commit (nc->GSN_database->cls, | ||
1843 | &emsg); | ||
1844 | send_tx_response (tx_msg->gns_header.r_id, | ||
1845 | (GNUNET_SYSERR == ret) ? | ||
1846 | GNUNET_EC_NAMESTORE_BACKEND_FAILED : GNUNET_EC_NONE, | ||
1847 | nc); | ||
1848 | if (GNUNET_SYSERR == ret) | ||
1849 | { | ||
1850 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
1851 | "Databse backend error: `%s'", emsg); | ||
1852 | GNUNET_free (emsg); | ||
1853 | } | ||
1854 | if (GNUNET_SYSERR != ret) | ||
1855 | { | ||
1856 | nc->in_transaction = GNUNET_NO; | ||
1857 | while (NULL != sa) | ||
1858 | { | ||
1859 | if ((nc != sa->nc) || | ||
1860 | (GNUNET_NO == sa->uncommited)) | ||
1861 | { | ||
1862 | sa = sa->next; | ||
1863 | continue; | ||
1864 | } | ||
1865 | sa->uncommited = GNUNET_NO; | ||
1866 | sn = sa->next; | ||
1867 | if (GNUNET_OK != continue_store_activity (sa, GNUNET_NO)) | ||
1868 | blocked = GNUNET_YES; | ||
1869 | sa = sn; | ||
1870 | } | ||
1871 | if (GNUNET_YES != blocked) | ||
1872 | GNUNET_SERVICE_client_continue (nc->client); | ||
1873 | } | ||
1874 | break; | ||
1875 | case GNUNET_NAMESTORE_TX_ROLLBACK: | ||
1876 | ret = nc->GSN_database->transaction_rollback (nc->GSN_database->cls, | ||
1877 | &emsg); | ||
1878 | send_tx_response (tx_msg->gns_header.r_id, | ||
1879 | (GNUNET_SYSERR == ret) ? | ||
1880 | GNUNET_EC_NAMESTORE_BACKEND_FAILED : GNUNET_EC_NONE, nc); | ||
1881 | GNUNET_SERVICE_client_continue (nc->client); | ||
1882 | if (GNUNET_SYSERR == ret) | ||
1883 | { | ||
1884 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
1885 | "Databse backend error: `%s'", emsg); | ||
1886 | GNUNET_free (emsg); | ||
1887 | } | ||
1888 | if (GNUNET_SYSERR != ret) | ||
1889 | { | ||
1890 | nc->in_transaction = GNUNET_NO; | ||
1891 | while (NULL != sa) | ||
1892 | { | ||
1893 | if ((nc != sa->nc) || | ||
1894 | (GNUNET_NO == sa->uncommited)) | ||
1895 | { | ||
1896 | sa = sa->next; | ||
1897 | continue; | ||
1898 | } | ||
1899 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
1900 | "Discarding uncommited StoreActivity\n"); | ||
1901 | sn = sa->next; | ||
1902 | free_store_activity (sa); | ||
1903 | sa = sn; | ||
1904 | } | ||
1905 | } | ||
1906 | break; | ||
1907 | default: | ||
1908 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, | ||
1909 | "Unknown control type %u\n", ntohs (tx_msg->control)); | ||
1910 | GNUNET_break (0); | ||
1911 | } | ||
1912 | } | ||
1913 | |||
1914 | /** | ||
1915 | * Context for record remove operations passed from #handle_zone_to_name to | ||
1916 | * #handle_zone_to_name_it as closure | ||
1917 | */ | ||
1918 | struct ZoneToNameCtx | ||
1919 | { | ||
1920 | /** | ||
1921 | * Namestore client | ||
1922 | */ | ||
1923 | struct NamestoreClient *nc; | ||
1924 | |||
1925 | /** | ||
1926 | * Request id (to be used in the response to the client). | ||
1927 | */ | ||
1928 | uint32_t rid; | ||
1929 | |||
1930 | /** | ||
1931 | * Set to #GNUNET_OK on success, #GNUNET_SYSERR on error. Note that | ||
1932 | * not finding a name for the zone still counts as a 'success' here, | ||
1933 | * as this field is about the success of executing the IPC protocol. | ||
1934 | */ | ||
1935 | enum GNUNET_ErrorCode ec; | ||
1936 | }; | ||
1937 | |||
1938 | |||
1939 | /** | ||
1940 | * Zone to name iterator | ||
1941 | * | ||
1942 | * @param cls struct ZoneToNameCtx * | ||
1943 | * @param seq sequence number of the record, MUST NOT BE ZERO | ||
1944 | * @param zone_key the zone key | ||
1945 | * @param name name | ||
1946 | * @param rd_count number of records in @a rd | ||
1947 | * @param rd record data | ||
1948 | */ | ||
1949 | static void | ||
1950 | handle_zone_to_name_it (void *cls, | ||
1951 | uint64_t seq, | ||
1952 | const struct GNUNET_CRYPTO_PrivateKey *zone_key, | ||
1953 | const char *name, | ||
1954 | unsigned int rd_count, | ||
1955 | const struct GNUNET_GNSRECORD_Data *rd) | ||
1956 | { | ||
1957 | struct ZoneToNameCtx *ztn_ctx = cls; | ||
1958 | struct GNUNET_MQ_Envelope *env; | ||
1959 | struct ZoneToNameResponseMessage *ztnr_msg; | ||
1960 | size_t name_len; | ||
1961 | size_t key_len; | ||
1962 | ssize_t rd_ser_len; | ||
1963 | size_t msg_size; | ||
1964 | char *name_tmp; | ||
1965 | char *rd_tmp; | ||
1966 | |||
1967 | GNUNET_assert (0 != seq); | ||
1968 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
1969 | "Found result for zone-to-name lookup: `%s'\n", | ||
1970 | name); | ||
1971 | ztn_ctx->ec = GNUNET_EC_NONE; | ||
1972 | name_len = (NULL == name) ? 0 : strlen (name) + 1; | ||
1973 | rd_ser_len = GNUNET_GNSRECORD_records_get_size (rd_count, rd); | ||
1974 | if (rd_ser_len < 0) | ||
1975 | { | ||
1976 | GNUNET_break (0); | ||
1977 | ztn_ctx->ec = htonl (GNUNET_EC_NAMESTORE_UNKNOWN); | ||
1978 | return; | ||
1979 | } | ||
1980 | key_len = GNUNET_CRYPTO_private_key_get_length (zone_key); | ||
1981 | msg_size = sizeof(struct ZoneToNameResponseMessage) | ||
1982 | + name_len + rd_ser_len + key_len; | ||
1983 | if (msg_size >= GNUNET_MAX_MESSAGE_SIZE) | ||
1984 | { | ||
1985 | GNUNET_break (0); | ||
1986 | ztn_ctx->ec = GNUNET_EC_NAMESTORE_RECORD_TOO_BIG; | ||
1987 | return; | ||
1988 | } | ||
1989 | env = | ||
1990 | GNUNET_MQ_msg_extra (ztnr_msg, | ||
1991 | key_len + name_len + rd_ser_len, | ||
1992 | GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_TO_NAME_RESPONSE); | ||
1993 | ztnr_msg->gns_header.header.size = htons (msg_size); | ||
1994 | ztnr_msg->gns_header.r_id = htonl (ztn_ctx->rid); | ||
1995 | ztnr_msg->ec = htonl (ztn_ctx->ec); | ||
1996 | ztnr_msg->rd_len = htons (rd_ser_len); | ||
1997 | ztnr_msg->rd_count = htons (rd_count); | ||
1998 | ztnr_msg->name_len = htons (name_len); | ||
1999 | ztnr_msg->key_len = htons (key_len); | ||
2000 | GNUNET_CRYPTO_write_private_key_to_buffer (zone_key, | ||
2001 | &ztnr_msg[1], | ||
2002 | key_len); | ||
2003 | name_tmp = (char *) &ztnr_msg[1] + key_len; | ||
2004 | GNUNET_memcpy (name_tmp, name, name_len); | ||
2005 | rd_tmp = &name_tmp[name_len]; | ||
2006 | GNUNET_assert ( | ||
2007 | rd_ser_len == | ||
2008 | GNUNET_GNSRECORD_records_serialize (rd_count, rd, rd_ser_len, rd_tmp)); | ||
2009 | ztn_ctx->ec = GNUNET_EC_NONE; | ||
2010 | GNUNET_MQ_send (ztn_ctx->nc->mq, env); | ||
2011 | } | ||
2012 | |||
2013 | static enum GNUNET_GenericReturnValue | ||
2014 | check_zone_to_name (void *cls, | ||
2015 | const struct ZoneToNameMessage *zis_msg) | ||
2016 | { | ||
2017 | return GNUNET_OK; | ||
2018 | } | ||
2019 | |||
2020 | |||
2021 | /** | ||
2022 | * Handles a #GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_TO_NAME message | ||
2023 | * | ||
2024 | * @param cls client client sending the message | ||
2025 | * @param ztn_msg message of type 'struct ZoneToNameMessage' | ||
2026 | */ | ||
2027 | static void | ||
2028 | handle_zone_to_name (void *cls, const struct ZoneToNameMessage *ztn_msg) | ||
2029 | { | ||
2030 | struct GNUNET_CRYPTO_PrivateKey zone; | ||
2031 | struct GNUNET_CRYPTO_PublicKey value_zone; | ||
2032 | struct NamestoreClient *nc = cls; | ||
2033 | struct ZoneToNameCtx ztn_ctx; | ||
2034 | struct GNUNET_MQ_Envelope *env; | ||
2035 | struct ZoneToNameResponseMessage *ztnr_msg; | ||
2036 | size_t key_len; | ||
2037 | size_t pkey_len; | ||
2038 | size_t kb_read; | ||
2039 | |||
2040 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received ZONE_TO_NAME message\n"); | ||
2041 | ztn_ctx.rid = ntohl (ztn_msg->gns_header.r_id); | ||
2042 | ztn_ctx.nc = nc; | ||
2043 | ztn_ctx.ec = GNUNET_EC_NAMESTORE_ZONE_NOT_FOUND; | ||
2044 | key_len = ntohs (ztn_msg->key_len); | ||
2045 | if ((GNUNET_SYSERR == | ||
2046 | GNUNET_CRYPTO_read_private_key_from_buffer (&ztn_msg[1], | ||
2047 | key_len, | ||
2048 | &zone, | ||
2049 | &kb_read)) || | ||
2050 | (kb_read != key_len)) | ||
2051 | { | ||
2052 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
2053 | "Error parsing private key.\n"); | ||
2054 | GNUNET_SERVICE_client_drop (nc->client); | ||
2055 | GNUNET_break (0); | ||
2056 | return; | ||
2057 | } | ||
2058 | pkey_len = ntohs (ztn_msg->pkey_len); | ||
2059 | if ((GNUNET_SYSERR == | ||
2060 | GNUNET_CRYPTO_read_public_key_from_buffer ((char*) &ztn_msg[1] | ||
2061 | + key_len, | ||
2062 | pkey_len, | ||
2063 | &value_zone, | ||
2064 | &kb_read)) || | ||
2065 | (kb_read != pkey_len)) | ||
2066 | { | ||
2067 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
2068 | "Error parsing public key.\n"); | ||
2069 | GNUNET_SERVICE_client_drop (nc->client); | ||
2070 | GNUNET_break (0); | ||
2071 | return; | ||
2072 | } | ||
2073 | if (GNUNET_SYSERR == nc->GSN_database->zone_to_name (nc->GSN_database->cls, | ||
2074 | &zone, | ||
2075 | &value_zone, | ||
2076 | &handle_zone_to_name_it, | ||
2077 | &ztn_ctx)) | ||
2078 | { | ||
2079 | /* internal error, hang up instead of signalling something | ||
2080 | that might be wrong */ | ||
2081 | GNUNET_break (0); | ||
2082 | GNUNET_SERVICE_client_drop (nc->client); | ||
2083 | return; | ||
2084 | } | ||
2085 | if (GNUNET_EC_NAMESTORE_ZONE_NOT_FOUND == ztn_ctx.ec) | ||
2086 | { | ||
2087 | /* no result found, send empty response */ | ||
2088 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
2089 | "Found no result for zone-to-name lookup.\n"); | ||
2090 | env = GNUNET_MQ_msg (ztnr_msg, | ||
2091 | GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_TO_NAME_RESPONSE); | ||
2092 | ztnr_msg->gns_header.r_id = ztn_msg->gns_header.r_id; | ||
2093 | ztnr_msg->ec = htonl (GNUNET_EC_NAMESTORE_ZONE_NOT_FOUND); | ||
2094 | GNUNET_MQ_send (nc->mq, env); | ||
2095 | } | ||
2096 | GNUNET_SERVICE_client_continue (nc->client); | ||
2097 | } | ||
2098 | |||
2099 | |||
2100 | /** | ||
2101 | * Context for record remove operations passed from | ||
2102 | * #run_zone_iteration_round to #zone_iterate_proc as closure | ||
2103 | */ | ||
2104 | struct ZoneIterationProcResult | ||
2105 | { | ||
2106 | /** | ||
2107 | * The zone iteration handle | ||
2108 | */ | ||
2109 | struct ZoneIteration *zi; | ||
2110 | |||
2111 | /** | ||
2112 | * Number of results left to be returned in this iteration. | ||
2113 | */ | ||
2114 | uint64_t limit; | ||
2115 | |||
2116 | /** | ||
2117 | * Skip a result and run again unless GNUNET_NO | ||
2118 | */ | ||
2119 | int run_again; | ||
2120 | }; | ||
2121 | |||
2122 | |||
2123 | /** | ||
2124 | * Process results for zone iteration from database | ||
2125 | * | ||
2126 | * @param cls struct ZoneIterationProcResult | ||
2127 | * @param seq sequence number of the record, MUST NOT BE ZERO | ||
2128 | * @param zone_key the zone key | ||
2129 | * @param name name | ||
2130 | * @param rd_count number of records for this name | ||
2131 | * @param rd record data | ||
2132 | */ | ||
2133 | static void | ||
2134 | zone_iterate_proc (void *cls, | ||
2135 | uint64_t seq, | ||
2136 | const struct GNUNET_CRYPTO_PrivateKey *zone_key, | ||
2137 | const char *name, | ||
2138 | unsigned int rd_count, | ||
2139 | const struct GNUNET_GNSRECORD_Data *rd) | ||
2140 | { | ||
2141 | struct ZoneIterationProcResult *proc = cls; | ||
2142 | |||
2143 | GNUNET_assert (0 != seq); | ||
2144 | if ((NULL == zone_key) && (NULL == name)) | ||
2145 | { | ||
2146 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Iteration done\n"); | ||
2147 | return; | ||
2148 | } | ||
2149 | if ((NULL == zone_key) || (NULL == name)) | ||
2150 | { | ||
2151 | /* what is this!? should never happen */ | ||
2152 | GNUNET_break (0); | ||
2153 | return; | ||
2154 | } | ||
2155 | if (0 == proc->limit) | ||
2156 | { | ||
2157 | /* what is this!? should never happen */ | ||
2158 | GNUNET_break (0); | ||
2159 | return; | ||
2160 | } | ||
2161 | proc->zi->seq = seq; | ||
2162 | if (0 < send_lookup_response_with_filter (proc->zi->nc, | ||
2163 | proc->zi->request_id, | ||
2164 | zone_key, | ||
2165 | name, | ||
2166 | rd_count, | ||
2167 | rd, | ||
2168 | proc->zi->filter)) | ||
2169 | proc->limit--; | ||
2170 | else | ||
2171 | proc->run_again = GNUNET_YES; | ||
2172 | } | ||
2173 | |||
2174 | |||
2175 | /** | ||
2176 | * Perform the next round of the zone iteration. | ||
2177 | * | ||
2178 | * @param zi zone iterator to process | ||
2179 | * @param limit number of results to return in one pass | ||
2180 | */ | ||
2181 | static void | ||
2182 | run_zone_iteration_round (struct ZoneIteration *zi, uint64_t limit) | ||
2183 | { | ||
2184 | struct ZoneIterationProcResult proc; | ||
2185 | struct GNUNET_TIME_Absolute start; | ||
2186 | struct GNUNET_TIME_Relative duration; | ||
2187 | struct NamestoreClient *nc = zi->nc; | ||
2188 | |||
2189 | memset (&proc, 0, sizeof(proc)); | ||
2190 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
2191 | "Asked to return up to %llu records at position %llu\n", | ||
2192 | (unsigned long long) limit, | ||
2193 | (unsigned long long) zi->seq); | ||
2194 | proc.zi = zi; | ||
2195 | proc.limit = limit; | ||
2196 | proc.run_again = GNUNET_YES; | ||
2197 | start = GNUNET_TIME_absolute_get (); | ||
2198 | while (GNUNET_YES == proc.run_again) | ||
2199 | { | ||
2200 | proc.run_again = GNUNET_NO; | ||
2201 | GNUNET_break (GNUNET_SYSERR != | ||
2202 | nc->GSN_database->iterate_records (nc->GSN_database->cls, | ||
2203 | (GNUNET_YES == | ||
2204 | GNUNET_is_zero ( | ||
2205 | &zi->zone)) | ||
2206 | ? NULL | ||
2207 | : &zi->zone, | ||
2208 | zi->seq, | ||
2209 | proc.limit, | ||
2210 | &zone_iterate_proc, | ||
2211 | &proc)); | ||
2212 | } | ||
2213 | duration = GNUNET_TIME_absolute_get_duration (start); | ||
2214 | duration = GNUNET_TIME_relative_divide (duration, limit - proc.limit); | ||
2215 | GNUNET_STATISTICS_set (statistics, | ||
2216 | "NAMESTORE iteration delay (μs/record)", | ||
2217 | duration.rel_value_us, | ||
2218 | GNUNET_NO); | ||
2219 | if (0 == proc.limit) | ||
2220 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
2221 | "Returned %llu results, more results available\n", | ||
2222 | (unsigned long long) limit); | ||
2223 | zi->send_end = (0 != proc.limit); | ||
2224 | if (0 == zi->cache_ops) | ||
2225 | zone_iteration_done_client_continue (zi); | ||
2226 | } | ||
2227 | |||
2228 | static enum GNUNET_GenericReturnValue | ||
2229 | check_iteration_start (void *cls, | ||
2230 | const struct ZoneIterationStartMessage *zis_msg) | ||
2231 | { | ||
2232 | uint16_t size; | ||
2233 | size_t key_len; | ||
2234 | |||
2235 | size = ntohs (zis_msg->gns_header.header.size); | ||
2236 | key_len = ntohs (zis_msg->key_len); | ||
2237 | |||
2238 | if (size < key_len + sizeof(*zis_msg)) | ||
2239 | { | ||
2240 | GNUNET_break (0); | ||
2241 | return GNUNET_SYSERR; | ||
2242 | } | ||
2243 | return GNUNET_OK; | ||
2244 | } | ||
2245 | |||
2246 | |||
2247 | /** | ||
2248 | * Handles a #GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_ITERATION_START message | ||
2249 | * | ||
2250 | * @param cls the client sending the message | ||
2251 | * @param zis_msg message from the client | ||
2252 | */ | ||
2253 | static void | ||
2254 | handle_iteration_start (void *cls, | ||
2255 | const struct ZoneIterationStartMessage *zis_msg) | ||
2256 | { | ||
2257 | struct GNUNET_CRYPTO_PrivateKey zone; | ||
2258 | struct NamestoreClient *nc = cls; | ||
2259 | struct ZoneIteration *zi; | ||
2260 | size_t key_len; | ||
2261 | size_t kb_read; | ||
2262 | |||
2263 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
2264 | "Received ZONE_ITERATION_START message\n"); | ||
2265 | key_len = ntohs (zis_msg->key_len); | ||
2266 | zi = GNUNET_new (struct ZoneIteration); | ||
2267 | if (0 < key_len) | ||
2268 | { | ||
2269 | if ((GNUNET_SYSERR == | ||
2270 | GNUNET_CRYPTO_read_private_key_from_buffer (&zis_msg[1], | ||
2271 | key_len, | ||
2272 | &zone, | ||
2273 | &kb_read)) || | ||
2274 | (kb_read != key_len)) | ||
2275 | { | ||
2276 | GNUNET_SERVICE_client_drop (nc->client); | ||
2277 | GNUNET_free (zi); | ||
2278 | return; | ||
2279 | } | ||
2280 | zi->zone = zone; | ||
2281 | } | ||
2282 | zi->request_id = ntohl (zis_msg->gns_header.r_id); | ||
2283 | zi->filter = ntohs (zis_msg->filter); | ||
2284 | zi->offset = 0; | ||
2285 | zi->nc = nc; | ||
2286 | GNUNET_CONTAINER_DLL_insert (nc->op_head, nc->op_tail, zi); | ||
2287 | run_zone_iteration_round (zi, 1); | ||
2288 | } | ||
2289 | |||
2290 | |||
2291 | /** | ||
2292 | * Handles a #GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_ITERATION_STOP message | ||
2293 | * | ||
2294 | * @param cls the client sending the message | ||
2295 | * @param zis_msg message from the client | ||
2296 | */ | ||
2297 | static void | ||
2298 | handle_iteration_stop (void *cls, | ||
2299 | const struct ZoneIterationStopMessage *zis_msg) | ||
2300 | { | ||
2301 | struct NamestoreClient *nc = cls; | ||
2302 | struct ZoneIteration *zi; | ||
2303 | uint32_t rid; | ||
2304 | |||
2305 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
2306 | "Received ZONE_ITERATION_STOP message\n"); | ||
2307 | rid = ntohl (zis_msg->gns_header.r_id); | ||
2308 | for (zi = nc->op_head; NULL != zi; zi = zi->next) | ||
2309 | if (zi->request_id == rid) | ||
2310 | break; | ||
2311 | if (NULL == zi) | ||
2312 | { | ||
2313 | GNUNET_break (0); | ||
2314 | GNUNET_SERVICE_client_drop (nc->client); | ||
2315 | return; | ||
2316 | } | ||
2317 | GNUNET_CONTAINER_DLL_remove (nc->op_head, nc->op_tail, zi); | ||
2318 | GNUNET_free (zi); | ||
2319 | GNUNET_SERVICE_client_continue (nc->client); | ||
2320 | } | ||
2321 | |||
2322 | |||
2323 | /** | ||
2324 | * Handles a #GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_ITERATION_NEXT message | ||
2325 | * | ||
2326 | * @param cls the client sending the message | ||
2327 | * @param zis_msg message from the client | ||
2328 | */ | ||
2329 | static void | ||
2330 | handle_iteration_next (void *cls, | ||
2331 | const struct ZoneIterationNextMessage *zis_msg) | ||
2332 | { | ||
2333 | struct NamestoreClient *nc = cls; | ||
2334 | struct ZoneIteration *zi; | ||
2335 | uint32_t rid; | ||
2336 | uint64_t limit; | ||
2337 | |||
2338 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
2339 | "Received ZONE_ITERATION_NEXT message\n"); | ||
2340 | GNUNET_STATISTICS_update (statistics, | ||
2341 | "Iteration NEXT messages received", | ||
2342 | 1, | ||
2343 | GNUNET_NO); | ||
2344 | rid = ntohl (zis_msg->gns_header.r_id); | ||
2345 | limit = GNUNET_ntohll (zis_msg->limit); | ||
2346 | for (zi = nc->op_head; NULL != zi; zi = zi->next) | ||
2347 | if (zi->request_id == rid) | ||
2348 | break; | ||
2349 | if (NULL == zi) | ||
2350 | { | ||
2351 | GNUNET_break (0); | ||
2352 | GNUNET_SERVICE_client_drop (nc->client); | ||
2353 | return; | ||
2354 | } | ||
2355 | run_zone_iteration_round (zi, limit); | ||
2356 | } | ||
2357 | |||
2358 | |||
2359 | /** | ||
2360 | * Function called when the monitor is ready for more data, and we | ||
2361 | * should thus unblock PUT operations that were blocked on the | ||
2362 | * monitor not being ready. | ||
2363 | */ | ||
2364 | static void | ||
2365 | monitor_unblock (struct ZoneMonitor *zm) | ||
2366 | { | ||
2367 | struct StoreActivity *sa = sa_head; | ||
2368 | |||
2369 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
2370 | "Unblocking zone monitor %p\n", zm); | ||
2371 | while ((NULL != sa) && (zm->limit > zm->iteration_cnt)) | ||
2372 | { | ||
2373 | struct StoreActivity *sn = sa->next; | ||
2374 | |||
2375 | if (sa->zm_pos == zm) | ||
2376 | continue_store_activity (sa, GNUNET_YES); | ||
2377 | sa = sn; | ||
2378 | } | ||
2379 | if (zm->limit > zm->iteration_cnt) | ||
2380 | { | ||
2381 | zm->sa_waiting = GNUNET_NO; | ||
2382 | if (NULL != zm->sa_wait_warning) | ||
2383 | { | ||
2384 | GNUNET_SCHEDULER_cancel (zm->sa_wait_warning); | ||
2385 | zm->sa_wait_warning = NULL; | ||
2386 | } | ||
2387 | } | ||
2388 | else if (GNUNET_YES == zm->sa_waiting) | ||
2389 | { | ||
2390 | zm->sa_waiting_start = GNUNET_TIME_absolute_get (); | ||
2391 | if (NULL != zm->sa_wait_warning) | ||
2392 | GNUNET_SCHEDULER_cancel (zm->sa_wait_warning); | ||
2393 | zm->sa_wait_warning = | ||
2394 | GNUNET_SCHEDULER_add_delayed (MONITOR_STALL_WARN_DELAY, | ||
2395 | &warn_monitor_slow, | ||
2396 | zm); | ||
2397 | } | ||
2398 | } | ||
2399 | |||
2400 | |||
2401 | /** | ||
2402 | * Send 'sync' message to zone monitor, we're now in sync. | ||
2403 | * | ||
2404 | * @param zm monitor that is now in sync | ||
2405 | */ | ||
2406 | static void | ||
2407 | monitor_sync (struct ZoneMonitor *zm) | ||
2408 | { | ||
2409 | struct GNUNET_MQ_Envelope *env; | ||
2410 | struct GNUNET_MessageHeader *sync; | ||
2411 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
2412 | "Synching zone monitor %p\n", zm); | ||
2413 | |||
2414 | env = GNUNET_MQ_msg (sync, GNUNET_MESSAGE_TYPE_NAMESTORE_MONITOR_SYNC); | ||
2415 | GNUNET_MQ_send (zm->nc->mq, env); | ||
2416 | /* mark iteration done */ | ||
2417 | zm->in_first_iteration = GNUNET_NO; | ||
2418 | zm->iteration_cnt = 0; | ||
2419 | if ((zm->limit > 0) && (zm->sa_waiting)) | ||
2420 | monitor_unblock (zm); | ||
2421 | } | ||
2422 | |||
2423 | |||
2424 | /** | ||
2425 | * Obtain the next datum during the zone monitor's zone initial iteration. | ||
2426 | * | ||
2427 | * @param cls zone monitor that does its initial iteration | ||
2428 | */ | ||
2429 | static void | ||
2430 | monitor_iteration_next (void *cls); | ||
2431 | |||
2432 | |||
2433 | /** | ||
2434 | * A #GNUNET_NAMESTORE_RecordIterator for monitors. | ||
2435 | * | ||
2436 | * @param cls a 'struct ZoneMonitor *' with information about the monitor | ||
2437 | * @param seq sequence number of the record, MUST NOT BE ZERO | ||
2438 | * @param zone_key zone key of the zone | ||
2439 | * @param name name | ||
2440 | * @param rd_count number of records in @a rd | ||
2441 | * @param rd array of records | ||
2442 | */ | ||
2443 | static void | ||
2444 | monitor_iterate_cb (void *cls, | ||
2445 | uint64_t seq, | ||
2446 | const struct GNUNET_CRYPTO_PrivateKey *zone_key, | ||
2447 | const char *name, | ||
2448 | unsigned int rd_count, | ||
2449 | const struct GNUNET_GNSRECORD_Data *rd) | ||
2450 | { | ||
2451 | struct ZoneMonitor *zm = cls; | ||
2452 | |||
2453 | GNUNET_assert (0 != seq); | ||
2454 | zm->seq = seq; | ||
2455 | GNUNET_assert (NULL != name); | ||
2456 | GNUNET_STATISTICS_update (statistics, | ||
2457 | "Monitor notifications sent", | ||
2458 | 1, | ||
2459 | GNUNET_NO); | ||
2460 | if (0 < send_lookup_response_with_filter (zm->nc, 0, zone_key, name, | ||
2461 | rd_count, rd, zm->filter)) | ||
2462 | { | ||
2463 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
2464 | "Sent records.\n"); | ||
2465 | zm->limit--; | ||
2466 | zm->iteration_cnt--; | ||
2467 | } | ||
2468 | else | ||
2469 | zm->run_again = GNUNET_YES; | ||
2470 | if ((0 == zm->iteration_cnt) && (0 != zm->limit)) | ||
2471 | { | ||
2472 | /* We are done with the current iteration batch, AND the | ||
2473 | client would right now accept more, so go again! */ | ||
2474 | GNUNET_assert (NULL == zm->task); | ||
2475 | zm->task = GNUNET_SCHEDULER_add_now (&monitor_iteration_next, zm); | ||
2476 | } | ||
2477 | } | ||
2478 | |||
2479 | static enum GNUNET_GenericReturnValue | ||
2480 | check_monitor_start (void *cls, | ||
2481 | const struct ZoneMonitorStartMessage *zis_msg) | ||
2482 | { | ||
2483 | uint16_t size; | ||
2484 | size_t key_len; | ||
2485 | |||
2486 | size = ntohs (zis_msg->header.size); | ||
2487 | key_len = ntohs (zis_msg->key_len); | ||
2488 | |||
2489 | if (size < key_len + sizeof(*zis_msg)) | ||
2490 | { | ||
2491 | GNUNET_break (0); | ||
2492 | return GNUNET_SYSERR; | ||
2493 | } | ||
2494 | return GNUNET_OK; | ||
2495 | } | ||
2496 | |||
2497 | |||
2498 | /** | ||
2499 | * Handles a #GNUNET_MESSAGE_TYPE_NAMESTORE_MONITOR_START message | ||
2500 | * | ||
2501 | * @param cls the client sending the message | ||
2502 | * @param zis_msg message from the client | ||
2503 | */ | ||
2504 | static void | ||
2505 | handle_monitor_start (void *cls, const struct | ||
2506 | ZoneMonitorStartMessage *zis_msg) | ||
2507 | { | ||
2508 | struct GNUNET_CRYPTO_PrivateKey zone; | ||
2509 | struct NamestoreClient *nc = cls; | ||
2510 | struct ZoneMonitor *zm; | ||
2511 | size_t key_len; | ||
2512 | size_t kb_read; | ||
2513 | |||
2514 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
2515 | "Received ZONE_MONITOR_START message\n"); | ||
2516 | zm = GNUNET_new (struct ZoneMonitor); | ||
2517 | zm->nc = nc; | ||
2518 | key_len = ntohs (zis_msg->key_len); | ||
2519 | if (0 < key_len) | ||
2520 | { | ||
2521 | if ((GNUNET_SYSERR == | ||
2522 | GNUNET_CRYPTO_read_private_key_from_buffer (&zis_msg[1], | ||
2523 | key_len, | ||
2524 | &zone, | ||
2525 | &kb_read)) || | ||
2526 | (kb_read != key_len)) | ||
2527 | { | ||
2528 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
2529 | "Error reading private key\n"); | ||
2530 | GNUNET_SERVICE_client_drop (nc->client); | ||
2531 | GNUNET_free (zm); | ||
2532 | return; | ||
2533 | } | ||
2534 | zm->zone = zone; | ||
2535 | } | ||
2536 | zm->limit = 1; | ||
2537 | zm->filter = ntohs (zis_msg->filter); | ||
2538 | zm->in_first_iteration = (GNUNET_YES == ntohl (zis_msg->iterate_first)); | ||
2539 | GNUNET_CONTAINER_DLL_insert (monitor_head, monitor_tail, zm); | ||
2540 | GNUNET_SERVICE_client_mark_monitor (nc->client); | ||
2541 | GNUNET_SERVICE_client_continue (nc->client); | ||
2542 | GNUNET_notification_context_add (monitor_nc, nc->mq); | ||
2543 | if (zm->in_first_iteration) | ||
2544 | zm->task = GNUNET_SCHEDULER_add_now (&monitor_iteration_next, zm); | ||
2545 | else | ||
2546 | monitor_sync (zm); | ||
2547 | } | ||
2548 | |||
2549 | |||
2550 | /** | ||
2551 | * Obtain the next datum during the zone monitor's zone initial iteration. | ||
2552 | * | ||
2553 | * @param cls zone monitor that does its initial iteration | ||
2554 | */ | ||
2555 | static void | ||
2556 | monitor_iteration_next (void *cls) | ||
2557 | { | ||
2558 | struct ZoneMonitor *zm = cls; | ||
2559 | struct NamestoreClient *nc = zm->nc; | ||
2560 | int ret; | ||
2561 | |||
2562 | zm->task = NULL; | ||
2563 | GNUNET_assert (0 == zm->iteration_cnt); | ||
2564 | if (zm->limit > 16) | ||
2565 | zm->iteration_cnt = zm->limit / 2; /* leave half for monitor events */ | ||
2566 | else | ||
2567 | zm->iteration_cnt = zm->limit; /* use it all */ | ||
2568 | zm->run_again = GNUNET_YES; | ||
2569 | while (GNUNET_YES == zm->run_again) | ||
2570 | { | ||
2571 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
2572 | "Running iteration\n"); | ||
2573 | zm->run_again = GNUNET_NO; | ||
2574 | ret = nc->GSN_database->iterate_records (nc->GSN_database->cls, | ||
2575 | (GNUNET_YES == GNUNET_is_zero ( | ||
2576 | &zm->zone)) ? NULL : &zm->zone, | ||
2577 | zm->seq, | ||
2578 | zm->iteration_cnt, | ||
2579 | &monitor_iterate_cb, | ||
2580 | zm); | ||
2581 | } | ||
2582 | if (GNUNET_SYSERR == ret) | ||
2583 | { | ||
2584 | GNUNET_SERVICE_client_drop (zm->nc->client); | ||
2585 | return; | ||
2586 | } | ||
2587 | if (GNUNET_NO == ret) | ||
2588 | { | ||
2589 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
2590 | "Zone empty... syncing\n"); | ||
2591 | /* empty zone */ | ||
2592 | monitor_sync (zm); | ||
2593 | return; | ||
2594 | } | ||
2595 | } | ||
2596 | |||
2597 | /** | ||
2598 | * Handles a #GNUNET_MESSAGE_TYPE_NAMESTORE_MONITOR_NEXT message | ||
2599 | * | ||
2600 | * @param cls the client sending the message | ||
2601 | * @param nm message from the client | ||
2602 | */ | ||
2603 | static void | ||
2604 | handle_monitor_next (void *cls, const struct ZoneMonitorNextMessage *nm) | ||
2605 | { | ||
2606 | struct NamestoreClient *nc = cls; | ||
2607 | struct ZoneMonitor *zm; | ||
2608 | uint64_t inc; | ||
2609 | |||
2610 | inc = GNUNET_ntohll (nm->limit); | ||
2611 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
2612 | "Received ZONE_MONITOR_NEXT message with limit %llu\n", | ||
2613 | (unsigned long long) inc); | ||
2614 | for (zm = monitor_head; NULL != zm; zm = zm->next) | ||
2615 | if (zm->nc == nc) | ||
2616 | break; | ||
2617 | if (NULL == zm) | ||
2618 | { | ||
2619 | GNUNET_break (0); | ||
2620 | GNUNET_SERVICE_client_drop (nc->client); | ||
2621 | return; | ||
2622 | } | ||
2623 | GNUNET_SERVICE_client_continue (nc->client); | ||
2624 | if (zm->limit + inc < zm->limit) | ||
2625 | { | ||
2626 | GNUNET_break (0); | ||
2627 | GNUNET_SERVICE_client_drop (nc->client); | ||
2628 | return; | ||
2629 | } | ||
2630 | zm->limit += inc; | ||
2631 | if ((zm->in_first_iteration) && (zm->limit == inc)) | ||
2632 | { | ||
2633 | /* We are still iterating, and the previous iteration must | ||
2634 | have stopped due to the client's limit, so continue it! */ | ||
2635 | GNUNET_assert (NULL == zm->task); | ||
2636 | zm->task = GNUNET_SCHEDULER_add_now (&monitor_iteration_next, zm); | ||
2637 | } | ||
2638 | GNUNET_assert (zm->iteration_cnt <= zm->limit); | ||
2639 | if ((zm->limit > zm->iteration_cnt) && (zm->sa_waiting)) | ||
2640 | { | ||
2641 | monitor_unblock (zm); | ||
2642 | } | ||
2643 | else if (GNUNET_YES == zm->sa_waiting) | ||
2644 | { | ||
2645 | if (NULL != zm->sa_wait_warning) | ||
2646 | GNUNET_SCHEDULER_cancel (zm->sa_wait_warning); | ||
2647 | zm->sa_waiting_start = GNUNET_TIME_absolute_get (); | ||
2648 | zm->sa_wait_warning = | ||
2649 | GNUNET_SCHEDULER_add_delayed (MONITOR_STALL_WARN_DELAY, | ||
2650 | &warn_monitor_slow, | ||
2651 | zm); | ||
2652 | } | ||
2653 | } | ||
2654 | |||
2655 | /** | ||
2656 | * Process namestore requests. | ||
2657 | * | ||
2658 | * @param cls closure | ||
2659 | * @param cfg configuration to use | ||
2660 | * @param service the initialized service | ||
2661 | */ | ||
2662 | static void | ||
2663 | run (void *cls, | ||
2664 | const struct GNUNET_CONFIGURATION_Handle *cfg, | ||
2665 | struct GNUNET_SERVICE_Handle *service) | ||
2666 | { | ||
2667 | char *database; | ||
2668 | (void) cls; | ||
2669 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Starting namestore service\n"); | ||
2670 | return_orphaned = GNUNET_CONFIGURATION_get_value_yesno (cfg, | ||
2671 | "namestore", | ||
2672 | "RETURN_ORPHANED"); | ||
2673 | GSN_cfg = cfg; | ||
2674 | monitor_nc = GNUNET_notification_context_create (1); | ||
2675 | statistics = GNUNET_STATISTICS_create ("namestore", cfg); | ||
2676 | /* Loading database plugin */ | ||
2677 | if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_string (cfg, | ||
2678 | "namestore", | ||
2679 | "database", | ||
2680 | &database)) | ||
2681 | { | ||
2682 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "No database backend configured\n"); | ||
2683 | GNUNET_SCHEDULER_add_now (&cleanup_task, NULL); | ||
2684 | return; | ||
2685 | } | ||
2686 | GNUNET_asprintf (&db_lib_name, "libgnunet_plugin_namestore_%s", database); | ||
2687 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Loading %s\n", db_lib_name); | ||
2688 | GSN_database = GNUNET_PLUGIN_load (db_lib_name, (void *) cfg); | ||
2689 | GNUNET_free (database); | ||
2690 | if (NULL == GSN_database) | ||
2691 | { | ||
2692 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
2693 | "Could not load database backend `%s'\n", | ||
2694 | db_lib_name); | ||
2695 | GNUNET_free (db_lib_name); | ||
2696 | GNUNET_SCHEDULER_add_now (&cleanup_task, NULL); | ||
2697 | return; | ||
2698 | } | ||
2699 | GNUNET_SCHEDULER_add_shutdown (&cleanup_task, NULL); | ||
2700 | } | ||
2701 | |||
2702 | |||
2703 | /** | ||
2704 | * Define "main" method using service macro. | ||
2705 | */ | ||
2706 | GNUNET_SERVICE_MAIN ( | ||
2707 | "namestore", | ||
2708 | GNUNET_SERVICE_OPTION_NONE, | ||
2709 | &run, | ||
2710 | &client_connect_cb, | ||
2711 | &client_disconnect_cb, | ||
2712 | NULL, | ||
2713 | GNUNET_MQ_hd_fixed_size (tx_control, | ||
2714 | GNUNET_MESSAGE_TYPE_NAMESTORE_TX_CONTROL, | ||
2715 | struct TxControlMessage, | ||
2716 | NULL), | ||
2717 | GNUNET_MQ_hd_var_size (record_store, | ||
2718 | GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_STORE, | ||
2719 | struct RecordStoreMessage, | ||
2720 | NULL), | ||
2721 | GNUNET_MQ_hd_var_size (record_lookup, | ||
2722 | GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_LOOKUP, | ||
2723 | struct LabelLookupMessage, | ||
2724 | NULL), | ||
2725 | GNUNET_MQ_hd_var_size (zone_to_name, | ||
2726 | GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_TO_NAME, | ||
2727 | struct ZoneToNameMessage, | ||
2728 | NULL), | ||
2729 | GNUNET_MQ_hd_var_size (iteration_start, | ||
2730 | GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_ITERATION_START, | ||
2731 | struct ZoneIterationStartMessage, | ||
2732 | NULL), | ||
2733 | GNUNET_MQ_hd_fixed_size (iteration_next, | ||
2734 | GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_ITERATION_NEXT, | ||
2735 | struct ZoneIterationNextMessage, | ||
2736 | NULL), | ||
2737 | GNUNET_MQ_hd_fixed_size (iteration_stop, | ||
2738 | GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_ITERATION_STOP, | ||
2739 | struct ZoneIterationStopMessage, | ||
2740 | NULL), | ||
2741 | GNUNET_MQ_hd_var_size (monitor_start, | ||
2742 | GNUNET_MESSAGE_TYPE_NAMESTORE_MONITOR_START, | ||
2743 | struct ZoneMonitorStartMessage, | ||
2744 | NULL), | ||
2745 | GNUNET_MQ_hd_fixed_size (monitor_next, | ||
2746 | GNUNET_MESSAGE_TYPE_NAMESTORE_MONITOR_NEXT, | ||
2747 | struct ZoneMonitorNextMessage, | ||
2748 | NULL), | ||
2749 | GNUNET_MQ_handler_end ()); | ||
2750 | |||
2751 | |||
2752 | /* 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 c7e0cf65f..000000000 --- a/src/namestore/gnunet-zoneimport.c +++ /dev/null | |||
@@ -1,1872 +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_gnsrecord_lib.h> | ||
28 | #include <gnunet_namestore_service.h> | ||
29 | #include <gnunet_statistics_service.h> | ||
30 | #include <gnunet_identity_service.h> | ||
31 | |||
32 | |||
33 | /** | ||
34 | * Maximum number of queries pending at the same time. | ||
35 | */ | ||
36 | #define THRESH 100 | ||
37 | |||
38 | /** | ||
39 | * TIME_THRESH is in usecs. How quickly do we submit fresh queries. | ||
40 | * Used as an additional throttle. | ||
41 | */ | ||
42 | #define TIME_THRESH 10 | ||
43 | |||
44 | /** | ||
45 | * How often do we retry a query before giving up for good? | ||
46 | */ | ||
47 | #define MAX_RETRIES 5 | ||
48 | |||
49 | /** | ||
50 | * How many DNS requests do we at most issue in rapid series? | ||
51 | */ | ||
52 | #define MAX_SERIES 10 | ||
53 | |||
54 | /** | ||
55 | * How long do we wait at least between series of requests? | ||
56 | */ | ||
57 | #define SERIES_DELAY \ | ||
58 | GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MICROSECONDS, 10) | ||
59 | |||
60 | /** | ||
61 | * How long do DNS records have to last at least after being imported? | ||
62 | */ | ||
63 | static struct GNUNET_TIME_Relative minimum_expiration_time; | ||
64 | |||
65 | /** | ||
66 | * How many requests do we request from NAMESTORE in one batch | ||
67 | * during our initial iteration? | ||
68 | */ | ||
69 | #define NS_BATCH_SIZE 1024 | ||
70 | |||
71 | /** | ||
72 | * Some zones may include authoritative records for other | ||
73 | * zones, such as foo.com.uk or bar.com.fr. As for GNS | ||
74 | * each dot represents a zone cut, we then need to create a | ||
75 | * zone on-the-fly to capture those records properly. | ||
76 | */ | ||
77 | struct Zone | ||
78 | { | ||
79 | /** | ||
80 | * Kept in a DLL. | ||
81 | */ | ||
82 | struct Zone *next; | ||
83 | |||
84 | /** | ||
85 | * Kept in a DLL. | ||
86 | */ | ||
87 | struct Zone *prev; | ||
88 | |||
89 | /** | ||
90 | * Domain of the zone (i.e. "fr" or "com.fr") | ||
91 | */ | ||
92 | char *domain; | ||
93 | |||
94 | /** | ||
95 | * Private key of the zone. | ||
96 | */ | ||
97 | struct GNUNET_CRYPTO_PrivateKey key; | ||
98 | }; | ||
99 | |||
100 | |||
101 | /** | ||
102 | * Record for the request to be stored by GNS. | ||
103 | */ | ||
104 | struct Record | ||
105 | { | ||
106 | /** | ||
107 | * Kept in a DLL. | ||
108 | */ | ||
109 | struct Record *next; | ||
110 | |||
111 | /** | ||
112 | * Kept in a DLL. | ||
113 | */ | ||
114 | struct Record *prev; | ||
115 | |||
116 | /** | ||
117 | * GNS record. | ||
118 | */ | ||
119 | struct GNUNET_GNSRECORD_Data grd; | ||
120 | }; | ||
121 | |||
122 | |||
123 | /** | ||
124 | * Request we should make. We keep this struct in memory per request, | ||
125 | * thus optimizing it is crucial for the overall memory consumption of | ||
126 | * the zone importer. | ||
127 | */ | ||
128 | struct Request | ||
129 | { | ||
130 | /** | ||
131 | * Requests are kept in a heap while waiting to be resolved. | ||
132 | */ | ||
133 | struct GNUNET_CONTAINER_HeapNode *hn; | ||
134 | |||
135 | /** | ||
136 | * Active requests are kept in a DLL. | ||
137 | */ | ||
138 | struct Request *next; | ||
139 | |||
140 | /** | ||
141 | * Active requests are kept in a DLL. | ||
142 | */ | ||
143 | struct Request *prev; | ||
144 | |||
145 | /** | ||
146 | * Head of records that should be published in GNS for | ||
147 | * this hostname. | ||
148 | */ | ||
149 | struct Record *rec_head; | ||
150 | |||
151 | /** | ||
152 | * Tail of records that should be published in GNS for | ||
153 | * this hostname. | ||
154 | */ | ||
155 | struct Record *rec_tail; | ||
156 | |||
157 | /** | ||
158 | * Socket used to make the request, NULL if not active. | ||
159 | */ | ||
160 | struct GNUNET_DNSSTUB_RequestSocket *rs; | ||
161 | |||
162 | /** | ||
163 | * Hostname we are resolving, allocated at the end of | ||
164 | * this struct (optimizing memory consumption by reducing | ||
165 | * total number of allocations). | ||
166 | */ | ||
167 | char *hostname; | ||
168 | |||
169 | /** | ||
170 | * Namestore operation pending for this record. | ||
171 | */ | ||
172 | struct GNUNET_NAMESTORE_QueueEntry *qe; | ||
173 | |||
174 | /** | ||
175 | * Zone responsible for this request. | ||
176 | */ | ||
177 | const struct Zone *zone; | ||
178 | |||
179 | /** | ||
180 | * At what time does the (earliest) of the returned records | ||
181 | * for this name expire? At this point, we need to re-fetch | ||
182 | * the record. | ||
183 | */ | ||
184 | struct GNUNET_TIME_Absolute expires; | ||
185 | |||
186 | /** | ||
187 | * While we are fetching the record, the value is set to the | ||
188 | * starting time of the DNS operation. While doing a | ||
189 | * NAMESTORE store, again set to the start time of the | ||
190 | * NAMESTORE operation. | ||
191 | */ | ||
192 | struct GNUNET_TIME_Absolute op_start_time; | ||
193 | |||
194 | /** | ||
195 | * How often did we issue this query? (And failed, reset | ||
196 | * to zero once we were successful.) | ||
197 | */ | ||
198 | unsigned int issue_num; | ||
199 | |||
200 | /** | ||
201 | * random 16-bit DNS query identifier. | ||
202 | */ | ||
203 | uint16_t id; | ||
204 | }; | ||
205 | |||
206 | |||
207 | /** | ||
208 | * Command-line argument specifying desired size of the hash map with | ||
209 | * all of our pending names. Usually, we use an automatically growing | ||
210 | * map, but this is only OK up to about a million entries. Above that | ||
211 | * number, the user must explicitly specify the size at startup. | ||
212 | */ | ||
213 | static unsigned int map_size = 1024; | ||
214 | |||
215 | /** | ||
216 | * Handle to the identity service. | ||
217 | */ | ||
218 | static struct GNUNET_IDENTITY_Handle *id; | ||
219 | |||
220 | /** | ||
221 | * Namestore handle. | ||
222 | */ | ||
223 | static struct GNUNET_NAMESTORE_Handle *ns; | ||
224 | |||
225 | /** | ||
226 | * Handle to the statistics service. | ||
227 | */ | ||
228 | static struct GNUNET_STATISTICS_Handle *stats; | ||
229 | |||
230 | /** | ||
231 | * Context for DNS resolution. | ||
232 | */ | ||
233 | static struct GNUNET_DNSSTUB_Context *ctx; | ||
234 | |||
235 | /** | ||
236 | * The number of DNS queries that are outstanding | ||
237 | */ | ||
238 | static unsigned int pending; | ||
239 | |||
240 | /** | ||
241 | * The number of NAMESTORE record store operations that are outstanding | ||
242 | */ | ||
243 | static unsigned int pending_rs; | ||
244 | |||
245 | /** | ||
246 | * Number of lookups we performed overall. | ||
247 | */ | ||
248 | static unsigned int lookups; | ||
249 | |||
250 | /** | ||
251 | * Number of records we had cached. | ||
252 | */ | ||
253 | static unsigned int cached; | ||
254 | |||
255 | /** | ||
256 | * How many hostnames did we reject (malformed). | ||
257 | */ | ||
258 | static unsigned int rejects; | ||
259 | |||
260 | /** | ||
261 | * Number of lookups that failed. | ||
262 | */ | ||
263 | static unsigned int failures; | ||
264 | |||
265 | /** | ||
266 | * Number of records we found. | ||
267 | */ | ||
268 | static unsigned int records; | ||
269 | |||
270 | /** | ||
271 | * Number of record sets given to namestore. | ||
272 | */ | ||
273 | static unsigned int record_sets; | ||
274 | |||
275 | /** | ||
276 | * Heap of all requests to perform, sorted by | ||
277 | * the time we should next do the request (i.e. by expires). | ||
278 | */ | ||
279 | static struct GNUNET_CONTAINER_Heap *req_heap; | ||
280 | |||
281 | /** | ||
282 | * Active requests are kept in a DLL. | ||
283 | */ | ||
284 | static struct Request *req_head; | ||
285 | |||
286 | /** | ||
287 | * Active requests are kept in a DLL. | ||
288 | */ | ||
289 | static struct Request *req_tail; | ||
290 | |||
291 | /** | ||
292 | * Main task. | ||
293 | */ | ||
294 | static struct GNUNET_SCHEDULER_Task *t; | ||
295 | |||
296 | /** | ||
297 | * Hash map of requests for which we may still get a response from | ||
298 | * the namestore. Set to NULL once the initial namestore iteration | ||
299 | * is done. | ||
300 | */ | ||
301 | static struct GNUNET_CONTAINER_MultiHashMap *ns_pending; | ||
302 | |||
303 | /** | ||
304 | * Current zone iteration handle. | ||
305 | */ | ||
306 | static struct GNUNET_NAMESTORE_ZoneIterator *zone_it; | ||
307 | |||
308 | /** | ||
309 | * Head of list of zones we are managing. | ||
310 | */ | ||
311 | static struct Zone *zone_head; | ||
312 | |||
313 | /** | ||
314 | * Tail of list of zones we are managing. | ||
315 | */ | ||
316 | static struct Zone *zone_tail; | ||
317 | |||
318 | /** | ||
319 | * After how many more results must #ns_lookup_result_cb() ask | ||
320 | * the namestore for more? | ||
321 | */ | ||
322 | static uint64_t ns_iterator_trigger_next; | ||
323 | |||
324 | /** | ||
325 | * Number of DNS requests counted in latency total. | ||
326 | */ | ||
327 | static uint64_t total_dns_latency_cnt; | ||
328 | |||
329 | /** | ||
330 | * Sum of DNS latencies observed. | ||
331 | */ | ||
332 | static struct GNUNET_TIME_Relative total_dns_latency; | ||
333 | |||
334 | /** | ||
335 | * Number of records processed (DNS lookup, no NAMESTORE) in total. | ||
336 | */ | ||
337 | static uint64_t total_reg_proc_dns; | ||
338 | |||
339 | /** | ||
340 | * Number of records processed (DNS lookup, with NAMESTORE) in total. | ||
341 | */ | ||
342 | static uint64_t total_reg_proc_dns_ns; | ||
343 | |||
344 | /** | ||
345 | * Start time of the regular processing. | ||
346 | */ | ||
347 | static struct GNUNET_TIME_Absolute start_time_reg_proc; | ||
348 | |||
349 | /** | ||
350 | * Last time we worked before going idle. | ||
351 | */ | ||
352 | static struct GNUNET_TIME_Absolute sleep_time_reg_proc; | ||
353 | |||
354 | /** | ||
355 | * Time we slept just waiting for work. | ||
356 | */ | ||
357 | static struct GNUNET_TIME_Relative idle_time; | ||
358 | |||
359 | |||
360 | /** | ||
361 | * Callback for #for_all_records | ||
362 | * | ||
363 | * @param cls closure | ||
364 | * @param rec a DNS record | ||
365 | */ | ||
366 | typedef void (*RecordProcessor) (void *cls, | ||
367 | const struct GNUNET_DNSPARSER_Record *rec); | ||
368 | |||
369 | |||
370 | /** | ||
371 | * Call @a rp for each record in @a p, regardless of | ||
372 | * what response section it is in. | ||
373 | * | ||
374 | * @param p packet from DNS | ||
375 | * @param rp function to call | ||
376 | * @param rp_cls closure for @a rp | ||
377 | */ | ||
378 | static void | ||
379 | for_all_records (const struct GNUNET_DNSPARSER_Packet *p, | ||
380 | RecordProcessor rp, | ||
381 | void *rp_cls) | ||
382 | { | ||
383 | for (unsigned int i = 0; i < p->num_answers; i++) | ||
384 | { | ||
385 | struct GNUNET_DNSPARSER_Record *rs = &p->answers[i]; | ||
386 | |||
387 | rp (rp_cls, rs); | ||
388 | } | ||
389 | for (unsigned int i = 0; i < p->num_authority_records; i++) | ||
390 | { | ||
391 | struct GNUNET_DNSPARSER_Record *rs = &p->authority_records[i]; | ||
392 | |||
393 | rp (rp_cls, rs); | ||
394 | } | ||
395 | for (unsigned int i = 0; i < p->num_additional_records; i++) | ||
396 | { | ||
397 | struct GNUNET_DNSPARSER_Record *rs = &p->additional_records[i]; | ||
398 | |||
399 | rp (rp_cls, rs); | ||
400 | } | ||
401 | } | ||
402 | |||
403 | |||
404 | /** | ||
405 | * Return just the label of the hostname in @a req. | ||
406 | * | ||
407 | * @param req request to process hostname of | ||
408 | * @return statically allocated pointer to the label, | ||
409 | * overwritten upon the next request! | ||
410 | */ | ||
411 | static const char * | ||
412 | get_label (struct Request *req) | ||
413 | { | ||
414 | static char label[64]; | ||
415 | const char *dot; | ||
416 | |||
417 | dot = strchr (req->hostname, (unsigned char) '.'); | ||
418 | if (NULL == dot) | ||
419 | { | ||
420 | GNUNET_break (0); | ||
421 | return NULL; | ||
422 | } | ||
423 | if (((size_t) (dot - req->hostname)) >= sizeof(label)) | ||
424 | { | ||
425 | GNUNET_break (0); | ||
426 | return NULL; | ||
427 | } | ||
428 | GNUNET_memcpy (label, req->hostname, dot - req->hostname); | ||
429 | label[dot - req->hostname] = '\0'; | ||
430 | return label; | ||
431 | } | ||
432 | |||
433 | |||
434 | /** | ||
435 | * Build DNS query for @a hostname. | ||
436 | * | ||
437 | * @param hostname host to build query for | ||
438 | * @param[out] raw_size number of bytes in the query | ||
439 | * @return NULL on error, otherwise pointer to statically (!) | ||
440 | * allocated query buffer | ||
441 | */ | ||
442 | static void * | ||
443 | build_dns_query (struct Request *req, size_t *raw_size) | ||
444 | { | ||
445 | static char raw[512]; | ||
446 | char *rawp; | ||
447 | struct GNUNET_DNSPARSER_Packet p; | ||
448 | struct GNUNET_DNSPARSER_Query q; | ||
449 | int ret; | ||
450 | |||
451 | q.name = (char *) req->hostname; | ||
452 | q.type = GNUNET_DNSPARSER_TYPE_NS; | ||
453 | q.dns_traffic_class = GNUNET_TUN_DNS_CLASS_INTERNET; | ||
454 | |||
455 | memset (&p, 0, sizeof(p)); | ||
456 | p.num_queries = 1; | ||
457 | p.queries = &q; | ||
458 | p.id = req->id; | ||
459 | ret = GNUNET_DNSPARSER_pack (&p, UINT16_MAX, &rawp, raw_size); | ||
460 | if (GNUNET_OK != ret) | ||
461 | { | ||
462 | if (GNUNET_NO == ret) | ||
463 | GNUNET_free (rawp); | ||
464 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
465 | "Failed to pack query for hostname `%s'\n", | ||
466 | req->hostname); | ||
467 | rejects++; | ||
468 | return NULL; | ||
469 | } | ||
470 | if (*raw_size > sizeof(raw)) | ||
471 | { | ||
472 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
473 | "Failed to pack query for hostname `%s'\n", | ||
474 | req->hostname); | ||
475 | rejects++; | ||
476 | GNUNET_break (0); | ||
477 | GNUNET_free (rawp); | ||
478 | return NULL; | ||
479 | } | ||
480 | GNUNET_memcpy (raw, rawp, *raw_size); | ||
481 | GNUNET_free (rawp); | ||
482 | return raw; | ||
483 | } | ||
484 | |||
485 | |||
486 | /** | ||
487 | * Free records associated with @a req. | ||
488 | * | ||
489 | * @param req request to free records of | ||
490 | */ | ||
491 | static void | ||
492 | free_records (struct Request *req) | ||
493 | { | ||
494 | struct Record *rec; | ||
495 | |||
496 | /* Free records */ | ||
497 | while (NULL != (rec = req->rec_head)) | ||
498 | { | ||
499 | GNUNET_CONTAINER_DLL_remove (req->rec_head, req->rec_tail, rec); | ||
500 | GNUNET_free (rec); | ||
501 | } | ||
502 | } | ||
503 | |||
504 | |||
505 | /** | ||
506 | * Free @a req and data structures reachable from it. | ||
507 | * | ||
508 | * @param req request to free | ||
509 | */ | ||
510 | static void | ||
511 | free_request (struct Request *req) | ||
512 | { | ||
513 | free_records (req); | ||
514 | GNUNET_free (req); | ||
515 | } | ||
516 | |||
517 | |||
518 | /** | ||
519 | * Process as many requests as possible from the queue. | ||
520 | * | ||
521 | * @param cls NULL | ||
522 | */ | ||
523 | static void | ||
524 | process_queue (void *cls); | ||
525 | |||
526 | |||
527 | /** | ||
528 | * Insert @a req into DLL sorted by next fetch time. | ||
529 | * | ||
530 | * @param req request to insert into #req_heap | ||
531 | */ | ||
532 | static void | ||
533 | insert_sorted (struct Request *req) | ||
534 | { | ||
535 | req->hn = | ||
536 | GNUNET_CONTAINER_heap_insert (req_heap, req, req->expires.abs_value_us); | ||
537 | if (req == GNUNET_CONTAINER_heap_peek (req_heap)) | ||
538 | { | ||
539 | if (NULL != t) | ||
540 | GNUNET_SCHEDULER_cancel (t); | ||
541 | sleep_time_reg_proc = GNUNET_TIME_absolute_get (); | ||
542 | t = GNUNET_SCHEDULER_add_at (req->expires, &process_queue, NULL); | ||
543 | } | ||
544 | } | ||
545 | |||
546 | |||
547 | /** | ||
548 | * Add record to the GNS record set for @a req. | ||
549 | * | ||
550 | * @param req the request to expand GNS record set for | ||
551 | * @param type type to use | ||
552 | * @param expiration_time when should @a rec expire | ||
553 | * @param data raw data to store | ||
554 | * @param data_len number of bytes in @a data | ||
555 | */ | ||
556 | static void | ||
557 | add_record (struct Request *req, | ||
558 | uint32_t type, | ||
559 | struct GNUNET_TIME_Absolute expiration_time, | ||
560 | const void *data, | ||
561 | size_t data_len) | ||
562 | { | ||
563 | struct Record *rec; | ||
564 | |||
565 | rec = GNUNET_malloc (sizeof(struct Record) + data_len); | ||
566 | rec->grd.data = &rec[1]; | ||
567 | rec->grd.expiration_time = expiration_time.abs_value_us; | ||
568 | rec->grd.data_size = data_len; | ||
569 | rec->grd.record_type = type; | ||
570 | rec->grd.flags = GNUNET_GNSRECORD_RF_NONE; | ||
571 | GNUNET_memcpy (&rec[1], data, data_len); | ||
572 | GNUNET_CONTAINER_DLL_insert (req->rec_head, req->rec_tail, rec); | ||
573 | } | ||
574 | |||
575 | |||
576 | /** | ||
577 | * Closure for #check_for_glue. | ||
578 | */ | ||
579 | struct GlueClosure | ||
580 | { | ||
581 | /** | ||
582 | * Overall request we are processing. | ||
583 | */ | ||
584 | struct Request *req; | ||
585 | |||
586 | /** | ||
587 | * NS name we are looking for glue for. | ||
588 | */ | ||
589 | const char *ns; | ||
590 | |||
591 | /** | ||
592 | * Set to #GNUNET_YES if glue was found. | ||
593 | */ | ||
594 | int found; | ||
595 | }; | ||
596 | |||
597 | |||
598 | /** | ||
599 | * Try to find glue records for a given NS record. | ||
600 | * | ||
601 | * @param cls a `struct GlueClosure *` | ||
602 | * @param rec record that may contain glue information | ||
603 | */ | ||
604 | static void | ||
605 | check_for_glue (void *cls, const struct GNUNET_DNSPARSER_Record *rec) | ||
606 | { | ||
607 | struct GlueClosure *gc = cls; | ||
608 | char dst[65536]; | ||
609 | size_t dst_len; | ||
610 | size_t off; | ||
611 | char ip[INET6_ADDRSTRLEN + 1]; | ||
612 | socklen_t ip_size = (socklen_t) sizeof(ip); | ||
613 | struct GNUNET_TIME_Absolute expiration_time; | ||
614 | struct GNUNET_TIME_Relative left; | ||
615 | |||
616 | if (0 != strcasecmp (rec->name, gc->ns)) | ||
617 | return; | ||
618 | expiration_time = rec->expiration_time; | ||
619 | left = GNUNET_TIME_absolute_get_remaining (expiration_time); | ||
620 | if (0 == left.rel_value_us) | ||
621 | return; /* ignore expired glue records */ | ||
622 | /* if expiration window is too short, bump it to configured minimum */ | ||
623 | if (left.rel_value_us < minimum_expiration_time.rel_value_us) | ||
624 | expiration_time = | ||
625 | GNUNET_TIME_relative_to_absolute (minimum_expiration_time); | ||
626 | dst_len = sizeof(dst); | ||
627 | off = 0; | ||
628 | switch (rec->type) | ||
629 | { | ||
630 | case GNUNET_DNSPARSER_TYPE_A: | ||
631 | if (sizeof(struct in_addr) != rec->data.raw.data_len) | ||
632 | { | ||
633 | GNUNET_break (0); | ||
634 | return; | ||
635 | } | ||
636 | if (NULL == inet_ntop (AF_INET, rec->data.raw.data, ip, ip_size)) | ||
637 | { | ||
638 | GNUNET_break (0); | ||
639 | return; | ||
640 | } | ||
641 | if ((GNUNET_OK == GNUNET_DNSPARSER_builder_add_name (dst, | ||
642 | dst_len, | ||
643 | &off, | ||
644 | gc->req->hostname)) && | ||
645 | (GNUNET_OK == | ||
646 | GNUNET_DNSPARSER_builder_add_name (dst, dst_len, &off, ip))) | ||
647 | { | ||
648 | add_record (gc->req, | ||
649 | GNUNET_GNSRECORD_TYPE_GNS2DNS, | ||
650 | expiration_time, | ||
651 | dst, | ||
652 | off); | ||
653 | gc->found = GNUNET_YES; | ||
654 | } | ||
655 | break; | ||
656 | |||
657 | case GNUNET_DNSPARSER_TYPE_AAAA: | ||
658 | if (sizeof(struct in6_addr) != rec->data.raw.data_len) | ||
659 | { | ||
660 | GNUNET_break (0); | ||
661 | return; | ||
662 | } | ||
663 | if (NULL == inet_ntop (AF_INET6, rec->data.raw.data, ip, ip_size)) | ||
664 | { | ||
665 | GNUNET_break (0); | ||
666 | return; | ||
667 | } | ||
668 | if ((GNUNET_OK == GNUNET_DNSPARSER_builder_add_name (dst, | ||
669 | dst_len, | ||
670 | &off, | ||
671 | gc->req->hostname)) && | ||
672 | (GNUNET_OK == | ||
673 | GNUNET_DNSPARSER_builder_add_name (dst, dst_len, &off, ip))) | ||
674 | { | ||
675 | add_record (gc->req, | ||
676 | GNUNET_GNSRECORD_TYPE_GNS2DNS, | ||
677 | expiration_time, | ||
678 | dst, | ||
679 | off); | ||
680 | gc->found = GNUNET_YES; | ||
681 | } | ||
682 | break; | ||
683 | |||
684 | case GNUNET_DNSPARSER_TYPE_CNAME: | ||
685 | if ((GNUNET_OK == GNUNET_DNSPARSER_builder_add_name (dst, | ||
686 | dst_len, | ||
687 | &off, | ||
688 | gc->req->hostname)) && | ||
689 | (GNUNET_OK == GNUNET_DNSPARSER_builder_add_name (dst, | ||
690 | dst_len, | ||
691 | &off, | ||
692 | rec->data.hostname))) | ||
693 | { | ||
694 | add_record (gc->req, | ||
695 | GNUNET_GNSRECORD_TYPE_GNS2DNS, | ||
696 | expiration_time, | ||
697 | dst, | ||
698 | off); | ||
699 | gc->found = GNUNET_YES; | ||
700 | } | ||
701 | break; | ||
702 | |||
703 | default: | ||
704 | /* useless, do nothing */ | ||
705 | break; | ||
706 | } | ||
707 | } | ||
708 | |||
709 | |||
710 | /** | ||
711 | * Closure for #process_record(). | ||
712 | */ | ||
713 | struct ProcessRecordContext | ||
714 | { | ||
715 | /** | ||
716 | * Answer we got back and are currently parsing, or NULL | ||
717 | * if not active. | ||
718 | */ | ||
719 | struct GNUNET_DNSPARSER_Packet *p; | ||
720 | |||
721 | /** | ||
722 | * Request we are processing. | ||
723 | */ | ||
724 | struct Request *req; | ||
725 | }; | ||
726 | |||
727 | |||
728 | /** | ||
729 | * We received @a rec for @a req. Remember the answer. | ||
730 | * | ||
731 | * @param cls a `struct ProcessRecordContext` | ||
732 | * @param rec response | ||
733 | */ | ||
734 | static void | ||
735 | process_record (void *cls, const struct GNUNET_DNSPARSER_Record *rec) | ||
736 | { | ||
737 | struct ProcessRecordContext *prc = cls; | ||
738 | struct Request *req = prc->req; | ||
739 | char dst[65536]; | ||
740 | size_t dst_len; | ||
741 | size_t off; | ||
742 | struct GNUNET_TIME_Absolute expiration_time; | ||
743 | struct GNUNET_TIME_Relative left; | ||
744 | |||
745 | dst_len = sizeof(dst); | ||
746 | off = 0; | ||
747 | records++; | ||
748 | if (0 != strcasecmp (rec->name, req->hostname)) | ||
749 | { | ||
750 | GNUNET_log ( | ||
751 | GNUNET_ERROR_TYPE_DEBUG, | ||
752 | "DNS returned record from zone `%s' of type %u while resolving `%s'\n", | ||
753 | rec->name, | ||
754 | (unsigned int) rec->type, | ||
755 | req->hostname); | ||
756 | return; /* does not match hostname, might be glue, but | ||
757 | not useful for this pass! */ | ||
758 | } | ||
759 | expiration_time = rec->expiration_time; | ||
760 | left = GNUNET_TIME_absolute_get_remaining (expiration_time); | ||
761 | if (0 == left.rel_value_us) | ||
762 | { | ||
763 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
764 | "DNS returned expired record for `%s'\n", | ||
765 | req->hostname); | ||
766 | GNUNET_STATISTICS_update (stats, | ||
767 | "# expired records obtained from DNS", | ||
768 | 1, | ||
769 | GNUNET_NO); | ||
770 | return; /* record expired */ | ||
771 | } | ||
772 | |||
773 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
774 | "DNS returned record that expires at %s for `%s'\n", | ||
775 | GNUNET_STRINGS_absolute_time_to_string (expiration_time), | ||
776 | req->hostname); | ||
777 | /* if expiration window is too short, bump it to configured minimum */ | ||
778 | if (left.rel_value_us < minimum_expiration_time.rel_value_us) | ||
779 | expiration_time = | ||
780 | GNUNET_TIME_relative_to_absolute (minimum_expiration_time); | ||
781 | switch (rec->type) | ||
782 | { | ||
783 | case GNUNET_DNSPARSER_TYPE_NS: { | ||
784 | struct GlueClosure gc; | ||
785 | |||
786 | /* check for glue */ | ||
787 | gc.req = req; | ||
788 | gc.ns = rec->data.hostname; | ||
789 | gc.found = GNUNET_NO; | ||
790 | for_all_records (prc->p, &check_for_glue, &gc); | ||
791 | if ((GNUNET_NO == gc.found) && | ||
792 | (GNUNET_OK == GNUNET_DNSPARSER_builder_add_name (dst, | ||
793 | dst_len, | ||
794 | &off, | ||
795 | req->hostname)) && | ||
796 | (GNUNET_OK == GNUNET_DNSPARSER_builder_add_name (dst, | ||
797 | dst_len, | ||
798 | &off, | ||
799 | rec->data.hostname))) | ||
800 | { | ||
801 | /* FIXME: actually check if this is out-of-bailiwick, | ||
802 | and if not request explicit resolution... */ | ||
803 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
804 | "Converted OOB (`%s') NS record for `%s'\n", | ||
805 | rec->data.hostname, | ||
806 | rec->name); | ||
807 | add_record (req, | ||
808 | GNUNET_GNSRECORD_TYPE_GNS2DNS, | ||
809 | expiration_time, | ||
810 | dst, | ||
811 | off); | ||
812 | } | ||
813 | else | ||
814 | { | ||
815 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
816 | "Converted NS record for `%s' using glue\n", | ||
817 | rec->name); | ||
818 | } | ||
819 | break; | ||
820 | } | ||
821 | |||
822 | case GNUNET_DNSPARSER_TYPE_CNAME: | ||
823 | if (GNUNET_OK == GNUNET_DNSPARSER_builder_add_name (dst, | ||
824 | dst_len, | ||
825 | &off, | ||
826 | rec->data.hostname)) | ||
827 | { | ||
828 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
829 | "Converting CNAME (`%s') record for `%s'\n", | ||
830 | rec->data.hostname, | ||
831 | rec->name); | ||
832 | add_record (req, rec->type, expiration_time, dst, off); | ||
833 | } | ||
834 | break; | ||
835 | |||
836 | case GNUNET_DNSPARSER_TYPE_DNAME: | ||
837 | /* No support for DNAME in GNS yet! FIXME: support later! */ | ||
838 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, | ||
839 | "FIXME: not supported: %s DNAME %s\n", | ||
840 | rec->name, | ||
841 | rec->data.hostname); | ||
842 | break; | ||
843 | |||
844 | case GNUNET_DNSPARSER_TYPE_MX: | ||
845 | if (GNUNET_OK == | ||
846 | GNUNET_DNSPARSER_builder_add_mx (dst, dst_len, &off, rec->data.mx)) | ||
847 | { | ||
848 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
849 | "Converting MX (`%s') record for `%s'\n", | ||
850 | rec->data.mx->mxhost, | ||
851 | rec->name); | ||
852 | add_record (req, rec->type, expiration_time, dst, off); | ||
853 | } | ||
854 | break; | ||
855 | |||
856 | case GNUNET_DNSPARSER_TYPE_SOA: | ||
857 | if (GNUNET_OK == | ||
858 | GNUNET_DNSPARSER_builder_add_soa (dst, dst_len, &off, rec->data.soa)) | ||
859 | { | ||
860 | /* NOTE: GNS does not really use SOAs */ | ||
861 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
862 | "Converting SOA record for `%s'\n", | ||
863 | rec->name); | ||
864 | add_record (req, rec->type, expiration_time, dst, off); | ||
865 | } | ||
866 | break; | ||
867 | |||
868 | case GNUNET_DNSPARSER_TYPE_SRV: | ||
869 | if (GNUNET_OK == | ||
870 | GNUNET_DNSPARSER_builder_add_srv (dst, dst_len, &off, rec->data.srv)) | ||
871 | { | ||
872 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
873 | "Converting SRV record for `%s'\n", | ||
874 | rec->name); | ||
875 | add_record (req, rec->type, expiration_time, dst, off); | ||
876 | } | ||
877 | break; | ||
878 | |||
879 | case GNUNET_DNSPARSER_TYPE_PTR: | ||
880 | if (GNUNET_OK == GNUNET_DNSPARSER_builder_add_name (dst, | ||
881 | dst_len, | ||
882 | &off, | ||
883 | rec->data.hostname)) | ||
884 | { | ||
885 | /* !?: what does a PTR record do in a regular TLD??? */ | ||
886 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
887 | "Converting PTR record for `%s' (weird)\n", | ||
888 | rec->name); | ||
889 | add_record (req, rec->type, expiration_time, dst, off); | ||
890 | } | ||
891 | break; | ||
892 | |||
893 | case GNUNET_DNSPARSER_TYPE_CERT: | ||
894 | if (GNUNET_OK == | ||
895 | GNUNET_DNSPARSER_builder_add_cert (dst, dst_len, &off, rec->data.cert)) | ||
896 | { | ||
897 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
898 | "Converting CERT record for `%s'\n", | ||
899 | rec->name); | ||
900 | add_record (req, rec->type, expiration_time, dst, off); | ||
901 | } | ||
902 | break; | ||
903 | |||
904 | /* Rest is 'raw' encoded and just needs to be copied IF | ||
905 | the hostname matches the requested name; otherwise we | ||
906 | simply cannot use it. */ | ||
907 | case GNUNET_DNSPARSER_TYPE_A: | ||
908 | case GNUNET_DNSPARSER_TYPE_AAAA: | ||
909 | case GNUNET_DNSPARSER_TYPE_TXT: | ||
910 | default: | ||
911 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
912 | "Converting record of type %u for `%s'\n", | ||
913 | (unsigned int) rec->type, | ||
914 | rec->name); | ||
915 | add_record (req, | ||
916 | rec->type, | ||
917 | expiration_time, | ||
918 | rec->data.raw.data, | ||
919 | rec->data.raw.data_len); | ||
920 | break; | ||
921 | } | ||
922 | } | ||
923 | |||
924 | |||
925 | static void | ||
926 | store_completed_cb (void *cls, enum GNUNET_ErrorCode ec) | ||
927 | { | ||
928 | static struct GNUNET_TIME_Absolute last; | ||
929 | struct Request *req = cls; | ||
930 | |||
931 | req->qe = NULL; | ||
932 | if (GNUNET_EC_NONE != ec) | ||
933 | { | ||
934 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
935 | "Failed to store zone data for `%s': %s\n", | ||
936 | req->hostname, | ||
937 | GNUNET_ErrorCode_get_hint (ec)); | ||
938 | } | ||
939 | else | ||
940 | { | ||
941 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
942 | "Stored records under `%s' (%d)\n", | ||
943 | req->hostname, | ||
944 | ec); | ||
945 | } | ||
946 | total_reg_proc_dns_ns++; /* finished regular processing */ | ||
947 | pending_rs--; | ||
948 | free_records (req); | ||
949 | /* compute NAMESTORE statistics */ | ||
950 | { | ||
951 | static uint64_t total_ns_latency_cnt; | ||
952 | static struct GNUNET_TIME_Relative total_ns_latency; | ||
953 | struct GNUNET_TIME_Relative ns_latency; | ||
954 | |||
955 | ns_latency = GNUNET_TIME_absolute_get_duration (req->op_start_time); | ||
956 | total_ns_latency = GNUNET_TIME_relative_add (total_ns_latency, ns_latency); | ||
957 | if (0 == total_ns_latency_cnt) | ||
958 | last = GNUNET_TIME_absolute_get (); | ||
959 | total_ns_latency_cnt++; | ||
960 | if (0 == (total_ns_latency_cnt % 1000)) | ||
961 | { | ||
962 | struct GNUNET_TIME_Relative delta; | ||
963 | |||
964 | delta = GNUNET_TIME_absolute_get_duration (last); | ||
965 | last = GNUNET_TIME_absolute_get (); | ||
966 | fprintf (stderr, | ||
967 | "Processed 1000 records in %s\n", | ||
968 | GNUNET_STRINGS_relative_time_to_string (delta, GNUNET_YES)); | ||
969 | GNUNET_STATISTICS_set (stats, | ||
970 | "# average NAMESTORE PUT latency (μs)", | ||
971 | total_ns_latency.rel_value_us | ||
972 | / total_ns_latency_cnt, | ||
973 | GNUNET_NO); | ||
974 | } | ||
975 | } | ||
976 | /* compute and publish overall velocity */ | ||
977 | if (0 == (total_reg_proc_dns_ns % 100)) | ||
978 | { | ||
979 | struct GNUNET_TIME_Relative runtime; | ||
980 | |||
981 | runtime = GNUNET_TIME_absolute_get_duration (start_time_reg_proc); | ||
982 | runtime = GNUNET_TIME_relative_subtract (runtime, idle_time); | ||
983 | runtime = | ||
984 | GNUNET_TIME_relative_divide (runtime, | ||
985 | total_reg_proc_dns + total_reg_proc_dns_ns); | ||
986 | GNUNET_STATISTICS_set (stats, | ||
987 | "# Regular processing completed without NAMESTORE", | ||
988 | total_reg_proc_dns, | ||
989 | GNUNET_NO); | ||
990 | GNUNET_STATISTICS_set (stats, | ||
991 | "# Regular processing completed with NAMESTORE PUT", | ||
992 | total_reg_proc_dns_ns, | ||
993 | GNUNET_NO); | ||
994 | GNUNET_STATISTICS_set (stats, | ||
995 | "# average request processing latency (μs)", | ||
996 | runtime.rel_value_us, | ||
997 | GNUNET_NO); | ||
998 | GNUNET_STATISTICS_set (stats, | ||
999 | "# total time spent idle (μs)", | ||
1000 | idle_time.rel_value_us, | ||
1001 | GNUNET_NO); | ||
1002 | } | ||
1003 | |||
1004 | if (NULL == t) | ||
1005 | { | ||
1006 | sleep_time_reg_proc = GNUNET_TIME_absolute_get (); | ||
1007 | t = GNUNET_SCHEDULER_add_now (&process_queue, NULL); | ||
1008 | } | ||
1009 | } | ||
1010 | |||
1011 | |||
1012 | /** | ||
1013 | * Function called with the result of a DNS resolution. | ||
1014 | * | ||
1015 | * @param cls closure with the `struct Request` | ||
1016 | * @param dns dns response, never NULL | ||
1017 | * @param dns_len number of bytes in @a dns | ||
1018 | */ | ||
1019 | static void | ||
1020 | process_result (void *cls, | ||
1021 | const struct GNUNET_TUN_DnsHeader *dns, | ||
1022 | size_t dns_len) | ||
1023 | { | ||
1024 | struct Request *req = cls; | ||
1025 | struct Record *rec; | ||
1026 | struct GNUNET_DNSPARSER_Packet *p; | ||
1027 | unsigned int rd_count; | ||
1028 | |||
1029 | GNUNET_assert (NULL == req->hn); | ||
1030 | if (NULL == dns) | ||
1031 | { | ||
1032 | /* stub gave up */ | ||
1033 | GNUNET_CONTAINER_DLL_remove (req_head, req_tail, req); | ||
1034 | pending--; | ||
1035 | if (NULL == t) | ||
1036 | { | ||
1037 | sleep_time_reg_proc = GNUNET_TIME_absolute_get (); | ||
1038 | t = GNUNET_SCHEDULER_add_now (&process_queue, NULL); | ||
1039 | } | ||
1040 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
1041 | "Stub gave up on DNS reply for `%s'\n", | ||
1042 | req->hostname); | ||
1043 | GNUNET_STATISTICS_update (stats, "# DNS lookups timed out", 1, GNUNET_NO); | ||
1044 | if (req->issue_num > MAX_RETRIES) | ||
1045 | { | ||
1046 | failures++; | ||
1047 | free_request (req); | ||
1048 | GNUNET_STATISTICS_update (stats, "# requests given up on", 1, GNUNET_NO); | ||
1049 | return; | ||
1050 | } | ||
1051 | total_reg_proc_dns++; | ||
1052 | req->rs = NULL; | ||
1053 | insert_sorted (req); | ||
1054 | return; | ||
1055 | } | ||
1056 | if (req->id != dns->id) | ||
1057 | { | ||
1058 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
1059 | "DNS ID did not match request, ignoring reply\n"); | ||
1060 | GNUNET_STATISTICS_update (stats, "# DNS ID mismatches", 1, GNUNET_NO); | ||
1061 | return; | ||
1062 | } | ||
1063 | GNUNET_CONTAINER_DLL_remove (req_head, req_tail, req); | ||
1064 | GNUNET_DNSSTUB_resolve_cancel (req->rs); | ||
1065 | req->rs = NULL; | ||
1066 | pending--; | ||
1067 | p = GNUNET_DNSPARSER_parse ((const char *) dns, dns_len); | ||
1068 | if (NULL == p) | ||
1069 | { | ||
1070 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
1071 | "Failed to parse DNS reply for `%s'\n", | ||
1072 | req->hostname); | ||
1073 | GNUNET_STATISTICS_update (stats, "# DNS parser errors", 1, GNUNET_NO); | ||
1074 | if (NULL == t) | ||
1075 | { | ||
1076 | sleep_time_reg_proc = GNUNET_TIME_absolute_get (); | ||
1077 | t = GNUNET_SCHEDULER_add_now (&process_queue, NULL); | ||
1078 | } | ||
1079 | if (req->issue_num > MAX_RETRIES) | ||
1080 | { | ||
1081 | failures++; | ||
1082 | free_request (req); | ||
1083 | GNUNET_STATISTICS_update (stats, "# requests given up on", 1, GNUNET_NO); | ||
1084 | return; | ||
1085 | } | ||
1086 | insert_sorted (req); | ||
1087 | return; | ||
1088 | } | ||
1089 | /* import new records */ | ||
1090 | req->issue_num = 0; /* success, reset counter! */ | ||
1091 | { | ||
1092 | struct ProcessRecordContext prc = { .req = req, .p = p }; | ||
1093 | |||
1094 | for_all_records (p, &process_record, &prc); | ||
1095 | } | ||
1096 | GNUNET_DNSPARSER_free_packet (p); | ||
1097 | /* count records found, determine minimum expiration time */ | ||
1098 | req->expires = GNUNET_TIME_UNIT_FOREVER_ABS; | ||
1099 | { | ||
1100 | struct GNUNET_TIME_Relative dns_latency; | ||
1101 | |||
1102 | dns_latency = GNUNET_TIME_absolute_get_duration (req->op_start_time); | ||
1103 | total_dns_latency = | ||
1104 | GNUNET_TIME_relative_add (total_dns_latency, dns_latency); | ||
1105 | total_dns_latency_cnt++; | ||
1106 | if (0 == (total_dns_latency_cnt % 1000)) | ||
1107 | { | ||
1108 | GNUNET_STATISTICS_set (stats, | ||
1109 | "# average DNS lookup latency (μs)", | ||
1110 | total_dns_latency.rel_value_us | ||
1111 | / total_dns_latency_cnt, | ||
1112 | GNUNET_NO); | ||
1113 | } | ||
1114 | } | ||
1115 | rd_count = 0; | ||
1116 | for (rec = req->rec_head; NULL != rec; rec = rec->next) | ||
1117 | { | ||
1118 | struct GNUNET_TIME_Absolute at; | ||
1119 | |||
1120 | at.abs_value_us = rec->grd.expiration_time; | ||
1121 | req->expires = GNUNET_TIME_absolute_min (req->expires, at); | ||
1122 | rd_count++; | ||
1123 | } | ||
1124 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, | ||
1125 | "Obtained %u records for `%s'\n", | ||
1126 | rd_count, | ||
1127 | req->hostname); | ||
1128 | /* Instead of going for SOA, simplified for now to look each | ||
1129 | day in case we got an empty response */ | ||
1130 | if (0 == rd_count) | ||
1131 | { | ||
1132 | req->expires = GNUNET_TIME_relative_to_absolute (GNUNET_TIME_UNIT_DAYS); | ||
1133 | GNUNET_STATISTICS_update (stats, | ||
1134 | "# empty DNS replies (usually NXDOMAIN)", | ||
1135 | 1, | ||
1136 | GNUNET_NO); | ||
1137 | } | ||
1138 | else | ||
1139 | { | ||
1140 | record_sets++; | ||
1141 | } | ||
1142 | /* convert records to namestore import format */ | ||
1143 | { | ||
1144 | struct GNUNET_GNSRECORD_Data rd[GNUNET_NZL (rd_count)]; | ||
1145 | unsigned int off = 0; | ||
1146 | |||
1147 | /* convert linked list into array */ | ||
1148 | for (rec = req->rec_head; NULL != rec; rec = rec->next) | ||
1149 | rd[off++] = rec->grd; | ||
1150 | pending_rs++; | ||
1151 | req->op_start_time = GNUNET_TIME_absolute_get (); | ||
1152 | req->qe = GNUNET_NAMESTORE_records_store (ns, | ||
1153 | &req->zone->key, | ||
1154 | get_label (req), | ||
1155 | rd_count, | ||
1156 | rd, | ||
1157 | &store_completed_cb, | ||
1158 | req); | ||
1159 | GNUNET_assert (NULL != req->qe); | ||
1160 | } | ||
1161 | insert_sorted (req); | ||
1162 | } | ||
1163 | |||
1164 | |||
1165 | /** | ||
1166 | * Process as many requests as possible from the queue. | ||
1167 | * | ||
1168 | * @param cls NULL | ||
1169 | */ | ||
1170 | static void | ||
1171 | process_queue (void *cls) | ||
1172 | { | ||
1173 | struct Request *req; | ||
1174 | unsigned int series; | ||
1175 | void *raw; | ||
1176 | size_t raw_size; | ||
1177 | struct GNUNET_TIME_Relative delay; | ||
1178 | |||
1179 | (void) cls; | ||
1180 | delay = GNUNET_TIME_absolute_get_duration (sleep_time_reg_proc); | ||
1181 | idle_time = GNUNET_TIME_relative_add (idle_time, delay); | ||
1182 | series = 0; | ||
1183 | t = NULL; | ||
1184 | while (pending + pending_rs < THRESH) | ||
1185 | { | ||
1186 | req = GNUNET_CONTAINER_heap_peek (req_heap); | ||
1187 | if (NULL == req) | ||
1188 | break; | ||
1189 | if (NULL != req->qe) | ||
1190 | return; /* namestore op still pending */ | ||
1191 | if (NULL != req->rs) | ||
1192 | { | ||
1193 | GNUNET_break (0); | ||
1194 | return; /* already submitted */ | ||
1195 | } | ||
1196 | if (GNUNET_TIME_absolute_get_remaining (req->expires).rel_value_us > 0) | ||
1197 | break; | ||
1198 | GNUNET_assert (req == GNUNET_CONTAINER_heap_remove_root (req_heap)); | ||
1199 | req->hn = NULL; | ||
1200 | GNUNET_CONTAINER_DLL_insert (req_head, req_tail, req); | ||
1201 | GNUNET_assert (NULL == req->rs); | ||
1202 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, | ||
1203 | "Requesting resolution for `%s'\n", | ||
1204 | req->hostname); | ||
1205 | raw = build_dns_query (req, &raw_size); | ||
1206 | if (NULL == raw) | ||
1207 | { | ||
1208 | GNUNET_break (0); | ||
1209 | free_request (req); | ||
1210 | continue; | ||
1211 | } | ||
1212 | req->op_start_time = GNUNET_TIME_absolute_get (); | ||
1213 | req->rs = GNUNET_DNSSTUB_resolve (ctx, raw, raw_size, &process_result, req); | ||
1214 | GNUNET_assert (NULL != req->rs); | ||
1215 | req->issue_num++; | ||
1216 | lookups++; | ||
1217 | pending++; | ||
1218 | series++; | ||
1219 | if (series > MAX_SERIES) | ||
1220 | break; | ||
1221 | } | ||
1222 | if (pending + pending_rs >= THRESH) | ||
1223 | { | ||
1224 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
1225 | "Stopped processing queue (%u+%u/%u)]\n", | ||
1226 | pending, | ||
1227 | pending_rs, | ||
1228 | THRESH); | ||
1229 | return; /* wait for replies */ | ||
1230 | } | ||
1231 | req = GNUNET_CONTAINER_heap_peek (req_heap); | ||
1232 | if (NULL == req) | ||
1233 | { | ||
1234 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
1235 | "Stopped processing queue: empty queue\n"); | ||
1236 | return; | ||
1237 | } | ||
1238 | if (GNUNET_TIME_absolute_get_remaining (req->expires).rel_value_us > 0) | ||
1239 | { | ||
1240 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, | ||
1241 | "Waiting until %s for next record (`%s') to expire\n", | ||
1242 | GNUNET_STRINGS_absolute_time_to_string (req->expires), | ||
1243 | req->hostname); | ||
1244 | if (NULL != t) | ||
1245 | GNUNET_SCHEDULER_cancel (t); | ||
1246 | sleep_time_reg_proc = GNUNET_TIME_absolute_get (); | ||
1247 | t = GNUNET_SCHEDULER_add_at (req->expires, &process_queue, NULL); | ||
1248 | return; | ||
1249 | } | ||
1250 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Throttling\n"); | ||
1251 | if (NULL != t) | ||
1252 | GNUNET_SCHEDULER_cancel (t); | ||
1253 | sleep_time_reg_proc = GNUNET_TIME_absolute_get (); | ||
1254 | t = GNUNET_SCHEDULER_add_delayed (SERIES_DELAY, &process_queue, NULL); | ||
1255 | } | ||
1256 | |||
1257 | |||
1258 | /** | ||
1259 | * Iterator called during #do_shutdown() to free requests in | ||
1260 | * the #ns_pending map. | ||
1261 | * | ||
1262 | * @param cls NULL | ||
1263 | * @param key unused | ||
1264 | * @param value the `struct Request` to free | ||
1265 | * @return #GNUNET_OK | ||
1266 | */ | ||
1267 | static int | ||
1268 | free_request_it (void *cls, const struct GNUNET_HashCode *key, void *value) | ||
1269 | { | ||
1270 | struct Request *req = value; | ||
1271 | |||
1272 | (void) cls; | ||
1273 | (void) key; | ||
1274 | free_request (req); | ||
1275 | return GNUNET_OK; | ||
1276 | } | ||
1277 | |||
1278 | |||
1279 | /** | ||
1280 | * Clean up and terminate the process. | ||
1281 | * | ||
1282 | * @param cls NULL | ||
1283 | */ | ||
1284 | static void | ||
1285 | do_shutdown (void *cls) | ||
1286 | { | ||
1287 | struct Request *req; | ||
1288 | struct Zone *zone; | ||
1289 | |||
1290 | (void) cls; | ||
1291 | if (NULL != id) | ||
1292 | { | ||
1293 | GNUNET_IDENTITY_disconnect (id); | ||
1294 | id = NULL; | ||
1295 | } | ||
1296 | if (NULL != t) | ||
1297 | { | ||
1298 | GNUNET_SCHEDULER_cancel (t); | ||
1299 | t = NULL; | ||
1300 | } | ||
1301 | while (NULL != (req = req_head)) | ||
1302 | { | ||
1303 | GNUNET_CONTAINER_DLL_remove (req_head, req_tail, req); | ||
1304 | if (NULL != req->qe) | ||
1305 | GNUNET_NAMESTORE_cancel (req->qe); | ||
1306 | free_request (req); | ||
1307 | } | ||
1308 | while (NULL != (req = GNUNET_CONTAINER_heap_remove_root (req_heap))) | ||
1309 | { | ||
1310 | req->hn = NULL; | ||
1311 | if (NULL != req->qe) | ||
1312 | GNUNET_NAMESTORE_cancel (req->qe); | ||
1313 | free_request (req); | ||
1314 | } | ||
1315 | if (NULL != zone_it) | ||
1316 | { | ||
1317 | GNUNET_NAMESTORE_zone_iteration_stop (zone_it); | ||
1318 | zone_it = NULL; | ||
1319 | } | ||
1320 | if (NULL != ns) | ||
1321 | { | ||
1322 | GNUNET_NAMESTORE_disconnect (ns); | ||
1323 | ns = NULL; | ||
1324 | } | ||
1325 | if (NULL != ctx) | ||
1326 | { | ||
1327 | GNUNET_DNSSTUB_stop (ctx); | ||
1328 | ctx = NULL; | ||
1329 | } | ||
1330 | if (NULL != req_heap) | ||
1331 | { | ||
1332 | GNUNET_CONTAINER_heap_destroy (req_heap); | ||
1333 | req_heap = NULL; | ||
1334 | } | ||
1335 | if (NULL != ns_pending) | ||
1336 | { | ||
1337 | GNUNET_CONTAINER_multihashmap_iterate (ns_pending, &free_request_it, NULL); | ||
1338 | GNUNET_CONTAINER_multihashmap_destroy (ns_pending); | ||
1339 | ns_pending = NULL; | ||
1340 | } | ||
1341 | while (NULL != (zone = zone_head)) | ||
1342 | { | ||
1343 | GNUNET_CONTAINER_DLL_remove (zone_head, zone_tail, zone); | ||
1344 | GNUNET_free (zone->domain); | ||
1345 | GNUNET_free (zone); | ||
1346 | } | ||
1347 | if (NULL != stats) | ||
1348 | { | ||
1349 | GNUNET_STATISTICS_destroy (stats, GNUNET_NO); | ||
1350 | stats = NULL; | ||
1351 | } | ||
1352 | } | ||
1353 | |||
1354 | |||
1355 | /** | ||
1356 | * Iterate over all of the zones we care about and see which records | ||
1357 | * we may need to re-fetch when. | ||
1358 | * | ||
1359 | * @param cls NULL | ||
1360 | */ | ||
1361 | static void | ||
1362 | iterate_zones (void *cls); | ||
1363 | |||
1364 | |||
1365 | /** | ||
1366 | * Function called if #GNUNET_NAMESTORE_records_lookup() failed. | ||
1367 | * Just logs an error. | ||
1368 | * | ||
1369 | * @param cls a `struct Zone` | ||
1370 | */ | ||
1371 | static void | ||
1372 | ns_lookup_error_cb (void *cls) | ||
1373 | { | ||
1374 | struct Zone *zone = cls; | ||
1375 | |||
1376 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, | ||
1377 | "Failed to load data from namestore for zone `%s'\n", | ||
1378 | zone->domain); | ||
1379 | zone_it = NULL; | ||
1380 | ns_iterator_trigger_next = 0; | ||
1381 | iterate_zones (NULL); | ||
1382 | } | ||
1383 | |||
1384 | |||
1385 | /** | ||
1386 | * Process a record that was stored in the namestore. | ||
1387 | * | ||
1388 | * @param cls a `struct Zone *` | ||
1389 | * @param key private key of the zone | ||
1390 | * @param label label of the records | ||
1391 | * @param rd_count number of entries in @a rd array, 0 if label was deleted | ||
1392 | * @param rd array of records with data to store | ||
1393 | */ | ||
1394 | static void | ||
1395 | ns_lookup_result_cb (void *cls, | ||
1396 | const struct GNUNET_CRYPTO_PrivateKey *key, | ||
1397 | const char *label, | ||
1398 | unsigned int rd_count, | ||
1399 | const struct GNUNET_GNSRECORD_Data *rd) | ||
1400 | { | ||
1401 | struct Zone *zone = cls; | ||
1402 | struct Request *req; | ||
1403 | struct GNUNET_HashCode hc; | ||
1404 | char *fqdn; | ||
1405 | |||
1406 | ns_iterator_trigger_next--; | ||
1407 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
1408 | "Obtained NAMESTORE reply, %llu left in round\n", | ||
1409 | (unsigned long long) ns_iterator_trigger_next); | ||
1410 | if (0 == ns_iterator_trigger_next) | ||
1411 | { | ||
1412 | ns_iterator_trigger_next = NS_BATCH_SIZE; | ||
1413 | GNUNET_STATISTICS_update (stats, | ||
1414 | "# NAMESTORE records requested from cache", | ||
1415 | ns_iterator_trigger_next, | ||
1416 | GNUNET_NO); | ||
1417 | GNUNET_NAMESTORE_zone_iterator_next (zone_it, ns_iterator_trigger_next); | ||
1418 | } | ||
1419 | GNUNET_asprintf (&fqdn, "%s.%s", label, zone->domain); | ||
1420 | GNUNET_CRYPTO_hash (fqdn, strlen (fqdn) + 1, &hc); | ||
1421 | GNUNET_free (fqdn); | ||
1422 | req = GNUNET_CONTAINER_multihashmap_get (ns_pending, &hc); | ||
1423 | if (NULL == req) | ||
1424 | { | ||
1425 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, | ||
1426 | "Ignoring record `%s' in zone `%s': not on my list!\n", | ||
1427 | label, | ||
1428 | zone->domain); | ||
1429 | return; | ||
1430 | } | ||
1431 | GNUNET_assert (GNUNET_OK == | ||
1432 | GNUNET_CONTAINER_multihashmap_remove (ns_pending, &hc, req)); | ||
1433 | GNUNET_break (0 == GNUNET_memcmp (key, &req->zone->key)); | ||
1434 | GNUNET_break (0 == strcasecmp (label, get_label (req))); | ||
1435 | for (unsigned int i = 0; i < rd_count; i++) | ||
1436 | { | ||
1437 | struct GNUNET_TIME_Absolute at; | ||
1438 | |||
1439 | if (0 != (rd->flags & GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION)) | ||
1440 | { | ||
1441 | struct GNUNET_TIME_Relative rel; | ||
1442 | |||
1443 | rel.rel_value_us = rd->expiration_time; | ||
1444 | at = GNUNET_TIME_relative_to_absolute (rel); | ||
1445 | } | ||
1446 | else | ||
1447 | { | ||
1448 | at.abs_value_us = rd->expiration_time; | ||
1449 | } | ||
1450 | add_record (req, rd->record_type, at, rd->data, rd->data_size); | ||
1451 | } | ||
1452 | if (0 == rd_count) | ||
1453 | { | ||
1454 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, | ||
1455 | "Empty record set in namestore for `%s'\n", | ||
1456 | req->hostname); | ||
1457 | } | ||
1458 | else | ||
1459 | { | ||
1460 | unsigned int pos = 0; | ||
1461 | |||
1462 | cached++; | ||
1463 | req->expires = GNUNET_TIME_UNIT_FOREVER_ABS; | ||
1464 | for (struct Record *rec = req->rec_head; NULL != rec; rec = rec->next) | ||
1465 | { | ||
1466 | struct GNUNET_TIME_Absolute at; | ||
1467 | |||
1468 | at.abs_value_us = rec->grd.expiration_time; | ||
1469 | req->expires = GNUNET_TIME_absolute_min (req->expires, at); | ||
1470 | pos++; | ||
1471 | } | ||
1472 | if (0 == pos) | ||
1473 | req->expires = GNUNET_TIME_UNIT_ZERO_ABS; | ||
1474 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, | ||
1475 | "Hot-start with %u existing records for `%s'\n", | ||
1476 | pos, | ||
1477 | req->hostname); | ||
1478 | } | ||
1479 | free_records (req); | ||
1480 | |||
1481 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
1482 | "Adding `%s' to worklist to start at %s\n", | ||
1483 | req->hostname, | ||
1484 | GNUNET_STRINGS_absolute_time_to_string (req->expires)); | ||
1485 | insert_sorted (req); | ||
1486 | } | ||
1487 | |||
1488 | |||
1489 | /** | ||
1490 | * Add @a hostname to the list of requests to be made. | ||
1491 | * | ||
1492 | * @param hostname name to resolve | ||
1493 | */ | ||
1494 | static void | ||
1495 | queue (const char *hostname) | ||
1496 | { | ||
1497 | struct Request *req; | ||
1498 | const char *dot; | ||
1499 | struct Zone *zone; | ||
1500 | size_t hlen; | ||
1501 | struct GNUNET_HashCode hc; | ||
1502 | |||
1503 | if (GNUNET_OK != GNUNET_DNSPARSER_check_name (hostname)) | ||
1504 | { | ||
1505 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
1506 | "Refusing invalid hostname `%s'\n", | ||
1507 | hostname); | ||
1508 | rejects++; | ||
1509 | return; | ||
1510 | } | ||
1511 | dot = strchr (hostname, (unsigned char) '.'); | ||
1512 | if (NULL == dot) | ||
1513 | { | ||
1514 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
1515 | "Refusing invalid hostname `%s' (lacks '.')\n", | ||
1516 | hostname); | ||
1517 | rejects++; | ||
1518 | return; | ||
1519 | } | ||
1520 | for (zone = zone_head; NULL != zone; zone = zone->next) | ||
1521 | if (0 == strcmp (zone->domain, dot + 1)) | ||
1522 | break; | ||
1523 | if (NULL == zone) | ||
1524 | { | ||
1525 | rejects++; | ||
1526 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
1527 | "Domain name `%s' not in ego list!\n", | ||
1528 | dot + 1); | ||
1529 | return; | ||
1530 | } | ||
1531 | |||
1532 | hlen = strlen (hostname) + 1; | ||
1533 | req = GNUNET_malloc (sizeof(struct Request) + hlen); | ||
1534 | req->zone = zone; | ||
1535 | req->hostname = (char *) &req[1]; | ||
1536 | GNUNET_memcpy (req->hostname, hostname, hlen); | ||
1537 | req->id = (uint16_t) GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_NONCE, | ||
1538 | UINT16_MAX); | ||
1539 | GNUNET_CRYPTO_hash (req->hostname, hlen, &hc); | ||
1540 | if (GNUNET_OK != GNUNET_CONTAINER_multihashmap_put ( | ||
1541 | ns_pending, | ||
1542 | &hc, | ||
1543 | req, | ||
1544 | GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY)) | ||
1545 | { | ||
1546 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, | ||
1547 | "Duplicate hostname `%s' ignored\n", | ||
1548 | hostname); | ||
1549 | GNUNET_free (req); | ||
1550 | return; | ||
1551 | } | ||
1552 | } | ||
1553 | |||
1554 | |||
1555 | /** | ||
1556 | * We have completed the initial iteration over the namestore's database. | ||
1557 | * This function is called on each of the remaining records in | ||
1558 | * #move_to_queue to #queue() them, as we will simply not find existing | ||
1559 | * records for them any longer. | ||
1560 | * | ||
1561 | * @param cls NULL | ||
1562 | * @param key unused | ||
1563 | * @param value a `struct Request` | ||
1564 | * @return #GNUNET_OK (continue to iterate) | ||
1565 | */ | ||
1566 | static int | ||
1567 | move_to_queue (void *cls, const struct GNUNET_HashCode *key, void *value) | ||
1568 | { | ||
1569 | struct Request *req = value; | ||
1570 | |||
1571 | (void) cls; | ||
1572 | (void) key; | ||
1573 | insert_sorted (req); | ||
1574 | return GNUNET_OK; | ||
1575 | } | ||
1576 | |||
1577 | |||
1578 | /** | ||
1579 | * Iterate over all of the zones we care about and see which records | ||
1580 | * we may need to re-fetch when. | ||
1581 | * | ||
1582 | * @param cls NULL | ||
1583 | */ | ||
1584 | static void | ||
1585 | iterate_zones (void *cls) | ||
1586 | { | ||
1587 | static struct Zone *last; | ||
1588 | |||
1589 | (void) cls; | ||
1590 | if (NULL != zone_it) | ||
1591 | { | ||
1592 | zone_it = NULL; | ||
1593 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
1594 | "Finished iteration over zone `%s'!\n", | ||
1595 | last->domain); | ||
1596 | /* subtract left-overs from previous iteration */ | ||
1597 | GNUNET_STATISTICS_update (stats, | ||
1598 | "# NAMESTORE records requested from cache", | ||
1599 | (long long) (-ns_iterator_trigger_next), | ||
1600 | GNUNET_NO); | ||
1601 | ns_iterator_trigger_next = 0; | ||
1602 | } | ||
1603 | GNUNET_assert (NULL != zone_tail); | ||
1604 | if (zone_tail == last) | ||
1605 | { | ||
1606 | /* Done iterating over relevant zones in NAMESTORE, move | ||
1607 | rest of hash map to work queue as well. */ | ||
1608 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
1609 | "Finished all NAMESTORE iterations!\n"); | ||
1610 | GNUNET_STATISTICS_set (stats, | ||
1611 | "# Domain names without cached reply", | ||
1612 | GNUNET_CONTAINER_multihashmap_size (ns_pending), | ||
1613 | GNUNET_NO); | ||
1614 | GNUNET_CONTAINER_multihashmap_iterate (ns_pending, &move_to_queue, NULL); | ||
1615 | GNUNET_CONTAINER_multihashmap_destroy (ns_pending); | ||
1616 | ns_pending = NULL; | ||
1617 | start_time_reg_proc = GNUNET_TIME_absolute_get (); | ||
1618 | total_reg_proc_dns = 0; | ||
1619 | total_reg_proc_dns_ns = 0; | ||
1620 | return; | ||
1621 | } | ||
1622 | if (NULL == last) | ||
1623 | last = zone_head; | ||
1624 | else | ||
1625 | last = last->next; | ||
1626 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
1627 | "Starting iteration over zone `%s'!\n", | ||
1628 | last->domain); | ||
1629 | /* subtract left-overs from previous iteration */ | ||
1630 | GNUNET_STATISTICS_update (stats, | ||
1631 | "# NAMESTORE records requested from cache", | ||
1632 | 1, | ||
1633 | GNUNET_NO); | ||
1634 | ns_iterator_trigger_next = 1; | ||
1635 | GNUNET_STATISTICS_update (stats, "# zones iterated", 1, GNUNET_NO); | ||
1636 | zone_it = GNUNET_NAMESTORE_zone_iteration_start (ns, | ||
1637 | &last->key, | ||
1638 | &ns_lookup_error_cb, | ||
1639 | NULL, | ||
1640 | &ns_lookup_result_cb, | ||
1641 | last, | ||
1642 | &iterate_zones, | ||
1643 | NULL); | ||
1644 | } | ||
1645 | |||
1646 | |||
1647 | /** | ||
1648 | * Begin processing hostnames from stdin. | ||
1649 | * | ||
1650 | * @param cls NULL | ||
1651 | */ | ||
1652 | static void | ||
1653 | process_stdin (void *cls) | ||
1654 | { | ||
1655 | static struct GNUNET_TIME_Absolute last; | ||
1656 | static uint64_t idot; | ||
1657 | char hn[256]; | ||
1658 | |||
1659 | (void) cls; | ||
1660 | t = NULL; | ||
1661 | if (NULL != id) | ||
1662 | { | ||
1663 | GNUNET_IDENTITY_disconnect (id); | ||
1664 | id = NULL; | ||
1665 | } | ||
1666 | while (NULL != fgets (hn, sizeof(hn), stdin)) | ||
1667 | { | ||
1668 | if (strlen (hn) > 0) | ||
1669 | hn[strlen (hn) - 1] = '\0'; /* eat newline */ | ||
1670 | if (0 == idot) | ||
1671 | last = GNUNET_TIME_absolute_get (); | ||
1672 | idot++; | ||
1673 | if (0 == idot % 100000) | ||
1674 | { | ||
1675 | struct GNUNET_TIME_Relative delta; | ||
1676 | |||
1677 | delta = GNUNET_TIME_absolute_get_duration (last); | ||
1678 | last = GNUNET_TIME_absolute_get (); | ||
1679 | fprintf (stderr, | ||
1680 | "Read 100000 domain names in %s\n", | ||
1681 | GNUNET_STRINGS_relative_time_to_string (delta, GNUNET_YES)); | ||
1682 | GNUNET_STATISTICS_set (stats, "# domain names provided", idot, GNUNET_NO); | ||
1683 | } | ||
1684 | queue (hn); | ||
1685 | } | ||
1686 | fprintf (stderr, | ||
1687 | "Done reading %llu domain names\n", | ||
1688 | (unsigned long long) idot); | ||
1689 | GNUNET_STATISTICS_set (stats, "# domain names provided", idot, GNUNET_NO); | ||
1690 | iterate_zones (NULL); | ||
1691 | } | ||
1692 | |||
1693 | |||
1694 | /** | ||
1695 | * Method called to inform about the egos of this peer. | ||
1696 | * | ||
1697 | * When used with #GNUNET_IDENTITY_connect, this function is | ||
1698 | * initially called for all egos and then again whenever a | ||
1699 | * ego's name changes or if it is deleted. At the end of | ||
1700 | * the initial pass over all egos, the function is once called | ||
1701 | * with 'NULL' for @a ego. That does NOT mean that the callback won't | ||
1702 | * be invoked in the future or that there was an error. | ||
1703 | * | ||
1704 | * When used with #GNUNET_IDENTITY_create or #GNUNET_IDENTITY_get, this | ||
1705 | * function is only called ONCE, and 'NULL' being passed in @a ego does | ||
1706 | * indicate an error (for example because name is taken or no default value is | ||
1707 | * known). If @a ego is non-NULL and if '*ctx' is set in those callbacks, the | ||
1708 | * value WILL be passed to a subsequent call to the identity callback of | ||
1709 | * #GNUNET_IDENTITY_connect (if that one was not NULL). | ||
1710 | * | ||
1711 | * When an identity is renamed, this function is called with the | ||
1712 | * (known) @a ego but the NEW @a name. | ||
1713 | * | ||
1714 | * When an identity is deleted, this function is called with the | ||
1715 | * (known) ego and "NULL" for the @a name. In this case, | ||
1716 | * the @a ego is henceforth invalid (and the @a ctx should also be | ||
1717 | * cleaned up). | ||
1718 | * | ||
1719 | * @param cls closure | ||
1720 | * @param ego ego handle, NULL for end of list | ||
1721 | * @param ctx context for application to store data for this ego | ||
1722 | * (during the lifetime of this process, initially NULL) | ||
1723 | * @param name name assigned by the user for this ego, | ||
1724 | * NULL if the user just deleted the ego and it | ||
1725 | * must thus no longer be used | ||
1726 | */ | ||
1727 | static void | ||
1728 | identity_cb (void *cls, | ||
1729 | struct GNUNET_IDENTITY_Ego *ego, | ||
1730 | void **ctx, | ||
1731 | const char *name) | ||
1732 | { | ||
1733 | (void) cls; | ||
1734 | (void) ctx; | ||
1735 | |||
1736 | if (NULL == ego) | ||
1737 | { | ||
1738 | /* end of iteration */ | ||
1739 | if (NULL == zone_head) | ||
1740 | { | ||
1741 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "No zone found\n"); | ||
1742 | GNUNET_SCHEDULER_shutdown (); | ||
1743 | return; | ||
1744 | } | ||
1745 | /* zone_head non-null, process hostnames from stdin */ | ||
1746 | t = GNUNET_SCHEDULER_add_now (&process_stdin, NULL); | ||
1747 | return; | ||
1748 | } | ||
1749 | if (NULL != name) | ||
1750 | { | ||
1751 | struct Zone *zone; | ||
1752 | |||
1753 | zone = GNUNET_new (struct Zone); | ||
1754 | zone->key = *GNUNET_IDENTITY_ego_get_private_key (ego); | ||
1755 | zone->domain = GNUNET_strdup (name); | ||
1756 | GNUNET_CONTAINER_DLL_insert (zone_head, zone_tail, zone); | ||
1757 | } | ||
1758 | } | ||
1759 | |||
1760 | |||
1761 | /** | ||
1762 | * Process requests from the queue, then if the queue is | ||
1763 | * not empty, try again. | ||
1764 | * | ||
1765 | * @param cls NULL | ||
1766 | * @param args remaining command-line arguments | ||
1767 | * @param cfgfile name of the configuration file used (for saving, can be NULL!) | ||
1768 | * @param cfg configuration | ||
1769 | */ | ||
1770 | static void | ||
1771 | run (void *cls, | ||
1772 | char *const *args, | ||
1773 | const char *cfgfile, | ||
1774 | const struct GNUNET_CONFIGURATION_Handle *cfg) | ||
1775 | { | ||
1776 | (void) cls; | ||
1777 | (void) args; | ||
1778 | (void) cfgfile; | ||
1779 | stats = GNUNET_STATISTICS_create ("zoneimport", cfg); | ||
1780 | req_heap = GNUNET_CONTAINER_heap_create (GNUNET_CONTAINER_HEAP_ORDER_MIN); | ||
1781 | ns_pending = GNUNET_CONTAINER_multihashmap_create (map_size, GNUNET_NO); | ||
1782 | if (NULL == ns_pending) | ||
1783 | { | ||
1784 | fprintf (stderr, "Failed to allocate memory for main hash map\n"); | ||
1785 | return; | ||
1786 | } | ||
1787 | ctx = GNUNET_DNSSTUB_start (256); | ||
1788 | if (NULL == ctx) | ||
1789 | { | ||
1790 | fprintf (stderr, "Failed to initialize GNUnet DNS STUB\n"); | ||
1791 | return; | ||
1792 | } | ||
1793 | if (NULL == args[0]) | ||
1794 | { | ||
1795 | fprintf (stderr, | ||
1796 | "You must provide a list of DNS resolvers on the command line\n"); | ||
1797 | return; | ||
1798 | } | ||
1799 | for (unsigned int i = 0; NULL != args[i]; i++) | ||
1800 | { | ||
1801 | if (GNUNET_OK != GNUNET_DNSSTUB_add_dns_ip (ctx, args[i])) | ||
1802 | { | ||
1803 | fprintf (stderr, "Failed to use `%s' for DNS resolver\n", args[i]); | ||
1804 | return; | ||
1805 | } | ||
1806 | } | ||
1807 | |||
1808 | |||
1809 | GNUNET_SCHEDULER_add_shutdown (&do_shutdown, NULL); | ||
1810 | ns = GNUNET_NAMESTORE_connect (cfg); | ||
1811 | if (NULL == ns) | ||
1812 | { | ||
1813 | GNUNET_SCHEDULER_shutdown (); | ||
1814 | return; | ||
1815 | } | ||
1816 | id = GNUNET_IDENTITY_connect (cfg, &identity_cb, NULL); | ||
1817 | } | ||
1818 | |||
1819 | |||
1820 | /** | ||
1821 | * Call with IP address of resolver to query. | ||
1822 | * | ||
1823 | * @param argc should be 2 | ||
1824 | * @param argv[1] should contain IP address | ||
1825 | * @return 0 on success | ||
1826 | */ | ||
1827 | int | ||
1828 | main (int argc, char *const *argv) | ||
1829 | { | ||
1830 | struct GNUNET_GETOPT_CommandLineOption options[] = | ||
1831 | { GNUNET_GETOPT_option_uint ('s', | ||
1832 | "size", | ||
1833 | "MAPSIZE", | ||
1834 | gettext_noop ( | ||
1835 | "size to use for the main hash map"), | ||
1836 | &map_size), | ||
1837 | GNUNET_GETOPT_option_relative_time ( | ||
1838 | 'm', | ||
1839 | "minimum-expiration", | ||
1840 | "RELATIVETIME", | ||
1841 | gettext_noop ("minimum expiration time we assume for imported records"), | ||
1842 | &minimum_expiration_time), | ||
1843 | GNUNET_GETOPT_OPTION_END }; | ||
1844 | int ret; | ||
1845 | |||
1846 | if (GNUNET_OK != GNUNET_STRINGS_get_utf8_args (argc, argv, &argc, &argv)) | ||
1847 | return 2; | ||
1848 | if (GNUNET_OK != (ret = GNUNET_PROGRAM_run (argc, | ||
1849 | argv, | ||
1850 | "gnunet-zoneimport", | ||
1851 | "import DNS zone into namestore", | ||
1852 | options, | ||
1853 | &run, | ||
1854 | NULL))) | ||
1855 | return ret; | ||
1856 | GNUNET_free_nz ((void *) argv); | ||
1857 | fprintf (stderr, | ||
1858 | "Rejected %u names, had %u cached, did %u lookups, stored %u record sets\n" | ||
1859 | "Found %u records, %u lookups failed, %u/%u pending on shutdown\n", | ||
1860 | rejects, | ||
1861 | cached, | ||
1862 | lookups, | ||
1863 | record_sets, | ||
1864 | records, | ||
1865 | failures, | ||
1866 | pending, | ||
1867 | pending_rs); | ||
1868 | return 0; | ||
1869 | } | ||
1870 | |||
1871 | |||
1872 | /* end of gnunet-zoneimport.c */ | ||
diff --git a/src/namestore/meson.build b/src/namestore/meson.build deleted file mode 100644 index fd7cfe553..000000000 --- a/src/namestore/meson.build +++ /dev/null | |||
@@ -1,139 +0,0 @@ | |||
1 | libgnunetnamestore_src = ['namestore_api.c', 'namestore_api_monitor.c'] | ||
2 | libgnunetpluginnamestore_sqlite_src = ['plugin_namestore_sqlite.c'] | ||
3 | |||
4 | gnunetnamestore_src = ['gnunet-namestore.c'] | ||
5 | gnunetservicenamestore_src = ['gnunet-service-namestore.c'] | ||
6 | |||
7 | configure_file(input : 'namestore.conf.in', | ||
8 | output : 'namestore.conf', | ||
9 | configuration : cdata, | ||
10 | install: true, | ||
11 | install_dir: pkgcfgdir) | ||
12 | |||
13 | |||
14 | if get_option('monolith') | ||
15 | foreach p : libgnunetnamestore_src + libgnunetpluginnamestore_sqlite_src + gnunetservicenamestore_src | ||
16 | gnunet_src += 'namestore/' + p | ||
17 | endforeach | ||
18 | subdir_done() | ||
19 | endif | ||
20 | |||
21 | libgnunetnamestore = library('gnunetnamestore', | ||
22 | libgnunetnamestore_src, | ||
23 | soversion: '0', | ||
24 | version: '0.0.1', | ||
25 | dependencies: [libgnunetutil_dep, | ||
26 | libgnunetgnsrecord_dep, | ||
27 | libgnunetidentity_dep], | ||
28 | include_directories: [incdir, configuration_inc], | ||
29 | install: true, | ||
30 | install_dir: get_option('libdir')) | ||
31 | libgnunetnamestore_dep = declare_dependency(link_with : libgnunetnamestore) | ||
32 | pkg.generate(libgnunetnamestore, url: 'https://www.gnunet.org', | ||
33 | description : 'Provides API for storing GNS records to a database') | ||
34 | |||
35 | shared_module('gnunet_plugin_rest_namestore', | ||
36 | ['plugin_rest_namestore.c'], | ||
37 | dependencies: [libgnunetrest_dep, | ||
38 | libgnunetidentity_dep, | ||
39 | libgnunetgnsrecordjson_dep, | ||
40 | libgnunetgnsrecord_dep, | ||
41 | libgnunetnamestore_dep, | ||
42 | libgnunetjson_dep, | ||
43 | libgnunetutil_dep, | ||
44 | json_dep, | ||
45 | mhd_dep], | ||
46 | include_directories: [incdir, configuration_inc], | ||
47 | install: true, | ||
48 | install_dir: get_option('libdir') / 'gnunet') | ||
49 | |||
50 | |||
51 | shared_module('gnunet_plugin_namestore_sqlite', | ||
52 | libgnunetpluginnamestore_sqlite_src, | ||
53 | dependencies: [libgnunetutil_dep, | ||
54 | libgnunetgnsrecord_dep, | ||
55 | libgnunetidentity_dep, | ||
56 | libgnunetsq_dep, | ||
57 | libgnunetstatistics_dep, | ||
58 | sqlite_dep], | ||
59 | include_directories: [incdir, configuration_inc], | ||
60 | install: true, | ||
61 | install_dir: get_option('libdir')/'gnunet') | ||
62 | |||
63 | if pq_dep.found() | ||
64 | shared_module('gnunet_plugin_namestore_postgres', | ||
65 | ['plugin_namestore_postgres.c'], | ||
66 | dependencies: [libgnunetutil_dep, | ||
67 | libgnunetgnsrecord_dep, | ||
68 | libgnunetidentity_dep, | ||
69 | libgnunetpq_dep, | ||
70 | libgnunetstatistics_dep, | ||
71 | pq_dep], | ||
72 | include_directories: [incdir, configuration_inc], | ||
73 | install: true, | ||
74 | install_dir: get_option('libdir')/'gnunet') | ||
75 | endif | ||
76 | |||
77 | executable ('gnunet-namestore', | ||
78 | gnunetnamestore_src, | ||
79 | dependencies: [libgnunetnamestore_dep, | ||
80 | libgnunetutil_dep, | ||
81 | libgnunetgnsrecord_dep, | ||
82 | libgnunetidentity_dep], | ||
83 | include_directories: [incdir, configuration_inc], | ||
84 | install: true, | ||
85 | install_dir: get_option('bindir')) | ||
86 | executable ('gnunet-namestore-dbtool', | ||
87 | ['gnunet-namestore-dbtool.c'], | ||
88 | dependencies: [libgnunetnamestore_dep, | ||
89 | libgnunetutil_dep, | ||
90 | libgnunetgnsrecord_dep, | ||
91 | libgnunetidentity_dep], | ||
92 | include_directories: [incdir, configuration_inc], | ||
93 | install: true, | ||
94 | install_dir: get_option('bindir')) | ||
95 | executable ('gnunet-namestore-zonefile', | ||
96 | ['gnunet-namestore-zonefile.c'], | ||
97 | dependencies: [libgnunetnamestore_dep, | ||
98 | libgnunetutil_dep, | ||
99 | libgnunetgnsrecord_dep, | ||
100 | libgnunetidentity_dep], | ||
101 | include_directories: [incdir, configuration_inc], | ||
102 | install: true, | ||
103 | install_dir: get_option('bindir')) | ||
104 | executable ('gnunet-zoneimport', | ||
105 | ['gnunet-zoneimport.c'], | ||
106 | dependencies: [libgnunetnamestore_dep, | ||
107 | libgnunetutil_dep, | ||
108 | libgnunetstatistics_dep, | ||
109 | libgnunetgnsrecord_dep, | ||
110 | libgnunetidentity_dep], | ||
111 | include_directories: [incdir, configuration_inc], | ||
112 | install: true, | ||
113 | install_dir: get_option('bindir')) | ||
114 | executable ('gnunet-service-namestore', | ||
115 | gnunetservicenamestore_src, | ||
116 | dependencies: [libgnunetnamestore_dep, | ||
117 | libgnunetutil_dep, | ||
118 | libgnunetnamecache_dep, | ||
119 | libgnunetgnsrecord_dep, | ||
120 | libgnunetidentity_dep, | ||
121 | libgnunetstatistics_dep], | ||
122 | include_directories: [incdir, configuration_inc], | ||
123 | install: true, | ||
124 | install_dir: get_option('libdir')/'gnunet'/'libexec') | ||
125 | executable ('gnunet-namestore-fcfsd', | ||
126 | ['gnunet-namestore-fcfsd.c'], | ||
127 | dependencies: [libgnunetnamestore_dep, | ||
128 | libgnunetutil_dep, | ||
129 | libgnunetnamecache_dep, | ||
130 | libgnunetgnsrecord_dep, | ||
131 | libgnunetidentity_dep, | ||
132 | mhd_dep, | ||
133 | json_dep, | ||
134 | libgnunetjson_dep, | ||
135 | libgnunetstatistics_dep], | ||
136 | include_directories: [incdir, configuration_inc], | ||
137 | install: true, | ||
138 | install_dir: get_option('libdir')/'gnunet'/'libexec') | ||
139 | |||
diff --git a/src/namestore/namestore-0001.sql b/src/namestore/namestore-0001.sql deleted file mode 100644 index bdfb31976..000000000 --- a/src/namestore/namestore-0001.sql +++ /dev/null | |||
@@ -1,48 +0,0 @@ | |||
1 | -- | ||
2 | -- This file is part of GNUnet | ||
3 | -- Copyright (C) 2014--2022 GNUnet e.V. | ||
4 | -- | ||
5 | -- GNUnet is free software; you can redistribute it and/or modify it under the | ||
6 | -- terms of the GNU General Public License as published by the Free Software | ||
7 | -- Foundation; either version 3, or (at your option) any later version. | ||
8 | -- | ||
9 | -- GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY | ||
10 | -- WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR | ||
11 | -- A PARTICULAR PURPOSE. See the GNU General Public License for more details. | ||
12 | -- | ||
13 | -- You should have received a copy of the GNU General Public License along with | ||
14 | -- GNUnet; see the file COPYING. If not, see <http://www.gnu.org/licenses/> | ||
15 | -- | ||
16 | |||
17 | -- Everything in one big transaction | ||
18 | BEGIN; | ||
19 | |||
20 | -- Check patch versioning is in place. | ||
21 | SELECT _v.register_patch('namestore-0001', NULL, NULL); | ||
22 | |||
23 | -------------------- Schema ---------------------------- | ||
24 | |||
25 | CREATE SCHEMA namestore; | ||
26 | COMMENT ON SCHEMA namestore IS 'gnunet-namestore data'; | ||
27 | |||
28 | SET search_path TO namestore; | ||
29 | |||
30 | CREATE TABLE ns098records ( | ||
31 | seq BIGSERIAL PRIMARY KEY, | ||
32 | zone_private_key BYTEA NOT NULL DEFAULT '', | ||
33 | pkey BYTEA DEFAULT '', | ||
34 | rvalue BYTEA NOT NULL DEFAULT '', | ||
35 | record_count INTEGER NOT NULL DEFAULT 0, | ||
36 | record_data BYTEA NOT NULL DEFAULT '', | ||
37 | label TEXT NOT NULL DEFAULT '', | ||
38 | CONSTRAINT zl UNIQUE (zone_private_key,label)); | ||
39 | |||
40 | CREATE INDEX IF NOT EXISTS ir_pkey_reverse | ||
41 | ON ns098records (zone_private_key,pkey); | ||
42 | CREATE INDEX IF NOT EXISTS ir_pkey_iter | ||
43 | ON ns098records (zone_private_key,seq); | ||
44 | CREATE INDEX IF NOT EXISTS ir_label | ||
45 | ON ns098records (label); | ||
46 | |||
47 | |||
48 | COMMIT; | ||
diff --git a/src/namestore/namestore-drop.sql b/src/namestore/namestore-drop.sql deleted file mode 100644 index 231417af8..000000000 --- a/src/namestore/namestore-drop.sql +++ /dev/null | |||
@@ -1,25 +0,0 @@ | |||
1 | -- | ||
2 | -- This file is part of GNUnet | ||
3 | -- Copyright (C) 2014--2022 GNUnet e.V. | ||
4 | -- | ||
5 | -- GNUnet is free software; you can redistribute it and/or modify it under the | ||
6 | -- terms of the GNU General Public License as published by the Free Software | ||
7 | -- Foundation; either version 3, or (at your option) any later version. | ||
8 | -- | ||
9 | -- GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY | ||
10 | -- WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR | ||
11 | -- A PARTICULAR PURPOSE. See the GNU General Public License for more details. | ||
12 | -- | ||
13 | -- You should have received a copy of the GNU General Public License along with | ||
14 | -- GNUnet; see the file COPYING. If not, see <http://www.gnu.org/licenses/> | ||
15 | -- | ||
16 | |||
17 | -- Everything in one big transaction | ||
18 | BEGIN; | ||
19 | |||
20 | |||
21 | SELECT _v.unregister_patch('namestore-0001'); | ||
22 | |||
23 | DROP SCHEMA namestore CASCADE; | ||
24 | |||
25 | COMMIT; | ||
diff --git a/src/namestore/namestore.conf.in b/src/namestore/namestore.conf.in deleted file mode 100644 index d817f3f95..000000000 --- a/src/namestore/namestore.conf.in +++ /dev/null | |||
@@ -1,47 +0,0 @@ | |||
1 | [namestore] | ||
2 | START_ON_DEMAND = @START_ON_DEMAND@ | ||
3 | RUN_PER_USER = YES | ||
4 | UNIXPATH = $GNUNET_USER_RUNTIME_DIR/gnunet-service-namestore.sock | ||
5 | UNIX_MATCH_UID = NO | ||
6 | UNIX_MATCH_GID = YES | ||
7 | @UNIXONLY@ PORT = 2099 | ||
8 | HOSTNAME = localhost | ||
9 | BINARY = gnunet-service-namestore | ||
10 | ACCEPT_FROM = 127.0.0.1; | ||
11 | ACCEPT_FROM6 = ::1; | ||
12 | |||
13 | # Which database should we use? | ||
14 | DATABASE = 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.) | ||
20 | CACHE_KEYS = YES | ||
21 | |||
22 | |||
23 | [namestore-sqlite] | ||
24 | INIT_ON_CONNECT = YES | ||
25 | FILENAME = $GNUNET_DATA_HOME/namestore/sqlite.db | ||
26 | |||
27 | [namestore-postgres] | ||
28 | # How to connect to the database | ||
29 | CONFIG = postgres:///gnunet | ||
30 | # Use asynchronous commit (SET synchronous_commit TO OFF). | ||
31 | ASYNC_COMMIT = NO | ||
32 | INIT_ON_CONNECT = YES | ||
33 | SQL_DIR = ${DATADIR}/sql/ | ||
34 | |||
35 | [uri] | ||
36 | gns = gnunet-namestore -e 1a -u | ||
37 | |||
38 | |||
39 | [fcfsd] | ||
40 | # Name of the fcfs registration service binary (for ARM) | ||
41 | BINARY = gnunet-namestore-fcfsd | ||
42 | START_ON_DEMAND = NO | ||
43 | UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-service-fcfsd.sock | ||
44 | RELATIVE_RECORD_EXPIRATION = 7 d | ||
45 | |||
46 | # On what port does the FCFS daemon listen for HTTP clients? | ||
47 | HTTPPORT = 18080 | ||
diff --git a/src/namestore/namestore.h b/src/namestore/namestore.h deleted file mode 100644 index 35d54d317..000000000 --- a/src/namestore/namestore.h +++ /dev/null | |||
@@ -1,491 +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 | |||
35 | GNUNET_NETWORK_STRUCT_BEGIN | ||
36 | |||
37 | /** | ||
38 | * Generic namestore message with op id | ||
39 | */ | ||
40 | struct 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 | struct RecordSet | ||
55 | { | ||
56 | /** | ||
57 | * Name length | ||
58 | */ | ||
59 | uint16_t name_len GNUNET_PACKED; | ||
60 | |||
61 | /** | ||
62 | * Length of serialized record data | ||
63 | */ | ||
64 | uint16_t rd_len GNUNET_PACKED; | ||
65 | |||
66 | /** | ||
67 | * Number of records contained | ||
68 | */ | ||
69 | uint16_t rd_count GNUNET_PACKED; | ||
70 | |||
71 | /** | ||
72 | * Reserved for alignment. | ||
73 | */ | ||
74 | uint16_t reserved GNUNET_PACKED; | ||
75 | |||
76 | |||
77 | /* followed by: | ||
78 | * name with length name_len | ||
79 | * serialized record data with rd_count records | ||
80 | */ | ||
81 | }; | ||
82 | |||
83 | /** | ||
84 | * Store a record to the namestore (as authority). | ||
85 | */ | ||
86 | struct RecordStoreMessage | ||
87 | { | ||
88 | /** | ||
89 | * Type will be #GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_STORE | ||
90 | */ | ||
91 | struct GNUNET_NAMESTORE_Header gns_header; | ||
92 | |||
93 | /** | ||
94 | * Number of record sets | ||
95 | */ | ||
96 | uint16_t rd_set_count; | ||
97 | |||
98 | /** | ||
99 | * Length of the zone key | ||
100 | */ | ||
101 | uint16_t key_len GNUNET_PACKED; | ||
102 | |||
103 | /** | ||
104 | * Followed by the private zone key | ||
105 | * Followed by rd_set_count RecordSets | ||
106 | */ | ||
107 | }; | ||
108 | |||
109 | |||
110 | /** | ||
111 | * Response to a record storage request. | ||
112 | */ | ||
113 | struct RecordStoreResponseMessage | ||
114 | { | ||
115 | /** | ||
116 | * Type will be #GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_STORE_RESPONSE | ||
117 | */ | ||
118 | struct GNUNET_NAMESTORE_Header gns_header; | ||
119 | |||
120 | /** | ||
121 | * GNUNET_ErrorCode | ||
122 | */ | ||
123 | uint32_t ec GNUNET_PACKED; | ||
124 | |||
125 | }; | ||
126 | |||
127 | |||
128 | /** | ||
129 | * Lookup a label | ||
130 | */ | ||
131 | struct LabelLookupMessage | ||
132 | { | ||
133 | /** | ||
134 | * Type will be #GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_LOOKUP | ||
135 | */ | ||
136 | struct GNUNET_NAMESTORE_Header gns_header; | ||
137 | |||
138 | /** | ||
139 | * Length of the name | ||
140 | */ | ||
141 | uint16_t label_len GNUNET_PACKED; | ||
142 | |||
143 | /** | ||
144 | * GNUNET_YES if this lookup corresponds to an edit request | ||
145 | */ | ||
146 | uint16_t is_edit_request GNUNET_PACKED; | ||
147 | |||
148 | /** | ||
149 | * The record filter | ||
150 | */ | ||
151 | uint16_t filter; | ||
152 | |||
153 | /** | ||
154 | * Length of the zone key | ||
155 | */ | ||
156 | uint16_t key_len GNUNET_PACKED; | ||
157 | |||
158 | /* followed by: | ||
159 | * the private zone key | ||
160 | * name with length name_len | ||
161 | */ | ||
162 | }; | ||
163 | |||
164 | |||
165 | /** | ||
166 | * Lookup a label | ||
167 | */ | ||
168 | struct LabelLookupResponseMessage | ||
169 | { | ||
170 | /** | ||
171 | * Type will be #GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_LOOKUP_RESPONSE | ||
172 | */ | ||
173 | struct GNUNET_NAMESTORE_Header gns_header; | ||
174 | |||
175 | /** | ||
176 | * Name length | ||
177 | */ | ||
178 | uint16_t name_len GNUNET_PACKED; | ||
179 | |||
180 | /** | ||
181 | * Length of serialized record data | ||
182 | */ | ||
183 | uint16_t rd_len GNUNET_PACKED; | ||
184 | |||
185 | /** | ||
186 | * Number of records contained | ||
187 | */ | ||
188 | uint16_t rd_count GNUNET_PACKED; | ||
189 | |||
190 | /** | ||
191 | * Was the label found in the database?? | ||
192 | * #GNUNET_YES or #GNUNET_NO | ||
193 | */ | ||
194 | int16_t found GNUNET_PACKED; | ||
195 | |||
196 | /** | ||
197 | * Reserved (alignment) | ||
198 | */ | ||
199 | uint16_t reserved GNUNET_PACKED; | ||
200 | |||
201 | /** | ||
202 | * Length of the zone key | ||
203 | */ | ||
204 | uint16_t key_len GNUNET_PACKED; | ||
205 | |||
206 | /* followed by: | ||
207 | * the private zone key | ||
208 | * name with length name_len | ||
209 | * serialized record data with rd_count records | ||
210 | */ | ||
211 | }; | ||
212 | |||
213 | |||
214 | /** | ||
215 | * Lookup a name for a zone hash | ||
216 | */ | ||
217 | struct ZoneToNameMessage | ||
218 | { | ||
219 | /** | ||
220 | * Type will be #GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_TO_NAME | ||
221 | */ | ||
222 | struct GNUNET_NAMESTORE_Header gns_header; | ||
223 | |||
224 | /** | ||
225 | * Length of the zone key | ||
226 | */ | ||
227 | uint16_t key_len GNUNET_PACKED; | ||
228 | |||
229 | /** | ||
230 | * Length of the public value zone key | ||
231 | */ | ||
232 | uint16_t pkey_len GNUNET_PACKED; | ||
233 | |||
234 | /** | ||
235 | * Followed by | ||
236 | * - the private zone key to look up in | ||
237 | * - the public key of the target zone | ||
238 | */ | ||
239 | }; | ||
240 | |||
241 | |||
242 | /** | ||
243 | * Respone for zone to name lookup | ||
244 | */ | ||
245 | struct ZoneToNameResponseMessage | ||
246 | { | ||
247 | /** | ||
248 | * Type will be #GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_TO_NAME_RESPONSE | ||
249 | */ | ||
250 | struct GNUNET_NAMESTORE_Header gns_header; | ||
251 | |||
252 | /** | ||
253 | * result in NBO: #GNUNET_EC_NONE on success, | ||
254 | * #GNUNET_EC_NAMESTORE_NO_RESULTS if there were no | ||
255 | * results. | ||
256 | * Other error messages on error. | ||
257 | */ | ||
258 | int32_t ec GNUNET_PACKED; | ||
259 | |||
260 | /** | ||
261 | * Length of the name | ||
262 | */ | ||
263 | uint16_t name_len GNUNET_PACKED; | ||
264 | |||
265 | /** | ||
266 | * Length of serialized record data | ||
267 | */ | ||
268 | uint16_t rd_len GNUNET_PACKED; | ||
269 | |||
270 | /** | ||
271 | * Number of records contained | ||
272 | */ | ||
273 | uint16_t rd_count GNUNET_PACKED; | ||
274 | |||
275 | /** | ||
276 | * Length of the zone key | ||
277 | */ | ||
278 | uint16_t key_len GNUNET_PACKED; | ||
279 | |||
280 | /* followed by: | ||
281 | * the private zone key | ||
282 | * name with length name_len | ||
283 | * serialized record data with rd_count records | ||
284 | */ | ||
285 | }; | ||
286 | |||
287 | |||
288 | /** | ||
289 | * Record is returned from the namestore (as authority). | ||
290 | */ | ||
291 | struct RecordResultMessage | ||
292 | { | ||
293 | /** | ||
294 | * Type will be #GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_RESULT | ||
295 | */ | ||
296 | struct GNUNET_NAMESTORE_Header gns_header; | ||
297 | |||
298 | /** | ||
299 | * Expiration time if the record result (if any). | ||
300 | * Takes TOMBSTONEs into account. | ||
301 | */ | ||
302 | struct GNUNET_TIME_AbsoluteNBO expire; | ||
303 | |||
304 | /** | ||
305 | * Name length | ||
306 | */ | ||
307 | uint16_t name_len GNUNET_PACKED; | ||
308 | |||
309 | /** | ||
310 | * Length of serialized record data | ||
311 | */ | ||
312 | uint16_t rd_len GNUNET_PACKED; | ||
313 | |||
314 | /** | ||
315 | * Number of records contained | ||
316 | */ | ||
317 | uint16_t rd_count GNUNET_PACKED; | ||
318 | |||
319 | /** | ||
320 | * Length of the zone key | ||
321 | */ | ||
322 | uint16_t key_len GNUNET_PACKED; | ||
323 | |||
324 | /* followed by: | ||
325 | * the private key of the authority | ||
326 | * name with length name_len | ||
327 | * serialized record data with rd_count records | ||
328 | */ | ||
329 | }; | ||
330 | |||
331 | /** | ||
332 | * Send a transaction control message. | ||
333 | */ | ||
334 | struct TxControlMessage | ||
335 | { | ||
336 | /** | ||
337 | * Type will be #GNUNET_MESSAGE_TYPE_NAMESTORE_TX_CONTROL | ||
338 | */ | ||
339 | struct GNUNET_NAMESTORE_Header gns_header; | ||
340 | |||
341 | /** | ||
342 | * always zero (for alignment) | ||
343 | */ | ||
344 | uint16_t reserved GNUNET_PACKED; | ||
345 | |||
346 | /** | ||
347 | * The type of control message to send | ||
348 | */ | ||
349 | uint16_t control GNUNET_PACKED; | ||
350 | |||
351 | }; | ||
352 | |||
353 | /** | ||
354 | * Result of a transaction control message. | ||
355 | */ | ||
356 | struct TxControlResultMessage | ||
357 | { | ||
358 | /** | ||
359 | * Type will be #GNUNET_MESSAGE_TYPE_NAMESTORE_TX_CONTROL_RESULT | ||
360 | */ | ||
361 | struct GNUNET_NAMESTORE_Header gns_header; | ||
362 | |||
363 | /** | ||
364 | * Of type GNUNET_ErrorCode | ||
365 | */ | ||
366 | uint32_t ec GNUNET_PACKED; | ||
367 | |||
368 | }; | ||
369 | |||
370 | |||
371 | |||
372 | /** | ||
373 | * Start monitoring a zone. | ||
374 | */ | ||
375 | struct ZoneMonitorStartMessage | ||
376 | { | ||
377 | /** | ||
378 | * Type will be #GNUNET_MESSAGE_TYPE_NAMESTORE_MONITOR_START | ||
379 | */ | ||
380 | struct GNUNET_MessageHeader header; | ||
381 | |||
382 | /** | ||
383 | * #GNUNET_YES to first iterate over all records, | ||
384 | * #GNUNET_NO to only monitor changes.o | ||
385 | */ | ||
386 | uint32_t iterate_first GNUNET_PACKED; | ||
387 | |||
388 | /** | ||
389 | * Record set filter control flags. | ||
390 | * See GNUNET_NAMESTORE_Filter enum. | ||
391 | */ | ||
392 | uint16_t filter; | ||
393 | |||
394 | /** | ||
395 | * Length of the zone key | ||
396 | */ | ||
397 | uint16_t key_len GNUNET_PACKED; | ||
398 | |||
399 | /** | ||
400 | * Followed by the private zone key. | ||
401 | */ | ||
402 | }; | ||
403 | |||
404 | |||
405 | /** | ||
406 | * Ask for next result of zone iteration for the given operation | ||
407 | */ | ||
408 | struct ZoneMonitorNextMessage | ||
409 | { | ||
410 | /** | ||
411 | * Type will be #GNUNET_MESSAGE_TYPE_NAMESTORE_MONITOR_NEXT | ||
412 | */ | ||
413 | struct GNUNET_MessageHeader header; | ||
414 | |||
415 | /** | ||
416 | * Always zero. | ||
417 | */ | ||
418 | uint32_t reserved; | ||
419 | |||
420 | /** | ||
421 | * Number of records to return to the iterator in one shot | ||
422 | * (before #GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_MONITOR_NEXT | ||
423 | * should be send again). In NBO. | ||
424 | */ | ||
425 | uint64_t limit; | ||
426 | }; | ||
427 | |||
428 | |||
429 | /** | ||
430 | * Start a zone iteration for the given zone | ||
431 | */ | ||
432 | struct ZoneIterationStartMessage | ||
433 | { | ||
434 | /** | ||
435 | * Type will be #GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_ITERATION_START | ||
436 | */ | ||
437 | struct GNUNET_NAMESTORE_Header gns_header; | ||
438 | |||
439 | /** | ||
440 | * Record set filter control flags. | ||
441 | * See GNUNET_NAMESTORE_Filter enum. | ||
442 | */ | ||
443 | uint16_t filter; | ||
444 | |||
445 | /** | ||
446 | * Length of the zone key | ||
447 | */ | ||
448 | uint16_t key_len GNUNET_PACKED; | ||
449 | |||
450 | /** | ||
451 | * Followed by the private zone key (optional) | ||
452 | */ | ||
453 | }; | ||
454 | |||
455 | |||
456 | /** | ||
457 | * Ask for next result of zone iteration for the given operation | ||
458 | */ | ||
459 | struct ZoneIterationNextMessage | ||
460 | { | ||
461 | /** | ||
462 | * Type will be #GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_ITERATION_NEXT | ||
463 | */ | ||
464 | struct GNUNET_NAMESTORE_Header gns_header; | ||
465 | |||
466 | /** | ||
467 | * Number of records to return to the iterator in one shot | ||
468 | * (before #GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_ITERATION_NEXT | ||
469 | * should be send again). In NBO. | ||
470 | */ | ||
471 | uint64_t limit; | ||
472 | }; | ||
473 | |||
474 | |||
475 | /** | ||
476 | * Stop zone iteration for the given operation | ||
477 | */ | ||
478 | struct ZoneIterationStopMessage | ||
479 | { | ||
480 | /** | ||
481 | * Type will be #GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_ITERATION_STOP | ||
482 | */ | ||
483 | struct GNUNET_NAMESTORE_Header gns_header; | ||
484 | }; | ||
485 | |||
486 | |||
487 | GNUNET_NETWORK_STRUCT_END | ||
488 | |||
489 | |||
490 | /* end of namestore.h */ | ||
491 | #endif | ||
diff --git a/src/namestore/namestore_api.c b/src/namestore/namestore_api.c deleted file mode 100644 index 7a4438e30..000000000 --- a/src/namestore/namestore_api.c +++ /dev/null | |||
@@ -1,1563 +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_error_codes.h" | ||
31 | #include "gnunet_util_lib.h" | ||
32 | #include "gnunet_constants.h" | ||
33 | #include "gnunet_arm_service.h" | ||
34 | #include "gnunet_signatures.h" | ||
35 | #include "gnunet_gns_service.h" | ||
36 | #include "gnunet_namestore_service.h" | ||
37 | #include "namestore.h" | ||
38 | |||
39 | |||
40 | #define LOG(kind, ...) GNUNET_log_from (kind, "namestore-api", __VA_ARGS__) | ||
41 | |||
42 | /** | ||
43 | * We grant the namestore up to 1 minute of latency, if it is slower than | ||
44 | * that, store queries will fail. | ||
45 | */ | ||
46 | #define NAMESTORE_DELAY_TOLERANCE GNUNET_TIME_UNIT_MINUTES | ||
47 | |||
48 | /** | ||
49 | * An QueueEntry used to store information for a pending | ||
50 | * NAMESTORE record operation | ||
51 | */ | ||
52 | struct GNUNET_NAMESTORE_QueueEntry | ||
53 | { | ||
54 | /** | ||
55 | * Kept in a DLL. | ||
56 | */ | ||
57 | struct GNUNET_NAMESTORE_QueueEntry *next; | ||
58 | |||
59 | /** | ||
60 | * Kept in a DLL. | ||
61 | */ | ||
62 | struct GNUNET_NAMESTORE_QueueEntry *prev; | ||
63 | |||
64 | /** | ||
65 | * Main handle to access the namestore. | ||
66 | */ | ||
67 | struct GNUNET_NAMESTORE_Handle *h; | ||
68 | |||
69 | /** | ||
70 | * Continuation to call | ||
71 | */ | ||
72 | GNUNET_NAMESTORE_ContinuationWithStatus cont; | ||
73 | |||
74 | /** | ||
75 | * Closure for @e cont. | ||
76 | */ | ||
77 | void *cont_cls; | ||
78 | |||
79 | /** | ||
80 | * Function to call with the records we get back; or NULL. | ||
81 | */ | ||
82 | GNUNET_NAMESTORE_RecordMonitor proc; | ||
83 | |||
84 | /** | ||
85 | * Function to call with the records we get back; or NULL. | ||
86 | */ | ||
87 | GNUNET_NAMESTORE_RecordSetMonitor proc2; | ||
88 | |||
89 | /** | ||
90 | * Closure for @e proc. | ||
91 | */ | ||
92 | void *proc_cls; | ||
93 | |||
94 | /** | ||
95 | * Function to call on errors. | ||
96 | */ | ||
97 | GNUNET_SCHEDULER_TaskCallback error_cb; | ||
98 | |||
99 | /** | ||
100 | * Closure for @e error_cb. | ||
101 | */ | ||
102 | void *error_cb_cls; | ||
103 | |||
104 | /** | ||
105 | * Envelope of the message to send to the service, if not yet | ||
106 | * sent. | ||
107 | */ | ||
108 | struct GNUNET_MQ_Envelope *env; | ||
109 | |||
110 | /** | ||
111 | * Task scheduled to warn us if the namestore is way too slow. | ||
112 | */ | ||
113 | struct GNUNET_SCHEDULER_Task *timeout_task; | ||
114 | |||
115 | /** | ||
116 | * The operation id this zone iteration operation has | ||
117 | */ | ||
118 | uint32_t op_id; | ||
119 | }; | ||
120 | |||
121 | |||
122 | /** | ||
123 | * Handle for a zone iterator operation | ||
124 | */ | ||
125 | struct GNUNET_NAMESTORE_ZoneIterator | ||
126 | { | ||
127 | /** | ||
128 | * Kept in a DLL. | ||
129 | */ | ||
130 | struct GNUNET_NAMESTORE_ZoneIterator *next; | ||
131 | |||
132 | /** | ||
133 | * Kept in a DLL. | ||
134 | */ | ||
135 | struct GNUNET_NAMESTORE_ZoneIterator *prev; | ||
136 | |||
137 | /** | ||
138 | * Main handle to access the namestore. | ||
139 | */ | ||
140 | struct GNUNET_NAMESTORE_Handle *h; | ||
141 | |||
142 | /** | ||
143 | * Function to call on completion. | ||
144 | */ | ||
145 | GNUNET_SCHEDULER_TaskCallback finish_cb; | ||
146 | |||
147 | /** | ||
148 | * Closure for @e error_cb. | ||
149 | */ | ||
150 | void *finish_cb_cls; | ||
151 | |||
152 | /** | ||
153 | * The continuation to call with the results | ||
154 | */ | ||
155 | GNUNET_NAMESTORE_RecordMonitor proc; | ||
156 | |||
157 | /** | ||
158 | * The continuation to call with the results | ||
159 | */ | ||
160 | GNUNET_NAMESTORE_RecordSetMonitor proc2; | ||
161 | |||
162 | /** | ||
163 | * Closure for @e proc. | ||
164 | */ | ||
165 | void *proc_cls; | ||
166 | |||
167 | /** | ||
168 | * Function to call on errors. | ||
169 | */ | ||
170 | GNUNET_SCHEDULER_TaskCallback error_cb; | ||
171 | |||
172 | /** | ||
173 | * Closure for @e error_cb. | ||
174 | */ | ||
175 | void *error_cb_cls; | ||
176 | |||
177 | /** | ||
178 | * Envelope of the message to send to the service, if not yet | ||
179 | * sent. | ||
180 | */ | ||
181 | struct GNUNET_MQ_Envelope *env; | ||
182 | |||
183 | /** | ||
184 | * Private key of the zone. | ||
185 | */ | ||
186 | struct GNUNET_CRYPTO_PrivateKey zone; | ||
187 | |||
188 | /** | ||
189 | * The operation id this zone iteration operation has | ||
190 | */ | ||
191 | uint32_t op_id; | ||
192 | }; | ||
193 | |||
194 | |||
195 | /** | ||
196 | * Connection to the NAMESTORE service. | ||
197 | */ | ||
198 | struct GNUNET_NAMESTORE_Handle | ||
199 | { | ||
200 | /** | ||
201 | * Configuration to use. | ||
202 | */ | ||
203 | const struct GNUNET_CONFIGURATION_Handle *cfg; | ||
204 | |||
205 | /** | ||
206 | * Connection to the service (if available). | ||
207 | */ | ||
208 | struct GNUNET_MQ_Handle *mq; | ||
209 | |||
210 | /** | ||
211 | * Head of pending namestore queue entries | ||
212 | */ | ||
213 | struct GNUNET_NAMESTORE_QueueEntry *op_head; | ||
214 | |||
215 | /** | ||
216 | * Tail of pending namestore queue entries | ||
217 | */ | ||
218 | struct GNUNET_NAMESTORE_QueueEntry *op_tail; | ||
219 | |||
220 | /** | ||
221 | * Head of pending namestore zone iterator entries | ||
222 | */ | ||
223 | struct GNUNET_NAMESTORE_ZoneIterator *z_head; | ||
224 | |||
225 | /** | ||
226 | * Tail of pending namestore zone iterator entries | ||
227 | */ | ||
228 | struct GNUNET_NAMESTORE_ZoneIterator *z_tail; | ||
229 | |||
230 | /** | ||
231 | * Reconnect task | ||
232 | */ | ||
233 | struct GNUNET_SCHEDULER_Task *reconnect_task; | ||
234 | |||
235 | /** | ||
236 | * Delay introduced before we reconnect. | ||
237 | */ | ||
238 | struct GNUNET_TIME_Relative reconnect_delay; | ||
239 | |||
240 | /** | ||
241 | * Should we reconnect to service due to some serious error? | ||
242 | */ | ||
243 | int reconnect; | ||
244 | |||
245 | /** | ||
246 | * The last operation id used for a NAMESTORE operation | ||
247 | */ | ||
248 | uint32_t last_op_id_used; | ||
249 | }; | ||
250 | |||
251 | |||
252 | /** | ||
253 | * Disconnect from service and then reconnect. | ||
254 | * | ||
255 | * @param h our handle | ||
256 | */ | ||
257 | static void | ||
258 | force_reconnect (struct GNUNET_NAMESTORE_Handle *h); | ||
259 | |||
260 | |||
261 | /** | ||
262 | * Find the queue entry that matches the @a rid | ||
263 | * | ||
264 | * @param h namestore handle | ||
265 | * @param rid id to look up | ||
266 | * @return NULL if @a rid was not found | ||
267 | */ | ||
268 | static struct GNUNET_NAMESTORE_QueueEntry * | ||
269 | find_qe (struct GNUNET_NAMESTORE_Handle *h, uint32_t rid) | ||
270 | { | ||
271 | struct GNUNET_NAMESTORE_QueueEntry *qe; | ||
272 | |||
273 | for (qe = h->op_head; qe != NULL; qe = qe->next) | ||
274 | if (qe->op_id == rid) | ||
275 | return qe; | ||
276 | return NULL; | ||
277 | } | ||
278 | |||
279 | |||
280 | /** | ||
281 | * Find the zone iteration entry that matches the @a rid | ||
282 | * | ||
283 | * @param h namestore handle | ||
284 | * @param rid id to look up | ||
285 | * @return NULL if @a rid was not found | ||
286 | */ | ||
287 | static struct GNUNET_NAMESTORE_ZoneIterator * | ||
288 | find_zi (struct GNUNET_NAMESTORE_Handle *h, uint32_t rid) | ||
289 | { | ||
290 | struct GNUNET_NAMESTORE_ZoneIterator *ze; | ||
291 | |||
292 | for (ze = h->z_head; ze != NULL; ze = ze->next) | ||
293 | if (ze->op_id == rid) | ||
294 | return ze; | ||
295 | return NULL; | ||
296 | } | ||
297 | |||
298 | |||
299 | /** | ||
300 | * Free @a qe. | ||
301 | * | ||
302 | * @param qe entry to free | ||
303 | */ | ||
304 | static void | ||
305 | free_qe (struct GNUNET_NAMESTORE_QueueEntry *qe) | ||
306 | { | ||
307 | struct GNUNET_NAMESTORE_Handle *h = qe->h; | ||
308 | |||
309 | GNUNET_CONTAINER_DLL_remove (h->op_head, h->op_tail, qe); | ||
310 | if (NULL != qe->env) | ||
311 | GNUNET_MQ_discard (qe->env); | ||
312 | if (NULL != qe->timeout_task) | ||
313 | GNUNET_SCHEDULER_cancel (qe->timeout_task); | ||
314 | GNUNET_free (qe); | ||
315 | } | ||
316 | |||
317 | |||
318 | /** | ||
319 | * Free @a ze. | ||
320 | * | ||
321 | * @param ze entry to free | ||
322 | */ | ||
323 | static void | ||
324 | free_ze (struct GNUNET_NAMESTORE_ZoneIterator *ze) | ||
325 | { | ||
326 | struct GNUNET_NAMESTORE_Handle *h = ze->h; | ||
327 | |||
328 | GNUNET_CONTAINER_DLL_remove (h->z_head, h->z_tail, ze); | ||
329 | if (NULL != ze->env) | ||
330 | GNUNET_MQ_discard (ze->env); | ||
331 | GNUNET_free (ze); | ||
332 | } | ||
333 | |||
334 | |||
335 | /** | ||
336 | * Check that @a rd_buf of length @a rd_len contains | ||
337 | * @a rd_count records. | ||
338 | * | ||
339 | * @param rd_len length of @a rd_buf | ||
340 | * @param rd_buf buffer with serialized records | ||
341 | * @param rd_count number of records expected | ||
342 | * @return #GNUNET_OK if @a rd_buf is well-formed | ||
343 | */ | ||
344 | static int | ||
345 | check_rd (size_t rd_len, const void *rd_buf, unsigned int rd_count) | ||
346 | { | ||
347 | struct GNUNET_GNSRECORD_Data rd[rd_count]; | ||
348 | |||
349 | if (GNUNET_OK != | ||
350 | GNUNET_GNSRECORD_records_deserialize (rd_len, rd_buf, rd_count, rd)) | ||
351 | { | ||
352 | GNUNET_break (0); | ||
353 | return GNUNET_SYSERR; | ||
354 | } | ||
355 | return GNUNET_OK; | ||
356 | } | ||
357 | |||
358 | /** | ||
359 | * Handle an incoming message of type | ||
360 | * #GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_STORE_RESPONSE | ||
361 | * | ||
362 | * @param cls | ||
363 | * @param msg the message we received | ||
364 | */ | ||
365 | static void | ||
366 | handle_record_store_response (void *cls, | ||
367 | const struct RecordStoreResponseMessage *msg) | ||
368 | { | ||
369 | struct GNUNET_NAMESTORE_Handle *h = cls; | ||
370 | struct GNUNET_NAMESTORE_QueueEntry *qe; | ||
371 | enum GNUNET_ErrorCode res; | ||
372 | |||
373 | qe = find_qe (h, ntohl (msg->gns_header.r_id)); | ||
374 | res = ntohl (msg->ec); | ||
375 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
376 | "Received RECORD_STORE_RESPONSE with result %d\n", | ||
377 | res); | ||
378 | if (NULL == qe) | ||
379 | return; | ||
380 | if (NULL != qe->cont) | ||
381 | qe->cont (qe->cont_cls, res); | ||
382 | free_qe (qe); | ||
383 | } | ||
384 | |||
385 | |||
386 | /** | ||
387 | * Check validity of an incoming message of type | ||
388 | * #GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_LOOKUP_RESPONSE | ||
389 | * | ||
390 | * @param cls | ||
391 | * @param msg the message we received | ||
392 | * @return #GNUNET_OK on success, #GNUNET_SYSERR on error | ||
393 | */ | ||
394 | static int | ||
395 | check_lookup_result (void *cls, const struct LabelLookupResponseMessage *msg) | ||
396 | { | ||
397 | const char *name; | ||
398 | size_t exp_msg_len; | ||
399 | size_t msg_len; | ||
400 | size_t name_len; | ||
401 | size_t rd_len; | ||
402 | size_t key_len; | ||
403 | |||
404 | (void) cls; | ||
405 | rd_len = ntohs (msg->rd_len); | ||
406 | msg_len = ntohs (msg->gns_header.header.size); | ||
407 | name_len = ntohs (msg->name_len); | ||
408 | key_len = ntohs (msg->key_len); | ||
409 | exp_msg_len = sizeof(*msg) + name_len + rd_len + key_len; | ||
410 | if (0 != ntohs (msg->reserved)) | ||
411 | { | ||
412 | GNUNET_break (0); | ||
413 | return GNUNET_SYSERR; | ||
414 | } | ||
415 | if (msg_len != exp_msg_len) | ||
416 | { | ||
417 | GNUNET_break (0); | ||
418 | return GNUNET_SYSERR; | ||
419 | } | ||
420 | name = (const char *) &msg[1] + key_len; | ||
421 | if ((name_len > 0) && ('\0' != name[name_len - 1])) | ||
422 | { | ||
423 | GNUNET_break (0); | ||
424 | return GNUNET_SYSERR; | ||
425 | } | ||
426 | if (GNUNET_NO == ntohs (msg->found)) | ||
427 | { | ||
428 | if (0 != ntohs (msg->rd_count)) | ||
429 | { | ||
430 | GNUNET_break (0); | ||
431 | return GNUNET_SYSERR; | ||
432 | } | ||
433 | return GNUNET_OK; | ||
434 | } | ||
435 | return check_rd (rd_len, &name[name_len], ntohs (msg->rd_count)); | ||
436 | } | ||
437 | |||
438 | |||
439 | /** | ||
440 | * Handle an incoming message of type | ||
441 | * #GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_LOOKUP_RESPONSE | ||
442 | * | ||
443 | * @param cls | ||
444 | * @param msg the message we received | ||
445 | */ | ||
446 | static void | ||
447 | handle_lookup_result (void *cls, const struct LabelLookupResponseMessage *msg) | ||
448 | { | ||
449 | struct GNUNET_NAMESTORE_Handle *h = cls; | ||
450 | struct GNUNET_NAMESTORE_QueueEntry *qe; | ||
451 | struct GNUNET_CRYPTO_PrivateKey private_key; | ||
452 | const char *name; | ||
453 | const char *rd_tmp; | ||
454 | size_t name_len; | ||
455 | size_t rd_len; | ||
456 | size_t key_len; | ||
457 | size_t kbytes_read; | ||
458 | unsigned int rd_count; | ||
459 | int16_t found = (int16_t) ntohs (msg->found); | ||
460 | |||
461 | LOG (GNUNET_ERROR_TYPE_DEBUG, "Received RECORD_LOOKUP_RESULT (found=%i)\n", | ||
462 | found); | ||
463 | qe = find_qe (h, ntohl (msg->gns_header.r_id)); | ||
464 | if (NULL == qe) | ||
465 | return; | ||
466 | rd_len = ntohs (msg->rd_len); | ||
467 | rd_count = ntohs (msg->rd_count); | ||
468 | name_len = ntohs (msg->name_len); | ||
469 | key_len = ntohs (msg->key_len); | ||
470 | GNUNET_assert (GNUNET_SYSERR != | ||
471 | GNUNET_CRYPTO_read_private_key_from_buffer (&msg[1], | ||
472 | key_len, | ||
473 | &private_key, | ||
474 | &kbytes_read)); | ||
475 | GNUNET_assert (kbytes_read == key_len); | ||
476 | name = (const char *) &msg[1] + key_len; | ||
477 | if (GNUNET_NO == found) | ||
478 | { | ||
479 | /* label was not in namestore */ | ||
480 | if (NULL != qe->proc) | ||
481 | qe->proc (qe->proc_cls, &private_key, name, 0, NULL); | ||
482 | free_qe (qe); | ||
483 | return; | ||
484 | } | ||
485 | if (GNUNET_SYSERR == found) | ||
486 | { | ||
487 | if (NULL != qe->error_cb) | ||
488 | qe->error_cb (qe->error_cb_cls); | ||
489 | free_qe (qe); | ||
490 | return; | ||
491 | } | ||
492 | |||
493 | rd_tmp = &name[name_len]; | ||
494 | { | ||
495 | struct GNUNET_GNSRECORD_Data rd[rd_count]; | ||
496 | |||
497 | GNUNET_assert ( | ||
498 | GNUNET_OK == | ||
499 | GNUNET_GNSRECORD_records_deserialize (rd_len, rd_tmp, rd_count, rd)); | ||
500 | if (0 == name_len) | ||
501 | name = NULL; | ||
502 | if (NULL != qe->proc) | ||
503 | qe->proc (qe->proc_cls, | ||
504 | &private_key, | ||
505 | name, | ||
506 | rd_count, | ||
507 | (rd_count > 0) ? rd : NULL); | ||
508 | } | ||
509 | free_qe (qe); | ||
510 | } | ||
511 | |||
512 | |||
513 | /** | ||
514 | * Handle an incoming message of type | ||
515 | * #GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_RESULT | ||
516 | * | ||
517 | * @param cls | ||
518 | * @param msg the message we received | ||
519 | * @return #GNUNET_OK on success, #GNUNET_SYSERR on error | ||
520 | */ | ||
521 | static int | ||
522 | check_record_result (void *cls, const struct RecordResultMessage *msg) | ||
523 | { | ||
524 | const char *name; | ||
525 | size_t msg_len; | ||
526 | size_t name_len; | ||
527 | size_t rd_len; | ||
528 | size_t key_len; | ||
529 | |||
530 | (void) cls; | ||
531 | rd_len = ntohs (msg->rd_len); | ||
532 | msg_len = ntohs (msg->gns_header.header.size); | ||
533 | key_len = ntohs (msg->key_len); | ||
534 | name_len = ntohs (msg->name_len); | ||
535 | if (msg_len != sizeof(struct RecordResultMessage) + key_len + name_len | ||
536 | + rd_len) | ||
537 | { | ||
538 | GNUNET_break (0); | ||
539 | return GNUNET_SYSERR; | ||
540 | } | ||
541 | name = (const char *) &msg[1] + key_len; | ||
542 | if ((0 == name_len) || ('\0' != name[name_len - 1])) | ||
543 | { | ||
544 | GNUNET_break (0); | ||
545 | return GNUNET_SYSERR; | ||
546 | } | ||
547 | if (0 == key_len) | ||
548 | { | ||
549 | GNUNET_break (0); | ||
550 | return GNUNET_SYSERR; | ||
551 | } | ||
552 | return check_rd (rd_len, &name[name_len], ntohs (msg->rd_count)); | ||
553 | } | ||
554 | |||
555 | |||
556 | /** | ||
557 | * Handle an incoming message of type | ||
558 | * #GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_RESULT | ||
559 | * | ||
560 | * @param cls | ||
561 | * @param msg the message we received | ||
562 | */ | ||
563 | static void | ||
564 | handle_record_result (void *cls, const struct RecordResultMessage *msg) | ||
565 | { | ||
566 | struct GNUNET_NAMESTORE_Handle *h = cls; | ||
567 | struct GNUNET_NAMESTORE_QueueEntry *qe; | ||
568 | struct GNUNET_NAMESTORE_ZoneIterator *ze; | ||
569 | struct GNUNET_CRYPTO_PrivateKey private_key; | ||
570 | const char *name; | ||
571 | const char *rd_tmp; | ||
572 | size_t name_len; | ||
573 | size_t rd_len; | ||
574 | size_t key_len; | ||
575 | size_t kbytes_read; | ||
576 | unsigned int rd_count; | ||
577 | |||
578 | LOG (GNUNET_ERROR_TYPE_DEBUG, "Received RECORD_RESULT\n"); | ||
579 | rd_len = ntohs (msg->rd_len); | ||
580 | rd_count = ntohs (msg->rd_count); | ||
581 | name_len = ntohs (msg->name_len); | ||
582 | key_len = ntohs (msg->key_len); | ||
583 | ze = find_zi (h, ntohl (msg->gns_header.r_id)); | ||
584 | qe = find_qe (h, ntohl (msg->gns_header.r_id)); | ||
585 | if ((NULL == ze) && (NULL == qe)) | ||
586 | return; /* rid not found */ | ||
587 | if ((NULL != ze) && (NULL != qe)) | ||
588 | { | ||
589 | GNUNET_break (0); /* rid ambiguous */ | ||
590 | force_reconnect (h); | ||
591 | return; | ||
592 | } | ||
593 | name = (const char *) &msg[1] + key_len; | ||
594 | GNUNET_assert (GNUNET_SYSERR != | ||
595 | GNUNET_CRYPTO_read_private_key_from_buffer (&msg[1], | ||
596 | key_len, | ||
597 | &private_key, | ||
598 | &kbytes_read)); | ||
599 | GNUNET_assert (kbytes_read == key_len); | ||
600 | rd_tmp = &name[name_len]; | ||
601 | { | ||
602 | struct GNUNET_GNSRECORD_Data rd[rd_count]; | ||
603 | |||
604 | GNUNET_assert ( | ||
605 | GNUNET_OK == | ||
606 | GNUNET_GNSRECORD_records_deserialize (rd_len, rd_tmp, rd_count, rd)); | ||
607 | if (0 == name_len) | ||
608 | name = NULL; | ||
609 | if (NULL != qe) | ||
610 | { | ||
611 | if (NULL != qe->proc) | ||
612 | qe->proc (qe->proc_cls, | ||
613 | &private_key, | ||
614 | name, | ||
615 | rd_count, | ||
616 | (rd_count > 0) ? rd : NULL); | ||
617 | free_qe (qe); | ||
618 | return; | ||
619 | } | ||
620 | if (NULL != ze) | ||
621 | { | ||
622 | // Store them here because a callback could free ze | ||
623 | GNUNET_NAMESTORE_RecordMonitor proc; | ||
624 | GNUNET_NAMESTORE_RecordSetMonitor proc2; | ||
625 | void *proc_cls = ze->proc_cls; | ||
626 | proc = ze->proc; | ||
627 | proc2 = ze->proc2; | ||
628 | if (NULL != proc) | ||
629 | proc (proc_cls, &private_key, name, rd_count, rd); | ||
630 | if (NULL != proc2) | ||
631 | proc2 (proc_cls, &private_key, name, | ||
632 | rd_count, rd, GNUNET_TIME_absolute_ntoh (msg->expire)); | ||
633 | return; | ||
634 | } | ||
635 | } | ||
636 | GNUNET_assert (0); | ||
637 | } | ||
638 | |||
639 | |||
640 | /** | ||
641 | * Handle an incoming message of type | ||
642 | * #GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_RESULT_END | ||
643 | * | ||
644 | * @param cls | ||
645 | * @param msg the message we received | ||
646 | */ | ||
647 | static void | ||
648 | handle_record_result_end (void *cls, const struct GNUNET_NAMESTORE_Header *msg) | ||
649 | { | ||
650 | struct GNUNET_NAMESTORE_Handle *h = cls; | ||
651 | struct GNUNET_NAMESTORE_QueueEntry *qe; | ||
652 | struct GNUNET_NAMESTORE_ZoneIterator *ze; | ||
653 | |||
654 | LOG (GNUNET_ERROR_TYPE_DEBUG, "Received RECORD_RESULT_END\n"); | ||
655 | ze = find_zi (h, ntohl (msg->r_id)); | ||
656 | qe = find_qe (h, ntohl (msg->r_id)); | ||
657 | if ((NULL == ze) && (NULL == qe)) | ||
658 | return; /* rid not found */ | ||
659 | if ((NULL != ze) && (NULL != qe)) | ||
660 | { | ||
661 | GNUNET_break (0); /* rid ambiguous */ | ||
662 | force_reconnect (h); | ||
663 | return; | ||
664 | } | ||
665 | LOG (GNUNET_ERROR_TYPE_DEBUG, "Zone iteration completed!\n"); | ||
666 | if (NULL == ze) | ||
667 | { | ||
668 | GNUNET_break (0); | ||
669 | force_reconnect (h); | ||
670 | return; | ||
671 | } | ||
672 | if (NULL != ze->finish_cb) | ||
673 | ze->finish_cb (ze->finish_cb_cls); | ||
674 | free_ze (ze); | ||
675 | } | ||
676 | |||
677 | static void | ||
678 | handle_tx_control_result (void *cls, | ||
679 | const struct TxControlResultMessage *msg) | ||
680 | { | ||
681 | struct GNUNET_NAMESTORE_Handle *h = cls; | ||
682 | struct GNUNET_NAMESTORE_QueueEntry *qe; | ||
683 | enum GNUNET_ErrorCode res; | ||
684 | |||
685 | qe = find_qe (h, ntohl (msg->gns_header.r_id)); | ||
686 | res = ntohs (msg->ec); | ||
687 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
688 | "Received TX_CONTROL_RESULT with result %d\n", | ||
689 | res); | ||
690 | if (NULL == qe) | ||
691 | return; | ||
692 | if (NULL != qe->cont) | ||
693 | qe->cont (qe->cont_cls, res); | ||
694 | free_qe (qe); | ||
695 | } | ||
696 | |||
697 | /** | ||
698 | * Handle an incoming message of type | ||
699 | * #GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_TO_NAME_RESPONSE. | ||
700 | * | ||
701 | * @param qe the respective entry in the message queue | ||
702 | * @param msg the message we received | ||
703 | * @return #GNUNET_OK on success, #GNUNET_SYSERR if message malformed | ||
704 | */ | ||
705 | static int | ||
706 | check_zone_to_name_response (void *cls, | ||
707 | const struct ZoneToNameResponseMessage *msg) | ||
708 | { | ||
709 | size_t name_len; | ||
710 | size_t rd_ser_len; | ||
711 | size_t key_len; | ||
712 | const char *name_tmp; | ||
713 | |||
714 | (void) cls; | ||
715 | if (GNUNET_EC_NONE != ntohl (msg->ec)) | ||
716 | return GNUNET_OK; | ||
717 | key_len = ntohs (msg->key_len); | ||
718 | name_len = ntohs (msg->name_len); | ||
719 | rd_ser_len = ntohs (msg->rd_len); | ||
720 | if (ntohs (msg->gns_header.header.size) != | ||
721 | sizeof(struct ZoneToNameResponseMessage) + key_len + name_len | ||
722 | + rd_ser_len) | ||
723 | { | ||
724 | GNUNET_break (0); | ||
725 | return GNUNET_SYSERR; | ||
726 | } | ||
727 | name_tmp = (const char *) &msg[1] + key_len; | ||
728 | if ((name_len > 0) && ('\0' != name_tmp[name_len - 1])) | ||
729 | { | ||
730 | GNUNET_break (0); | ||
731 | return GNUNET_SYSERR; | ||
732 | } | ||
733 | return check_rd (rd_ser_len, &name_tmp[name_len], ntohs (msg->rd_count)); | ||
734 | } | ||
735 | |||
736 | |||
737 | /** | ||
738 | * Handle an incoming message of type | ||
739 | * #GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_TO_NAME_RESPONSE. | ||
740 | * | ||
741 | * @param cls | ||
742 | * @param msg the message we received | ||
743 | */ | ||
744 | static void | ||
745 | handle_zone_to_name_response (void *cls, | ||
746 | const struct ZoneToNameResponseMessage *msg) | ||
747 | { | ||
748 | struct GNUNET_NAMESTORE_Handle *h = cls; | ||
749 | struct GNUNET_NAMESTORE_QueueEntry *qe; | ||
750 | struct GNUNET_CRYPTO_PrivateKey zone; | ||
751 | enum GNUNET_ErrorCode res; | ||
752 | size_t name_len; | ||
753 | size_t rd_ser_len; | ||
754 | unsigned int rd_count; | ||
755 | const char *name_tmp; | ||
756 | const char *rd_tmp; | ||
757 | size_t key_len; | ||
758 | size_t kbytes_read; | ||
759 | |||
760 | LOG (GNUNET_ERROR_TYPE_DEBUG, "Received ZONE_TO_NAME_RESPONSE\n"); | ||
761 | qe = find_qe (h, ntohl (msg->gns_header.r_id)); | ||
762 | if (NULL == qe) | ||
763 | { | ||
764 | LOG (GNUNET_ERROR_TYPE_WARNING, | ||
765 | "Response queue already gone...\n"); | ||
766 | return; | ||
767 | } | ||
768 | res = ntohl (msg->ec); | ||
769 | key_len = ntohs (msg->key_len); | ||
770 | GNUNET_assert (GNUNET_SYSERR != | ||
771 | GNUNET_CRYPTO_read_private_key_from_buffer (&msg[1], | ||
772 | key_len, | ||
773 | &zone, | ||
774 | &kbytes_read)); | ||
775 | GNUNET_assert (kbytes_read == key_len); | ||
776 | switch (res) | ||
777 | { | ||
778 | break; | ||
779 | |||
780 | case GNUNET_EC_NAMESTORE_NO_RESULTS: | ||
781 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
782 | "Namestore has no result for zone to name mapping \n"); | ||
783 | if (NULL != qe->proc) | ||
784 | qe->proc (qe->proc_cls, &zone, NULL, 0, NULL); | ||
785 | free_qe (qe); | ||
786 | return; | ||
787 | |||
788 | case GNUNET_EC_NONE: | ||
789 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
790 | "Namestore has result for zone to name mapping \n"); | ||
791 | name_len = ntohs (msg->name_len); | ||
792 | rd_count = ntohs (msg->rd_count); | ||
793 | rd_ser_len = ntohs (msg->rd_len); | ||
794 | name_tmp = (const char *) &msg[1] + key_len; | ||
795 | rd_tmp = &name_tmp[name_len]; | ||
796 | { | ||
797 | struct GNUNET_GNSRECORD_Data rd[rd_count]; | ||
798 | |||
799 | GNUNET_assert (GNUNET_OK == | ||
800 | GNUNET_GNSRECORD_records_deserialize (rd_ser_len, | ||
801 | rd_tmp, | ||
802 | rd_count, | ||
803 | rd)); | ||
804 | /* normal end, call continuation with result */ | ||
805 | if (NULL != qe->proc) | ||
806 | qe->proc (qe->proc_cls, &zone, name_tmp, rd_count, rd); | ||
807 | /* return is important here: break would call continuation with error! */ | ||
808 | free_qe (qe); | ||
809 | return; | ||
810 | } | ||
811 | |||
812 | default: | ||
813 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
814 | "An error occurred during zone to name operation: %s\n", | ||
815 | GNUNET_ErrorCode_get_hint (res)); | ||
816 | break; | ||
817 | } | ||
818 | /* error case, call continuation with error */ | ||
819 | if (NULL != qe->error_cb) | ||
820 | qe->error_cb (qe->error_cb_cls); | ||
821 | free_qe (qe); | ||
822 | } | ||
823 | |||
824 | |||
825 | /** | ||
826 | * Generic error handler, called with the appropriate error code and | ||
827 | * the same closure specified at the creation of the message queue. | ||
828 | * Not every message queue implementation supports an error handler. | ||
829 | * | ||
830 | * @param cls closure with the `struct GNUNET_NAMESTORE_Handle *` | ||
831 | * @param error error code | ||
832 | */ | ||
833 | static void | ||
834 | mq_error_handler (void *cls, enum GNUNET_MQ_Error error) | ||
835 | { | ||
836 | struct GNUNET_NAMESTORE_Handle *h = cls; | ||
837 | |||
838 | (void) error; | ||
839 | force_reconnect (h); | ||
840 | } | ||
841 | |||
842 | |||
843 | /** | ||
844 | * Reconnect to namestore service. | ||
845 | * | ||
846 | * @param h the handle to the NAMESTORE service | ||
847 | */ | ||
848 | static void | ||
849 | reconnect (struct GNUNET_NAMESTORE_Handle *h) | ||
850 | { | ||
851 | struct GNUNET_MQ_MessageHandler handlers[] = | ||
852 | { GNUNET_MQ_hd_fixed_size (record_store_response, | ||
853 | GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_STORE_RESPONSE, | ||
854 | struct RecordStoreResponseMessage, | ||
855 | h), | ||
856 | GNUNET_MQ_hd_var_size (zone_to_name_response, | ||
857 | GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_TO_NAME_RESPONSE, | ||
858 | struct ZoneToNameResponseMessage, | ||
859 | h), | ||
860 | GNUNET_MQ_hd_var_size (record_result, | ||
861 | GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_RESULT, | ||
862 | struct RecordResultMessage, | ||
863 | h), | ||
864 | GNUNET_MQ_hd_fixed_size (record_result_end, | ||
865 | GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_RESULT_END, | ||
866 | struct GNUNET_NAMESTORE_Header, | ||
867 | h), | ||
868 | GNUNET_MQ_hd_var_size (lookup_result, | ||
869 | GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_LOOKUP_RESPONSE, | ||
870 | struct LabelLookupResponseMessage, | ||
871 | h), | ||
872 | GNUNET_MQ_hd_fixed_size (tx_control_result, | ||
873 | GNUNET_MESSAGE_TYPE_NAMESTORE_TX_CONTROL_RESULT, | ||
874 | struct TxControlResultMessage, | ||
875 | h), | ||
876 | GNUNET_MQ_handler_end () }; | ||
877 | struct GNUNET_NAMESTORE_ZoneIterator *it; | ||
878 | struct GNUNET_NAMESTORE_QueueEntry *qe; | ||
879 | |||
880 | GNUNET_assert (NULL == h->mq); | ||
881 | h->mq = | ||
882 | GNUNET_CLIENT_connect (h->cfg, "namestore", handlers, &mq_error_handler, h); | ||
883 | if (NULL == h->mq) | ||
884 | return; | ||
885 | /* re-transmit pending requests that waited for a reconnect... */ | ||
886 | for (it = h->z_head; NULL != it; it = it->next) | ||
887 | { | ||
888 | GNUNET_MQ_send (h->mq, it->env); | ||
889 | it->env = NULL; | ||
890 | } | ||
891 | for (qe = h->op_head; NULL != qe; qe = qe->next) | ||
892 | { | ||
893 | GNUNET_MQ_send (h->mq, qe->env); | ||
894 | qe->env = NULL; | ||
895 | } | ||
896 | } | ||
897 | |||
898 | |||
899 | /** | ||
900 | * Re-establish the connection to the service. | ||
901 | * | ||
902 | * @param cls handle to use to re-connect. | ||
903 | */ | ||
904 | static void | ||
905 | reconnect_task (void *cls) | ||
906 | { | ||
907 | struct GNUNET_NAMESTORE_Handle *h = cls; | ||
908 | |||
909 | h->reconnect_task = NULL; | ||
910 | reconnect (h); | ||
911 | } | ||
912 | |||
913 | |||
914 | /** | ||
915 | * Disconnect from service and then reconnect. | ||
916 | * | ||
917 | * @param h our handle | ||
918 | */ | ||
919 | static void | ||
920 | force_reconnect (struct GNUNET_NAMESTORE_Handle *h) | ||
921 | { | ||
922 | struct GNUNET_NAMESTORE_ZoneIterator *ze; | ||
923 | struct GNUNET_NAMESTORE_QueueEntry *qe; | ||
924 | |||
925 | GNUNET_MQ_destroy (h->mq); | ||
926 | h->mq = NULL; | ||
927 | while (NULL != (ze = h->z_head)) | ||
928 | { | ||
929 | if (NULL != ze->error_cb) | ||
930 | ze->error_cb (ze->error_cb_cls); | ||
931 | free_ze (ze); | ||
932 | } | ||
933 | while (NULL != (qe = h->op_head)) | ||
934 | { | ||
935 | if (NULL != qe->error_cb) | ||
936 | qe->error_cb (qe->error_cb_cls); | ||
937 | if (NULL != qe->cont) | ||
938 | qe->cont (qe->cont_cls, | ||
939 | GNUNET_EC_NAMESTORE_UNKNOWN); | ||
940 | free_qe (qe); | ||
941 | } | ||
942 | |||
943 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Reconnecting to namestore\n"); | ||
944 | h->reconnect_delay = GNUNET_TIME_STD_BACKOFF (h->reconnect_delay); | ||
945 | h->reconnect_task = | ||
946 | GNUNET_SCHEDULER_add_delayed (h->reconnect_delay, &reconnect_task, h); | ||
947 | } | ||
948 | |||
949 | |||
950 | /** | ||
951 | * Get a fresh operation id to distinguish between namestore requests | ||
952 | * | ||
953 | * @param h the namestore handle | ||
954 | * @return next operation id to use | ||
955 | */ | ||
956 | static uint32_t | ||
957 | get_op_id (struct GNUNET_NAMESTORE_Handle *h) | ||
958 | { | ||
959 | return h->last_op_id_used++; | ||
960 | } | ||
961 | |||
962 | |||
963 | /** | ||
964 | * Initialize the connection with the NAMESTORE service. | ||
965 | * | ||
966 | * @param cfg configuration to use | ||
967 | * @return handle to the GNS service, or NULL on error | ||
968 | */ | ||
969 | struct GNUNET_NAMESTORE_Handle * | ||
970 | GNUNET_NAMESTORE_connect (const struct GNUNET_CONFIGURATION_Handle *cfg) | ||
971 | { | ||
972 | struct GNUNET_NAMESTORE_Handle *h; | ||
973 | |||
974 | h = GNUNET_new (struct GNUNET_NAMESTORE_Handle); | ||
975 | h->cfg = cfg; | ||
976 | reconnect (h); | ||
977 | if (NULL == h->mq) | ||
978 | { | ||
979 | GNUNET_free (h); | ||
980 | return NULL; | ||
981 | } | ||
982 | return h; | ||
983 | } | ||
984 | |||
985 | |||
986 | /** | ||
987 | * Disconnect from the namestore service (and free associated | ||
988 | * resources). | ||
989 | * | ||
990 | * @param h handle to the namestore | ||
991 | */ | ||
992 | void | ||
993 | GNUNET_NAMESTORE_disconnect (struct GNUNET_NAMESTORE_Handle *h) | ||
994 | { | ||
995 | struct GNUNET_NAMESTORE_QueueEntry *q; | ||
996 | struct GNUNET_NAMESTORE_ZoneIterator *z; | ||
997 | |||
998 | LOG (GNUNET_ERROR_TYPE_DEBUG, "Cleaning up\n"); | ||
999 | GNUNET_break (NULL == h->op_head); | ||
1000 | while (NULL != (q = h->op_head)) | ||
1001 | { | ||
1002 | GNUNET_CONTAINER_DLL_remove (h->op_head, h->op_tail, q); | ||
1003 | GNUNET_free (q); | ||
1004 | } | ||
1005 | GNUNET_break (NULL == h->z_head); | ||
1006 | while (NULL != (z = h->z_head)) | ||
1007 | { | ||
1008 | GNUNET_CONTAINER_DLL_remove (h->z_head, h->z_tail, z); | ||
1009 | GNUNET_free (z); | ||
1010 | } | ||
1011 | if (NULL != h->mq) | ||
1012 | { | ||
1013 | GNUNET_MQ_destroy (h->mq); | ||
1014 | h->mq = NULL; | ||
1015 | } | ||
1016 | if (NULL != h->reconnect_task) | ||
1017 | { | ||
1018 | GNUNET_SCHEDULER_cancel (h->reconnect_task); | ||
1019 | h->reconnect_task = NULL; | ||
1020 | } | ||
1021 | GNUNET_free (h); | ||
1022 | } | ||
1023 | |||
1024 | |||
1025 | /** | ||
1026 | * Task launched to warn the user that the namestore is | ||
1027 | * excessively slow and that a query was thus dropped. | ||
1028 | * | ||
1029 | * @param cls a `struct GNUNET_NAMESTORE_QueueEntry *` | ||
1030 | */ | ||
1031 | static void | ||
1032 | warn_delay (void *cls) | ||
1033 | { | ||
1034 | struct GNUNET_NAMESTORE_QueueEntry *qe = cls; | ||
1035 | |||
1036 | qe->timeout_task = NULL; | ||
1037 | LOG (GNUNET_ERROR_TYPE_WARNING, | ||
1038 | "Did not receive response from namestore after %s!\n", | ||
1039 | GNUNET_STRINGS_relative_time_to_string (NAMESTORE_DELAY_TOLERANCE, | ||
1040 | GNUNET_YES)); | ||
1041 | if (NULL != qe->cont) | ||
1042 | { | ||
1043 | qe->cont (qe->cont_cls, GNUNET_EC_NAMESTORE_UNKNOWN); | ||
1044 | qe->cont = NULL; | ||
1045 | } | ||
1046 | GNUNET_NAMESTORE_cancel (qe); | ||
1047 | } | ||
1048 | |||
1049 | |||
1050 | struct GNUNET_NAMESTORE_QueueEntry * | ||
1051 | GNUNET_NAMESTORE_records_store ( | ||
1052 | struct GNUNET_NAMESTORE_Handle *h, | ||
1053 | const struct GNUNET_CRYPTO_PrivateKey *pkey, | ||
1054 | const char *label, | ||
1055 | unsigned int rd_count, | ||
1056 | const struct GNUNET_GNSRECORD_Data *rd, | ||
1057 | GNUNET_NAMESTORE_ContinuationWithStatus cont, | ||
1058 | void *cont_cls) | ||
1059 | { | ||
1060 | struct GNUNET_NAMESTORE_RecordInfo ri; | ||
1061 | unsigned int rds_sent; | ||
1062 | ri.a_label = label; | ||
1063 | ri.a_rd_count = rd_count; | ||
1064 | ri.a_rd = (struct GNUNET_GNSRECORD_Data *) rd; | ||
1065 | return GNUNET_NAMESTORE_records_store2 (h, pkey, 1, &ri, &rds_sent, | ||
1066 | cont, cont_cls); | ||
1067 | } | ||
1068 | |||
1069 | struct GNUNET_NAMESTORE_QueueEntry * | ||
1070 | GNUNET_NAMESTORE_records_store2 ( | ||
1071 | struct GNUNET_NAMESTORE_Handle *h, | ||
1072 | const struct GNUNET_CRYPTO_PrivateKey *pkey, | ||
1073 | unsigned int rd_set_count, | ||
1074 | const struct GNUNET_NAMESTORE_RecordInfo *record_info, | ||
1075 | unsigned int *rds_sent, | ||
1076 | GNUNET_NAMESTORE_ContinuationWithStatus cont, | ||
1077 | void *cont_cls) | ||
1078 | { | ||
1079 | struct GNUNET_NAMESTORE_QueueEntry *qe; | ||
1080 | struct GNUNET_MQ_Envelope *env; | ||
1081 | const char *label; | ||
1082 | unsigned int rd_count; | ||
1083 | const struct GNUNET_GNSRECORD_Data *rd; | ||
1084 | char *name_tmp; | ||
1085 | char *rd_ser; | ||
1086 | ssize_t rd_ser_len[rd_set_count]; | ||
1087 | size_t name_len; | ||
1088 | uint32_t rid; | ||
1089 | struct RecordStoreMessage *msg; | ||
1090 | struct RecordSet *rd_set; | ||
1091 | ssize_t sret; | ||
1092 | int i; | ||
1093 | size_t rd_set_len = 0; | ||
1094 | size_t key_len = 0; | ||
1095 | size_t max_len; | ||
1096 | key_len = GNUNET_CRYPTO_private_key_get_length (pkey); | ||
1097 | max_len = UINT16_MAX - key_len - sizeof (struct RecordStoreMessage); | ||
1098 | |||
1099 | *rds_sent = 0; | ||
1100 | for (i = 0; i < rd_set_count; i++) | ||
1101 | { | ||
1102 | label = record_info[i].a_label; | ||
1103 | rd_count = record_info[i].a_rd_count; | ||
1104 | rd = record_info[i].a_rd; | ||
1105 | name_len = strlen (label) + 1; | ||
1106 | if (name_len > MAX_NAME_LEN) | ||
1107 | { | ||
1108 | GNUNET_break (0); | ||
1109 | *rds_sent = 0; | ||
1110 | return NULL; | ||
1111 | } | ||
1112 | rd_ser_len[i] = GNUNET_GNSRECORD_records_get_size (rd_count, rd); | ||
1113 | if (rd_ser_len[i] < 0) | ||
1114 | { | ||
1115 | GNUNET_break (0); | ||
1116 | *rds_sent = 0; | ||
1117 | return NULL; | ||
1118 | } | ||
1119 | if (rd_ser_len[i] > max_len) | ||
1120 | { | ||
1121 | GNUNET_break (0); | ||
1122 | *rds_sent = 0; | ||
1123 | return NULL; | ||
1124 | } | ||
1125 | if ((rd_set_len + sizeof (struct RecordSet) + name_len + rd_ser_len[i]) > | ||
1126 | max_len) | ||
1127 | break; | ||
1128 | rd_set_len += sizeof (struct RecordSet) + name_len + rd_ser_len[i]; | ||
1129 | } | ||
1130 | *rds_sent = i; | ||
1131 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
1132 | "Sending %u of %u records!\n", *rds_sent, rd_set_count); | ||
1133 | rid = get_op_id (h); | ||
1134 | qe = GNUNET_new (struct GNUNET_NAMESTORE_QueueEntry); | ||
1135 | qe->h = h; | ||
1136 | qe->cont = cont; | ||
1137 | qe->cont_cls = cont_cls; | ||
1138 | qe->op_id = rid; | ||
1139 | GNUNET_CONTAINER_DLL_insert_tail (h->op_head, h->op_tail, qe); | ||
1140 | /* setup msg */ | ||
1141 | env = GNUNET_MQ_msg_extra (msg, | ||
1142 | key_len + rd_set_len, | ||
1143 | GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_STORE); | ||
1144 | GNUNET_assert (NULL != msg); | ||
1145 | GNUNET_assert (NULL != env); | ||
1146 | msg->gns_header.r_id = htonl (rid); | ||
1147 | msg->key_len = htons (key_len); | ||
1148 | msg->rd_set_count = htons ((uint16_t) (*rds_sent)); | ||
1149 | GNUNET_CRYPTO_write_private_key_to_buffer (pkey, | ||
1150 | &msg[1], | ||
1151 | key_len); | ||
1152 | rd_set = (struct RecordSet*) (((char*) &msg[1]) + key_len); | ||
1153 | for (int i = 0; i < *rds_sent; i++) | ||
1154 | { | ||
1155 | label = record_info[i].a_label; | ||
1156 | rd = record_info[i].a_rd; | ||
1157 | name_len = strlen (label) + 1; | ||
1158 | rd_set->name_len = htons (name_len); | ||
1159 | rd_set->rd_count = htons (record_info[i].a_rd_count); | ||
1160 | rd_set->rd_len = htons (rd_ser_len[i]); | ||
1161 | rd_set->reserved = ntohs (0); | ||
1162 | name_tmp = (char *) &rd_set[1]; | ||
1163 | GNUNET_memcpy (name_tmp, label, name_len); | ||
1164 | rd_ser = &name_tmp[name_len]; | ||
1165 | sret = GNUNET_GNSRECORD_records_serialize (record_info[i].a_rd_count, | ||
1166 | rd, rd_ser_len[i], rd_ser); | ||
1167 | if ((0 > sret) || (sret != rd_ser_len[i])) | ||
1168 | { | ||
1169 | GNUNET_break (0); | ||
1170 | GNUNET_free (env); | ||
1171 | return NULL; | ||
1172 | } | ||
1173 | // Point to next RecordSet | ||
1174 | rd_set = (struct RecordSet*) &name_tmp[name_len + rd_ser_len[i]]; | ||
1175 | } | ||
1176 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1177 | "Sending NAMESTORE_RECORD_STORE message for name %u record sets\n", | ||
1178 | *rds_sent); | ||
1179 | qe->timeout_task = | ||
1180 | GNUNET_SCHEDULER_add_delayed (NAMESTORE_DELAY_TOLERANCE, &warn_delay, qe); | ||
1181 | if (NULL == h->mq) | ||
1182 | { | ||
1183 | qe->env = env; | ||
1184 | LOG (GNUNET_ERROR_TYPE_WARNING, | ||
1185 | "Delaying NAMESTORE_RECORD_STORE message as namestore is not ready!\n"); | ||
1186 | } | ||
1187 | else | ||
1188 | { | ||
1189 | GNUNET_MQ_send (h->mq, env); | ||
1190 | } | ||
1191 | return qe; | ||
1192 | } | ||
1193 | |||
1194 | |||
1195 | static struct GNUNET_NAMESTORE_QueueEntry * | ||
1196 | records_lookup ( | ||
1197 | struct GNUNET_NAMESTORE_Handle *h, | ||
1198 | const struct GNUNET_CRYPTO_PrivateKey *pkey, | ||
1199 | const char *label, | ||
1200 | GNUNET_SCHEDULER_TaskCallback error_cb, | ||
1201 | void *error_cb_cls, | ||
1202 | GNUNET_NAMESTORE_RecordMonitor rm, | ||
1203 | void *rm_cls, | ||
1204 | int is_edit_request, | ||
1205 | enum GNUNET_GNSRECORD_Filter filter) | ||
1206 | { | ||
1207 | struct GNUNET_NAMESTORE_QueueEntry *qe; | ||
1208 | struct GNUNET_MQ_Envelope *env; | ||
1209 | struct LabelLookupMessage *msg; | ||
1210 | size_t label_len; | ||
1211 | size_t key_len; | ||
1212 | |||
1213 | if (1 == (label_len = strlen (label) + 1)) | ||
1214 | { | ||
1215 | GNUNET_break (0); | ||
1216 | return NULL; | ||
1217 | } | ||
1218 | |||
1219 | qe = GNUNET_new (struct GNUNET_NAMESTORE_QueueEntry); | ||
1220 | qe->h = h; | ||
1221 | qe->error_cb = error_cb; | ||
1222 | qe->error_cb_cls = error_cb_cls; | ||
1223 | qe->proc = rm; | ||
1224 | qe->proc_cls = rm_cls; | ||
1225 | qe->op_id = get_op_id (h); | ||
1226 | GNUNET_CONTAINER_DLL_insert_tail (h->op_head, h->op_tail, qe); | ||
1227 | |||
1228 | key_len = GNUNET_CRYPTO_private_key_get_length (pkey); | ||
1229 | env = GNUNET_MQ_msg_extra (msg, | ||
1230 | label_len + key_len, | ||
1231 | GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_LOOKUP); | ||
1232 | msg->gns_header.r_id = htonl (qe->op_id); | ||
1233 | GNUNET_CRYPTO_write_private_key_to_buffer (pkey, | ||
1234 | &msg[1], | ||
1235 | key_len); | ||
1236 | |||
1237 | msg->key_len = htons (key_len); | ||
1238 | msg->is_edit_request = htons (is_edit_request); | ||
1239 | msg->label_len = htons (label_len); | ||
1240 | msg->filter = htons (filter); | ||
1241 | GNUNET_memcpy (((char*) &msg[1]) + key_len, label, label_len); | ||
1242 | if (NULL == h->mq) | ||
1243 | qe->env = env; | ||
1244 | else | ||
1245 | GNUNET_MQ_send (h->mq, env); | ||
1246 | return qe; | ||
1247 | } | ||
1248 | |||
1249 | struct GNUNET_NAMESTORE_QueueEntry * | ||
1250 | GNUNET_NAMESTORE_records_lookup ( | ||
1251 | struct GNUNET_NAMESTORE_Handle *h, | ||
1252 | const struct GNUNET_CRYPTO_PrivateKey *pkey, | ||
1253 | const char *label, | ||
1254 | GNUNET_SCHEDULER_TaskCallback error_cb, | ||
1255 | void *error_cb_cls, | ||
1256 | GNUNET_NAMESTORE_RecordMonitor rm, | ||
1257 | void *rm_cls) | ||
1258 | { | ||
1259 | return records_lookup (h, pkey, label, | ||
1260 | error_cb, error_cb_cls, | ||
1261 | rm, rm_cls, GNUNET_NO, GNUNET_GNSRECORD_FILTER_NONE); | ||
1262 | |||
1263 | } | ||
1264 | |||
1265 | struct GNUNET_NAMESTORE_QueueEntry * | ||
1266 | GNUNET_NAMESTORE_records_lookup2 ( | ||
1267 | struct GNUNET_NAMESTORE_Handle *h, | ||
1268 | const struct GNUNET_CRYPTO_PrivateKey *pkey, | ||
1269 | const char *label, | ||
1270 | GNUNET_SCHEDULER_TaskCallback error_cb, | ||
1271 | void *error_cb_cls, | ||
1272 | GNUNET_NAMESTORE_RecordMonitor rm, | ||
1273 | void *rm_cls, | ||
1274 | enum GNUNET_GNSRECORD_Filter filter) | ||
1275 | { | ||
1276 | return records_lookup (h, pkey, label, | ||
1277 | error_cb, error_cb_cls, | ||
1278 | rm, rm_cls, GNUNET_NO, filter); | ||
1279 | |||
1280 | } | ||
1281 | |||
1282 | |||
1283 | struct GNUNET_NAMESTORE_QueueEntry * | ||
1284 | GNUNET_NAMESTORE_records_edit ( | ||
1285 | struct GNUNET_NAMESTORE_Handle *h, | ||
1286 | const struct GNUNET_CRYPTO_PrivateKey *pkey, | ||
1287 | const char *label, | ||
1288 | GNUNET_SCHEDULER_TaskCallback error_cb, | ||
1289 | void *error_cb_cls, | ||
1290 | GNUNET_NAMESTORE_RecordMonitor rm, | ||
1291 | void *rm_cls) | ||
1292 | { | ||
1293 | return records_lookup (h, pkey, label, | ||
1294 | error_cb, error_cb_cls, | ||
1295 | rm, rm_cls, GNUNET_YES, GNUNET_GNSRECORD_FILTER_NONE); | ||
1296 | } | ||
1297 | |||
1298 | struct GNUNET_NAMESTORE_QueueEntry * | ||
1299 | GNUNET_NAMESTORE_zone_to_name ( | ||
1300 | struct GNUNET_NAMESTORE_Handle *h, | ||
1301 | const struct GNUNET_CRYPTO_PrivateKey *zone, | ||
1302 | const struct GNUNET_CRYPTO_PublicKey *value_zone, | ||
1303 | GNUNET_SCHEDULER_TaskCallback error_cb, | ||
1304 | void *error_cb_cls, | ||
1305 | GNUNET_NAMESTORE_RecordMonitor proc, | ||
1306 | void *proc_cls) | ||
1307 | { | ||
1308 | struct GNUNET_NAMESTORE_QueueEntry *qe; | ||
1309 | struct GNUNET_MQ_Envelope *env; | ||
1310 | struct ZoneToNameMessage *msg; | ||
1311 | uint32_t rid; | ||
1312 | size_t key_len; | ||
1313 | ssize_t pkey_len; | ||
1314 | |||
1315 | rid = get_op_id (h); | ||
1316 | qe = GNUNET_new (struct GNUNET_NAMESTORE_QueueEntry); | ||
1317 | qe->h = h; | ||
1318 | qe->error_cb = error_cb; | ||
1319 | qe->error_cb_cls = error_cb_cls; | ||
1320 | qe->proc = proc; | ||
1321 | qe->proc_cls = proc_cls; | ||
1322 | qe->op_id = rid; | ||
1323 | GNUNET_CONTAINER_DLL_insert_tail (h->op_head, h->op_tail, qe); | ||
1324 | |||
1325 | key_len = GNUNET_CRYPTO_private_key_get_length (zone); | ||
1326 | pkey_len = GNUNET_CRYPTO_public_key_get_length (value_zone); | ||
1327 | env = GNUNET_MQ_msg_extra (msg, key_len + pkey_len, | ||
1328 | GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_TO_NAME); | ||
1329 | msg->gns_header.r_id = htonl (rid); | ||
1330 | msg->key_len = htons (key_len); | ||
1331 | msg->pkey_len = htons (pkey_len); | ||
1332 | GNUNET_CRYPTO_write_private_key_to_buffer (zone, &msg[1], key_len); | ||
1333 | GNUNET_CRYPTO_write_public_key_to_buffer (value_zone, | ||
1334 | (char*) &msg[1] + key_len, | ||
1335 | pkey_len); | ||
1336 | if (NULL == h->mq) | ||
1337 | qe->env = env; | ||
1338 | else | ||
1339 | GNUNET_MQ_send (h->mq, env); | ||
1340 | return qe; | ||
1341 | } | ||
1342 | |||
1343 | |||
1344 | struct GNUNET_NAMESTORE_ZoneIterator * | ||
1345 | GNUNET_NAMESTORE_zone_iteration_start ( | ||
1346 | struct GNUNET_NAMESTORE_Handle *h, | ||
1347 | const struct GNUNET_CRYPTO_PrivateKey *zone, | ||
1348 | GNUNET_SCHEDULER_TaskCallback error_cb, | ||
1349 | void *error_cb_cls, | ||
1350 | GNUNET_NAMESTORE_RecordMonitor proc, | ||
1351 | void *proc_cls, | ||
1352 | GNUNET_SCHEDULER_TaskCallback finish_cb, | ||
1353 | void *finish_cb_cls) | ||
1354 | { | ||
1355 | struct GNUNET_NAMESTORE_ZoneIterator *it; | ||
1356 | struct GNUNET_MQ_Envelope *env; | ||
1357 | struct ZoneIterationStartMessage *msg; | ||
1358 | uint32_t rid; | ||
1359 | size_t key_len = 0; | ||
1360 | |||
1361 | LOG (GNUNET_ERROR_TYPE_DEBUG, "Sending ZONE_ITERATION_START message\n"); | ||
1362 | rid = get_op_id (h); | ||
1363 | it = GNUNET_new (struct GNUNET_NAMESTORE_ZoneIterator); | ||
1364 | it->h = h; | ||
1365 | it->error_cb = error_cb; | ||
1366 | it->error_cb_cls = error_cb_cls; | ||
1367 | it->finish_cb = finish_cb; | ||
1368 | it->finish_cb_cls = finish_cb_cls; | ||
1369 | it->proc = proc; | ||
1370 | it->proc_cls = proc_cls; | ||
1371 | it->op_id = rid; | ||
1372 | if (NULL != zone) | ||
1373 | { | ||
1374 | it->zone = *zone; | ||
1375 | key_len = GNUNET_CRYPTO_private_key_get_length (zone); | ||
1376 | } | ||
1377 | GNUNET_CONTAINER_DLL_insert_tail (h->z_head, h->z_tail, it); | ||
1378 | env = GNUNET_MQ_msg_extra (msg, | ||
1379 | key_len, | ||
1380 | GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_ITERATION_START); | ||
1381 | msg->gns_header.r_id = htonl (rid); | ||
1382 | msg->key_len = htons (key_len); | ||
1383 | if (NULL != zone) | ||
1384 | GNUNET_CRYPTO_write_private_key_to_buffer (zone, &msg[1], key_len); | ||
1385 | if (NULL == h->mq) | ||
1386 | it->env = env; | ||
1387 | else | ||
1388 | GNUNET_MQ_send (h->mq, env); | ||
1389 | return it; | ||
1390 | } | ||
1391 | |||
1392 | struct GNUNET_NAMESTORE_ZoneIterator * | ||
1393 | GNUNET_NAMESTORE_zone_iteration_start2 ( | ||
1394 | struct GNUNET_NAMESTORE_Handle *h, | ||
1395 | const struct GNUNET_CRYPTO_PrivateKey *zone, | ||
1396 | GNUNET_SCHEDULER_TaskCallback error_cb, | ||
1397 | void *error_cb_cls, | ||
1398 | GNUNET_NAMESTORE_RecordSetMonitor proc, | ||
1399 | void *proc_cls, | ||
1400 | GNUNET_SCHEDULER_TaskCallback finish_cb, | ||
1401 | void *finish_cb_cls, | ||
1402 | enum GNUNET_GNSRECORD_Filter filter) | ||
1403 | { | ||
1404 | struct GNUNET_NAMESTORE_ZoneIterator *it; | ||
1405 | struct GNUNET_MQ_Envelope *env; | ||
1406 | struct ZoneIterationStartMessage *msg; | ||
1407 | uint32_t rid; | ||
1408 | size_t key_len = 0; | ||
1409 | |||
1410 | LOG (GNUNET_ERROR_TYPE_DEBUG, "Sending ZONE_ITERATION_START message\n"); | ||
1411 | rid = get_op_id (h); | ||
1412 | it = GNUNET_new (struct GNUNET_NAMESTORE_ZoneIterator); | ||
1413 | it->h = h; | ||
1414 | it->error_cb = error_cb; | ||
1415 | it->error_cb_cls = error_cb_cls; | ||
1416 | it->finish_cb = finish_cb; | ||
1417 | it->finish_cb_cls = finish_cb_cls; | ||
1418 | it->proc2 = proc; | ||
1419 | it->proc_cls = proc_cls; | ||
1420 | it->op_id = rid; | ||
1421 | if (NULL != zone) | ||
1422 | { | ||
1423 | it->zone = *zone; | ||
1424 | key_len = GNUNET_CRYPTO_private_key_get_length (zone); | ||
1425 | } | ||
1426 | GNUNET_CONTAINER_DLL_insert_tail (h->z_head, h->z_tail, it); | ||
1427 | env = GNUNET_MQ_msg_extra (msg, | ||
1428 | key_len, | ||
1429 | GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_ITERATION_START); | ||
1430 | msg->gns_header.r_id = htonl (rid); | ||
1431 | msg->key_len = htons (key_len); | ||
1432 | msg->filter = htons ((uint16_t) filter); | ||
1433 | if (NULL != zone) | ||
1434 | GNUNET_CRYPTO_write_private_key_to_buffer (zone, &msg[1], key_len); | ||
1435 | if (NULL == h->mq) | ||
1436 | it->env = env; | ||
1437 | else | ||
1438 | GNUNET_MQ_send (h->mq, env); | ||
1439 | return it; | ||
1440 | } | ||
1441 | |||
1442 | |||
1443 | void | ||
1444 | GNUNET_NAMESTORE_zone_iterator_next (struct GNUNET_NAMESTORE_ZoneIterator *it, | ||
1445 | uint64_t limit) | ||
1446 | { | ||
1447 | struct GNUNET_NAMESTORE_Handle *h = it->h; | ||
1448 | struct ZoneIterationNextMessage *msg; | ||
1449 | struct GNUNET_MQ_Envelope *env; | ||
1450 | |||
1451 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1452 | "Sending ZONE_ITERATION_NEXT message with limit %llu\n", | ||
1453 | (unsigned long long) limit); | ||
1454 | env = GNUNET_MQ_msg (msg, GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_ITERATION_NEXT); | ||
1455 | msg->gns_header.r_id = htonl (it->op_id); | ||
1456 | msg->limit = GNUNET_htonll (limit); | ||
1457 | GNUNET_MQ_send (h->mq, env); | ||
1458 | } | ||
1459 | |||
1460 | |||
1461 | /** | ||
1462 | * Stops iteration and releases the namestore handle for further calls. | ||
1463 | * | ||
1464 | * @param it the iterator | ||
1465 | */ | ||
1466 | void | ||
1467 | GNUNET_NAMESTORE_zone_iteration_stop (struct GNUNET_NAMESTORE_ZoneIterator *it) | ||
1468 | { | ||
1469 | struct GNUNET_NAMESTORE_Handle *h = it->h; | ||
1470 | struct GNUNET_MQ_Envelope *env; | ||
1471 | struct ZoneIterationStopMessage *msg; | ||
1472 | |||
1473 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending ZONE_ITERATION_STOP message\n"); | ||
1474 | if (NULL != h->mq) | ||
1475 | { | ||
1476 | env = | ||
1477 | GNUNET_MQ_msg (msg, GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_ITERATION_STOP); | ||
1478 | msg->gns_header.r_id = htonl (it->op_id); | ||
1479 | GNUNET_MQ_send (h->mq, env); | ||
1480 | } | ||
1481 | free_ze (it); | ||
1482 | } | ||
1483 | |||
1484 | |||
1485 | /** | ||
1486 | * Cancel a namestore operation. The final callback from the | ||
1487 | * operation must not have been done yet. | ||
1488 | * | ||
1489 | * @param qe operation to cancel | ||
1490 | */ | ||
1491 | void | ||
1492 | GNUNET_NAMESTORE_cancel (struct GNUNET_NAMESTORE_QueueEntry *qe) | ||
1493 | { | ||
1494 | free_qe (qe); | ||
1495 | } | ||
1496 | |||
1497 | /** | ||
1498 | * New API draft. Experimental | ||
1499 | */ | ||
1500 | |||
1501 | static struct GNUNET_NAMESTORE_QueueEntry * | ||
1502 | send_transaction_control_msg (struct GNUNET_NAMESTORE_Handle *h, | ||
1503 | GNUNET_NAMESTORE_ContinuationWithStatus cont, | ||
1504 | void *cont_cls, | ||
1505 | enum GNUNET_NAMESTORE_TxControl ctrl) | ||
1506 | { | ||
1507 | struct GNUNET_NAMESTORE_QueueEntry *qe; | ||
1508 | struct GNUNET_MQ_Envelope *env; | ||
1509 | struct TxControlMessage *msg; | ||
1510 | uint32_t rid; | ||
1511 | |||
1512 | rid = get_op_id (h); | ||
1513 | qe = GNUNET_new (struct GNUNET_NAMESTORE_QueueEntry); | ||
1514 | qe->h = h; | ||
1515 | qe->cont = cont; | ||
1516 | qe->cont_cls = cont_cls; | ||
1517 | qe->op_id = rid; | ||
1518 | GNUNET_CONTAINER_DLL_insert_tail (h->op_head, h->op_tail, qe); | ||
1519 | |||
1520 | env = GNUNET_MQ_msg (msg, GNUNET_MESSAGE_TYPE_NAMESTORE_TX_CONTROL); | ||
1521 | msg->gns_header.r_id = htonl (rid); | ||
1522 | msg->control = htons (ctrl); | ||
1523 | if (NULL == h->mq) | ||
1524 | qe->env = env; | ||
1525 | else | ||
1526 | GNUNET_MQ_send (h->mq, env); | ||
1527 | return qe; | ||
1528 | GNUNET_break (0); | ||
1529 | return NULL; | ||
1530 | } | ||
1531 | |||
1532 | struct GNUNET_NAMESTORE_QueueEntry * | ||
1533 | GNUNET_NAMESTORE_transaction_begin (struct GNUNET_NAMESTORE_Handle *h, | ||
1534 | GNUNET_NAMESTORE_ContinuationWithStatus cont, | ||
1535 | void *cont_cls) | ||
1536 | { | ||
1537 | return send_transaction_control_msg (h, cont, cont_cls, | ||
1538 | GNUNET_NAMESTORE_TX_BEGIN); | ||
1539 | } | ||
1540 | |||
1541 | struct GNUNET_NAMESTORE_QueueEntry * | ||
1542 | GNUNET_NAMESTORE_transaction_commit (struct GNUNET_NAMESTORE_Handle *h, | ||
1543 | GNUNET_NAMESTORE_ContinuationWithStatus | ||
1544 | cont, | ||
1545 | void *cont_cls) | ||
1546 | { | ||
1547 | return send_transaction_control_msg (h, cont, cont_cls, | ||
1548 | GNUNET_NAMESTORE_TX_COMMIT); | ||
1549 | } | ||
1550 | |||
1551 | |||
1552 | struct GNUNET_NAMESTORE_QueueEntry * | ||
1553 | GNUNET_NAMESTORE_transaction_rollback (struct GNUNET_NAMESTORE_Handle *h, | ||
1554 | GNUNET_NAMESTORE_ContinuationWithStatus | ||
1555 | cont, | ||
1556 | void *cont_cls) | ||
1557 | { | ||
1558 | return send_transaction_control_msg (h, cont, cont_cls, | ||
1559 | GNUNET_NAMESTORE_TX_ROLLBACK); | ||
1560 | } | ||
1561 | |||
1562 | |||
1563 | /* 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 ec4ba879b..000000000 --- a/src/namestore/namestore_api_monitor.c +++ /dev/null | |||
@@ -1,443 +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_constants.h" | ||
29 | #include "gnunet_arm_service.h" | ||
30 | #include "gnunet_signatures.h" | ||
31 | #include "gnunet_namestore_service.h" | ||
32 | #include "namestore.h" | ||
33 | |||
34 | |||
35 | /** | ||
36 | * Handle for a monitoring activity. | ||
37 | */ | ||
38 | struct GNUNET_NAMESTORE_ZoneMonitor | ||
39 | { | ||
40 | /** | ||
41 | * Configuration (to reconnect). | ||
42 | */ | ||
43 | const struct GNUNET_CONFIGURATION_Handle *cfg; | ||
44 | |||
45 | /** | ||
46 | * Handle to namestore service. | ||
47 | */ | ||
48 | struct GNUNET_MQ_Handle *mq; | ||
49 | |||
50 | /** | ||
51 | * Function to call on errors. | ||
52 | */ | ||
53 | GNUNET_SCHEDULER_TaskCallback error_cb; | ||
54 | |||
55 | /** | ||
56 | * Closure for @e error_cb. | ||
57 | */ | ||
58 | void *error_cb_cls; | ||
59 | |||
60 | /** | ||
61 | * Function to call on events. | ||
62 | */ | ||
63 | GNUNET_NAMESTORE_RecordMonitor monitor; | ||
64 | |||
65 | /** | ||
66 | * Function to call on events. | ||
67 | */ | ||
68 | GNUNET_NAMESTORE_RecordSetMonitor monitor2; | ||
69 | |||
70 | /** | ||
71 | * Record set filter for this monitor | ||
72 | */ | ||
73 | enum GNUNET_GNSRECORD_Filter filter; | ||
74 | |||
75 | /** | ||
76 | * Closure for @e monitor. | ||
77 | */ | ||
78 | void *monitor_cls; | ||
79 | |||
80 | /** | ||
81 | * Function called when we've synchronized. | ||
82 | */ | ||
83 | GNUNET_SCHEDULER_TaskCallback sync_cb; | ||
84 | |||
85 | /** | ||
86 | * Closure for @e sync_cb. | ||
87 | */ | ||
88 | void *sync_cb_cls; | ||
89 | |||
90 | /** | ||
91 | * Monitored zone. | ||
92 | */ | ||
93 | struct GNUNET_CRYPTO_PrivateKey zone; | ||
94 | |||
95 | /** | ||
96 | * Do we first iterate over all existing records? | ||
97 | */ | ||
98 | int iterate_first; | ||
99 | |||
100 | /** | ||
101 | * Zone key length | ||
102 | */ | ||
103 | uint32_t key_len; | ||
104 | }; | ||
105 | |||
106 | |||
107 | /** | ||
108 | * Reconnect to the namestore service. | ||
109 | * | ||
110 | * @param zm monitor to reconnect | ||
111 | */ | ||
112 | static void | ||
113 | reconnect (struct GNUNET_NAMESTORE_ZoneMonitor *zm); | ||
114 | |||
115 | |||
116 | /** | ||
117 | * Handle SYNC message from the namestore service. | ||
118 | * | ||
119 | * @param cls the monitor | ||
120 | * @param msg the sync message | ||
121 | */ | ||
122 | static void | ||
123 | handle_sync (void *cls, const struct GNUNET_MessageHeader *msg) | ||
124 | { | ||
125 | struct GNUNET_NAMESTORE_ZoneMonitor *zm = cls; | ||
126 | |||
127 | (void) cls; | ||
128 | (void) msg; | ||
129 | if (NULL != zm->sync_cb) | ||
130 | zm->sync_cb (zm->sync_cb_cls); | ||
131 | } | ||
132 | |||
133 | |||
134 | /** | ||
135 | * We've received a notification about a change to our zone. | ||
136 | * Check that it is well-formed. | ||
137 | * | ||
138 | * @param cls the zone monitor handle | ||
139 | * @param lrm the message from the service. | ||
140 | */ | ||
141 | static int | ||
142 | check_result (void *cls, const struct RecordResultMessage *lrm) | ||
143 | { | ||
144 | struct GNUNET_NAMESTORE_ZoneMonitor *zm = cls; | ||
145 | size_t lrm_len; | ||
146 | size_t exp_lrm_len; | ||
147 | size_t name_len; | ||
148 | size_t rd_len; | ||
149 | unsigned rd_count; | ||
150 | const char *name_tmp; | ||
151 | const char *rd_ser_tmp; | ||
152 | size_t key_len; | ||
153 | |||
154 | (void) zm; | ||
155 | key_len = ntohs (lrm->key_len); | ||
156 | (void) cls; | ||
157 | if (0 == key_len) | ||
158 | { | ||
159 | GNUNET_break (0); | ||
160 | return GNUNET_SYSERR; | ||
161 | } | ||
162 | lrm_len = ntohs (lrm->gns_header.header.size); | ||
163 | rd_len = ntohs (lrm->rd_len); | ||
164 | rd_count = ntohs (lrm->rd_count); | ||
165 | name_len = ntohs (lrm->name_len); | ||
166 | if (name_len > MAX_NAME_LEN) | ||
167 | { | ||
168 | GNUNET_break (0); | ||
169 | return GNUNET_SYSERR; | ||
170 | } | ||
171 | exp_lrm_len = sizeof(struct RecordResultMessage) + name_len + rd_len + key_len; | ||
172 | if (lrm_len != exp_lrm_len) | ||
173 | { | ||
174 | GNUNET_break (0); | ||
175 | return GNUNET_SYSERR; | ||
176 | } | ||
177 | if (0 == name_len) | ||
178 | { | ||
179 | GNUNET_break (0); | ||
180 | return GNUNET_SYSERR; | ||
181 | } | ||
182 | name_tmp = (const char *) &lrm[1] + key_len; | ||
183 | if (name_tmp[name_len - 1] != '\0') | ||
184 | { | ||
185 | GNUNET_break (0); | ||
186 | return GNUNET_SYSERR; | ||
187 | } | ||
188 | rd_ser_tmp = (const char *) &name_tmp[name_len]; | ||
189 | { | ||
190 | struct GNUNET_GNSRECORD_Data rd[rd_count]; | ||
191 | |||
192 | if (GNUNET_OK != | ||
193 | GNUNET_GNSRECORD_records_deserialize (rd_len, rd_ser_tmp, rd_count, rd)) | ||
194 | { | ||
195 | GNUNET_break (0); | ||
196 | return GNUNET_SYSERR; | ||
197 | } | ||
198 | } | ||
199 | return GNUNET_OK; | ||
200 | } | ||
201 | |||
202 | |||
203 | /** | ||
204 | * We've received a notification about a change to our zone. | ||
205 | * Forward to monitor callback. | ||
206 | * | ||
207 | * @param cls the zone monitor handle | ||
208 | * @param lrm the message from the service. | ||
209 | */ | ||
210 | static void | ||
211 | handle_result (void *cls, const struct RecordResultMessage *lrm) | ||
212 | { | ||
213 | struct GNUNET_NAMESTORE_ZoneMonitor *zm = cls; | ||
214 | struct GNUNET_CRYPTO_PrivateKey private_key; | ||
215 | size_t name_len; | ||
216 | size_t rd_len; | ||
217 | size_t key_len; | ||
218 | size_t kbytes_read; | ||
219 | unsigned rd_count; | ||
220 | const char *name_tmp; | ||
221 | const char *rd_ser_tmp; | ||
222 | |||
223 | key_len = ntohs (lrm->key_len); | ||
224 | rd_len = ntohs (lrm->rd_len); | ||
225 | rd_count = ntohs (lrm->rd_count); | ||
226 | name_len = ntohs (lrm->name_len); | ||
227 | name_tmp = (const char *) &lrm[1] + key_len; | ||
228 | GNUNET_assert (GNUNET_SYSERR != | ||
229 | GNUNET_CRYPTO_read_private_key_from_buffer (&lrm[1], | ||
230 | key_len, | ||
231 | &private_key, | ||
232 | &kbytes_read)); | ||
233 | GNUNET_assert (kbytes_read == key_len); | ||
234 | rd_ser_tmp = (const char *) &name_tmp[name_len]; | ||
235 | { | ||
236 | struct GNUNET_GNSRECORD_Data rd[rd_count]; | ||
237 | |||
238 | GNUNET_assert ( | ||
239 | GNUNET_OK == | ||
240 | GNUNET_GNSRECORD_records_deserialize (rd_len, rd_ser_tmp, rd_count, rd)); | ||
241 | if (NULL != zm->monitor2) | ||
242 | zm->monitor2 (zm->monitor_cls, &private_key, name_tmp, | ||
243 | rd_count, rd, GNUNET_TIME_absolute_ntoh (lrm->expire)); | ||
244 | else | ||
245 | zm->monitor (zm->monitor_cls, &private_key, name_tmp, rd_count, rd); | ||
246 | } | ||
247 | } | ||
248 | |||
249 | |||
250 | /** | ||
251 | * Generic error handler, called with the appropriate error code and | ||
252 | * the same closure specified at the creation of the message queue. | ||
253 | * Not every message queue implementation supports an error handler. | ||
254 | * | ||
255 | * @param cls closure with the `struct GNUNET_NAMESTORE_ZoneMonitor *` | ||
256 | * @param error error code | ||
257 | */ | ||
258 | static void | ||
259 | mq_error_handler (void *cls, enum GNUNET_MQ_Error error) | ||
260 | { | ||
261 | struct GNUNET_NAMESTORE_ZoneMonitor *zm = cls; | ||
262 | |||
263 | (void) error; | ||
264 | reconnect (zm); | ||
265 | } | ||
266 | |||
267 | |||
268 | /** | ||
269 | * Reconnect to the namestore service. | ||
270 | * | ||
271 | * @param zm monitor to reconnect | ||
272 | */ | ||
273 | static void | ||
274 | reconnect (struct GNUNET_NAMESTORE_ZoneMonitor *zm) | ||
275 | { | ||
276 | struct GNUNET_MQ_MessageHandler handlers[] = | ||
277 | { GNUNET_MQ_hd_fixed_size (sync, | ||
278 | GNUNET_MESSAGE_TYPE_NAMESTORE_MONITOR_SYNC, | ||
279 | struct GNUNET_MessageHeader, | ||
280 | zm), | ||
281 | GNUNET_MQ_hd_var_size (result, | ||
282 | GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_RESULT, | ||
283 | struct RecordResultMessage, | ||
284 | zm), | ||
285 | GNUNET_MQ_handler_end () }; | ||
286 | struct GNUNET_MQ_Envelope *env; | ||
287 | struct ZoneMonitorStartMessage *sm; | ||
288 | |||
289 | if (NULL != zm->mq) | ||
290 | { | ||
291 | GNUNET_MQ_destroy (zm->mq); | ||
292 | zm->error_cb (zm->error_cb_cls); | ||
293 | } | ||
294 | zm->mq = GNUNET_CLIENT_connect (zm->cfg, | ||
295 | "namestore", | ||
296 | handlers, | ||
297 | &mq_error_handler, | ||
298 | zm); | ||
299 | if (NULL == zm->mq) | ||
300 | return; | ||
301 | env = GNUNET_MQ_msg_extra (sm, | ||
302 | zm->key_len, | ||
303 | GNUNET_MESSAGE_TYPE_NAMESTORE_MONITOR_START); | ||
304 | sm->iterate_first = htonl (zm->iterate_first); | ||
305 | if (0 < zm->key_len) | ||
306 | GNUNET_CRYPTO_write_private_key_to_buffer (&zm->zone, | ||
307 | &sm[1], | ||
308 | zm->key_len); | ||
309 | sm->key_len = htons (zm->key_len); | ||
310 | sm->filter = htons (zm->filter); | ||
311 | GNUNET_MQ_send (zm->mq, env); | ||
312 | } | ||
313 | |||
314 | |||
315 | struct GNUNET_NAMESTORE_ZoneMonitor * | ||
316 | GNUNET_NAMESTORE_zone_monitor_start ( | ||
317 | const struct GNUNET_CONFIGURATION_Handle *cfg, | ||
318 | const struct GNUNET_CRYPTO_PrivateKey *zone, | ||
319 | int iterate_first, | ||
320 | GNUNET_SCHEDULER_TaskCallback error_cb, | ||
321 | void *error_cb_cls, | ||
322 | GNUNET_NAMESTORE_RecordMonitor monitor, | ||
323 | void *monitor_cls, | ||
324 | GNUNET_SCHEDULER_TaskCallback sync_cb, | ||
325 | void *sync_cb_cls) | ||
326 | { | ||
327 | struct GNUNET_NAMESTORE_ZoneMonitor *zm; | ||
328 | |||
329 | zm = GNUNET_new (struct GNUNET_NAMESTORE_ZoneMonitor); | ||
330 | if (NULL != zone) | ||
331 | { | ||
332 | zm->key_len = GNUNET_CRYPTO_private_key_get_length (zone); | ||
333 | zm->zone = *zone; | ||
334 | } | ||
335 | zm->iterate_first = iterate_first; | ||
336 | zm->error_cb = error_cb; | ||
337 | zm->error_cb_cls = error_cb_cls; | ||
338 | zm->monitor = monitor; | ||
339 | zm->monitor_cls = monitor_cls; | ||
340 | zm->sync_cb = sync_cb; | ||
341 | zm->sync_cb_cls = sync_cb_cls; | ||
342 | zm->cfg = cfg; | ||
343 | reconnect (zm); | ||
344 | if (NULL == zm->mq) | ||
345 | { | ||
346 | GNUNET_free (zm); | ||
347 | return NULL; | ||
348 | } | ||
349 | return zm; | ||
350 | } | ||
351 | |||
352 | struct GNUNET_NAMESTORE_ZoneMonitor * | ||
353 | GNUNET_NAMESTORE_zone_monitor_start2 ( | ||
354 | const struct GNUNET_CONFIGURATION_Handle *cfg, | ||
355 | const struct GNUNET_CRYPTO_PrivateKey *zone, | ||
356 | int iterate_first, | ||
357 | GNUNET_SCHEDULER_TaskCallback error_cb, | ||
358 | void *error_cb_cls, | ||
359 | GNUNET_NAMESTORE_RecordSetMonitor monitor, | ||
360 | void *monitor_cls, | ||
361 | GNUNET_SCHEDULER_TaskCallback sync_cb, | ||
362 | void *sync_cb_cls, | ||
363 | enum GNUNET_GNSRECORD_Filter filter) | ||
364 | { | ||
365 | struct GNUNET_NAMESTORE_ZoneMonitor *zm; | ||
366 | |||
367 | zm = GNUNET_new (struct GNUNET_NAMESTORE_ZoneMonitor); | ||
368 | if (NULL != zone) | ||
369 | { | ||
370 | zm->key_len = GNUNET_CRYPTO_private_key_get_length (zone); | ||
371 | zm->zone = *zone; | ||
372 | } | ||
373 | zm->iterate_first = iterate_first; | ||
374 | zm->error_cb = error_cb; | ||
375 | zm->error_cb_cls = error_cb_cls; | ||
376 | zm->monitor2 = monitor; | ||
377 | zm->monitor_cls = monitor_cls; | ||
378 | zm->sync_cb = sync_cb; | ||
379 | zm->sync_cb_cls = sync_cb_cls; | ||
380 | zm->cfg = cfg; | ||
381 | zm->filter = filter; | ||
382 | reconnect (zm); | ||
383 | if (NULL == zm->mq) | ||
384 | { | ||
385 | GNUNET_free (zm); | ||
386 | return NULL; | ||
387 | } | ||
388 | return zm; | ||
389 | } | ||
390 | |||
391 | |||
392 | /** | ||
393 | * Calls the monitor processor specified in #GNUNET_NAMESTORE_zone_monitor_start | ||
394 | * for the next record(s). This function is used to allow clients that merely | ||
395 | * monitor the NAMESTORE to still throttle namestore operations, so we can be | ||
396 | * sure that the monitors can keep up. | ||
397 | * | ||
398 | * Note that #GNUNET_NAMESTORE_records_store() only waits for this | ||
399 | * call if the previous limit set by the client was already reached. | ||
400 | * Thus, by using a @a limit greater than 1, monitors basically enable | ||
401 | * a queue of notifications to be processed asynchronously with some | ||
402 | * delay. Note that even with a limit of 1 the | ||
403 | * #GNUNET_NAMESTORE_records_store() function will run asynchronously | ||
404 | * and the continuation may be invoked before the monitors completed | ||
405 | * (or even started) processing the notification. Thus, monitors will | ||
406 | * only closely track the current state of the namestore, but not | ||
407 | * be involved in the transactions. | ||
408 | * | ||
409 | * @param zm the monitor | ||
410 | * @param limit number of records to return to the iterator in one shot | ||
411 | * (before #GNUNET_NAMESTORE_zone_monitor_next is to be called again) | ||
412 | */ | ||
413 | void | ||
414 | GNUNET_NAMESTORE_zone_monitor_next (struct GNUNET_NAMESTORE_ZoneMonitor *zm, | ||
415 | uint64_t limit) | ||
416 | { | ||
417 | struct GNUNET_MQ_Envelope *env; | ||
418 | struct ZoneMonitorNextMessage *nm; | ||
419 | |||
420 | env = GNUNET_MQ_msg (nm, GNUNET_MESSAGE_TYPE_NAMESTORE_MONITOR_NEXT); | ||
421 | nm->limit = GNUNET_htonll (limit); | ||
422 | GNUNET_MQ_send (zm->mq, env); | ||
423 | } | ||
424 | |||
425 | |||
426 | /** | ||
427 | * Stop monitoring a zone for changes. | ||
428 | * | ||
429 | * @param zm handle to the monitor activity to stop | ||
430 | */ | ||
431 | void | ||
432 | GNUNET_NAMESTORE_zone_monitor_stop (struct GNUNET_NAMESTORE_ZoneMonitor *zm) | ||
433 | { | ||
434 | if (NULL != zm->mq) | ||
435 | { | ||
436 | GNUNET_MQ_destroy (zm->mq); | ||
437 | zm->mq = NULL; | ||
438 | } | ||
439 | GNUNET_free (zm); | ||
440 | } | ||
441 | |||
442 | |||
443 | /* end of namestore_api_monitor.c */ | ||
diff --git a/src/namestore/perf_namestore_api_import.c b/src/namestore/perf_namestore_api_import.c deleted file mode 100644 index e56fb961c..000000000 --- a/src/namestore/perf_namestore_api_import.c +++ /dev/null | |||
@@ -1,406 +0,0 @@ | |||
1 | /* | ||
2 | This file is part of GNUnet. | ||
3 | Copyright (C) 2022 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_import.c | ||
22 | * @brief testcase for namestore: Import a lot of records | ||
23 | * @author Martin Schanzenbach | ||
24 | */ | ||
25 | #include "platform.h" | ||
26 | #include "gnunet_namestore_service.h" | ||
27 | #include "gnunet_testing_lib.h" | ||
28 | #include "namestore.h" | ||
29 | |||
30 | #define TEST_RECORD_TYPE GNUNET_DNSPARSER_TYPE_TXT | ||
31 | |||
32 | #define TEST_RECORD_COUNT 10000 | ||
33 | |||
34 | /** | ||
35 | * A #BENCHMARK_SIZE of 1000 takes less than a minute on a reasonably | ||
36 | * modern system, so 30 minutes should be OK even for very, very | ||
37 | * slow systems. | ||
38 | */ | ||
39 | #define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 30) | ||
40 | |||
41 | /** | ||
42 | * The runtime of the benchmark is expected to be linear | ||
43 | * for the iteration phase with a *good* database. The FLAT | ||
44 | * database uses a quadratic retrieval algorithm, | ||
45 | * hence it should be quadratic in the size. | ||
46 | */ | ||
47 | #define BENCHMARK_SIZE 1000 | ||
48 | |||
49 | /** | ||
50 | * Maximum record size | ||
51 | */ | ||
52 | #define MAX_REC_SIZE 500 | ||
53 | |||
54 | /** | ||
55 | * How big are the blocks we fetch? Note that the first block is | ||
56 | * always just 1 record set per current API. Smaller block | ||
57 | * sizes will make quadratic iteration-by-offset penalties | ||
58 | * more pronounced. | ||
59 | */ | ||
60 | #define BLOCK_SIZE 100 | ||
61 | |||
62 | static struct GNUNET_NAMESTORE_Handle *nsh; | ||
63 | |||
64 | static struct GNUNET_SCHEDULER_Task *timeout_task; | ||
65 | |||
66 | static struct GNUNET_SCHEDULER_Task *t; | ||
67 | |||
68 | static struct GNUNET_CRYPTO_PrivateKey privkey; | ||
69 | |||
70 | static struct GNUNET_NAMESTORE_QueueEntry *qe; | ||
71 | |||
72 | static int res; | ||
73 | |||
74 | static struct GNUNET_TIME_Absolute start; | ||
75 | |||
76 | struct GNUNET_NAMESTORE_RecordInfo ri[TEST_RECORD_COUNT]; | ||
77 | |||
78 | int single_put_pos; | ||
79 | |||
80 | static int bulk_count = 0; | ||
81 | |||
82 | |||
83 | /** | ||
84 | * Terminate everything | ||
85 | * | ||
86 | * @param cls NULL | ||
87 | */ | ||
88 | static void | ||
89 | end (void *cls) | ||
90 | { | ||
91 | (void) cls; | ||
92 | if (NULL != qe) | ||
93 | { | ||
94 | GNUNET_NAMESTORE_cancel (qe); | ||
95 | qe = NULL; | ||
96 | } | ||
97 | if (NULL != nsh) | ||
98 | { | ||
99 | GNUNET_NAMESTORE_disconnect (nsh); | ||
100 | nsh = NULL; | ||
101 | } | ||
102 | if (NULL != t) | ||
103 | { | ||
104 | GNUNET_SCHEDULER_cancel (t); | ||
105 | t = NULL; | ||
106 | } | ||
107 | if (NULL != timeout_task) | ||
108 | { | ||
109 | GNUNET_SCHEDULER_cancel (timeout_task); | ||
110 | timeout_task = NULL; | ||
111 | } | ||
112 | } | ||
113 | |||
114 | |||
115 | /** | ||
116 | * End with timeout. As this is a benchmark, we do not | ||
117 | * fail hard but return "skipped". | ||
118 | */ | ||
119 | static void | ||
120 | timeout (void *cls) | ||
121 | { | ||
122 | (void) cls; | ||
123 | timeout_task = NULL; | ||
124 | GNUNET_SCHEDULER_shutdown (); | ||
125 | res = 77; | ||
126 | } | ||
127 | |||
128 | |||
129 | static struct GNUNET_GNSRECORD_Data * | ||
130 | create_record (unsigned int count) | ||
131 | { | ||
132 | struct GNUNET_GNSRECORD_Data *rd; | ||
133 | |||
134 | rd = GNUNET_malloc (count + sizeof(struct GNUNET_GNSRECORD_Data)); | ||
135 | rd->expiration_time = GNUNET_TIME_relative_to_absolute ( | ||
136 | GNUNET_TIME_UNIT_HOURS).abs_value_us; | ||
137 | rd->record_type = TEST_RECORD_TYPE; | ||
138 | rd->data_size = count; | ||
139 | rd->data = (void *) &rd[1]; | ||
140 | rd->flags = 0; | ||
141 | memset (&rd[1], | ||
142 | 'a', | ||
143 | count); | ||
144 | return rd; | ||
145 | } | ||
146 | |||
147 | |||
148 | static void | ||
149 | publish_records_single (void *cls); | ||
150 | |||
151 | static void | ||
152 | commit_cont (void *cls, | ||
153 | enum GNUNET_ErrorCode ec) | ||
154 | { | ||
155 | struct GNUNET_TIME_Relative delay; | ||
156 | |||
157 | (void) cls; | ||
158 | qe = NULL; | ||
159 | if (GNUNET_EC_NONE != ec) | ||
160 | { | ||
161 | GNUNET_break (0); | ||
162 | GNUNET_SCHEDULER_shutdown (); | ||
163 | return; | ||
164 | } | ||
165 | single_put_pos++; | ||
166 | delay = GNUNET_TIME_absolute_get_duration (start); | ||
167 | fprintf (stdout, | ||
168 | "BULK-TX: Publishing %u records took %s\n", | ||
169 | TEST_RECORD_COUNT, | ||
170 | GNUNET_STRINGS_relative_time_to_string (delay, | ||
171 | GNUNET_YES)); | ||
172 | res = 0; | ||
173 | GNUNET_SCHEDULER_shutdown (); | ||
174 | } | ||
175 | |||
176 | static void | ||
177 | publish_records_bulk_tx (void *cls); | ||
178 | |||
179 | |||
180 | static void | ||
181 | put_cont_bulk_tx (void *cls, | ||
182 | enum GNUNET_ErrorCode ec) | ||
183 | { | ||
184 | qe = NULL; | ||
185 | if (GNUNET_EC_NONE != ec) | ||
186 | { | ||
187 | GNUNET_break (0); | ||
188 | GNUNET_SCHEDULER_shutdown (); | ||
189 | return; | ||
190 | } | ||
191 | if (bulk_count == TEST_RECORD_COUNT) | ||
192 | { | ||
193 | qe = GNUNET_NAMESTORE_transaction_commit (nsh, commit_cont, NULL); | ||
194 | return; | ||
195 | } | ||
196 | t = GNUNET_SCHEDULER_add_now (&publish_records_bulk_tx, NULL); | ||
197 | } | ||
198 | |||
199 | |||
200 | static void | ||
201 | publish_records_bulk_tx (void *cls) | ||
202 | { | ||
203 | unsigned int sent_rds; | ||
204 | t = NULL; | ||
205 | qe = GNUNET_NAMESTORE_records_store2 (nsh, | ||
206 | &privkey, | ||
207 | TEST_RECORD_COUNT - bulk_count, | ||
208 | &ri[bulk_count], | ||
209 | &sent_rds, | ||
210 | &put_cont_bulk_tx, | ||
211 | NULL); | ||
212 | bulk_count += sent_rds; | ||
213 | GNUNET_assert (sent_rds != 0); | ||
214 | } | ||
215 | |||
216 | |||
217 | static void | ||
218 | begin_cont (void *cls, | ||
219 | enum GNUNET_ErrorCode ec) | ||
220 | { | ||
221 | unsigned int sent_rds; | ||
222 | qe = GNUNET_NAMESTORE_records_store2 (nsh, | ||
223 | &privkey, | ||
224 | TEST_RECORD_COUNT - bulk_count, | ||
225 | &ri[bulk_count], | ||
226 | &sent_rds, | ||
227 | &put_cont_bulk_tx, | ||
228 | NULL); | ||
229 | bulk_count += sent_rds; | ||
230 | GNUNET_assert (sent_rds != 0); | ||
231 | } | ||
232 | |||
233 | static void | ||
234 | publish_records_bulk (void *cls); | ||
235 | |||
236 | static void | ||
237 | put_cont_bulk (void *cls, | ||
238 | enum GNUNET_ErrorCode ec) | ||
239 | { | ||
240 | struct GNUNET_TIME_Relative delay; | ||
241 | |||
242 | (void) cls; | ||
243 | qe = NULL; | ||
244 | if (GNUNET_EC_NONE != ec) | ||
245 | { | ||
246 | GNUNET_break (0); | ||
247 | GNUNET_SCHEDULER_shutdown (); | ||
248 | return; | ||
249 | } | ||
250 | |||
251 | if (bulk_count == TEST_RECORD_COUNT) | ||
252 | { | ||
253 | delay = GNUNET_TIME_absolute_get_duration (start); | ||
254 | fprintf (stdout, | ||
255 | "BULK: Publishing %u records took %s\n", | ||
256 | TEST_RECORD_COUNT, | ||
257 | GNUNET_STRINGS_relative_time_to_string (delay, | ||
258 | GNUNET_YES)); | ||
259 | start = GNUNET_TIME_absolute_get (); | ||
260 | bulk_count = 0; | ||
261 | qe = GNUNET_NAMESTORE_transaction_begin (nsh, begin_cont, NULL); | ||
262 | return; | ||
263 | } | ||
264 | (void) cls; | ||
265 | qe = NULL; | ||
266 | if (GNUNET_EC_NONE != ec) | ||
267 | { | ||
268 | GNUNET_break (0); | ||
269 | GNUNET_SCHEDULER_shutdown (); | ||
270 | return; | ||
271 | } | ||
272 | t = GNUNET_SCHEDULER_add_now (&publish_records_bulk, NULL); | ||
273 | } | ||
274 | |||
275 | static void | ||
276 | publish_records_bulk (void *cls) | ||
277 | { | ||
278 | static unsigned int sent_rds = 0; | ||
279 | (void) cls; | ||
280 | t = NULL; | ||
281 | qe = GNUNET_NAMESTORE_records_store2 (nsh, | ||
282 | &privkey, | ||
283 | TEST_RECORD_COUNT - bulk_count, | ||
284 | &ri[bulk_count], | ||
285 | &sent_rds, | ||
286 | &put_cont_bulk, | ||
287 | NULL); | ||
288 | bulk_count += sent_rds; | ||
289 | GNUNET_assert (sent_rds != 0); | ||
290 | } | ||
291 | |||
292 | |||
293 | static void | ||
294 | put_cont_single (void *cls, | ||
295 | enum GNUNET_ErrorCode ec) | ||
296 | { | ||
297 | struct GNUNET_TIME_Relative delay; | ||
298 | (void) cls; | ||
299 | qe = NULL; | ||
300 | if (GNUNET_EC_NONE != ec) | ||
301 | { | ||
302 | GNUNET_break (0); | ||
303 | GNUNET_SCHEDULER_shutdown (); | ||
304 | return; | ||
305 | } | ||
306 | single_put_pos++; | ||
307 | if (single_put_pos == TEST_RECORD_COUNT) | ||
308 | { | ||
309 | delay = GNUNET_TIME_absolute_get_duration (start); | ||
310 | fprintf (stdout, | ||
311 | "SINGLE: Publishing %u records took %s\n", | ||
312 | TEST_RECORD_COUNT, | ||
313 | GNUNET_STRINGS_relative_time_to_string (delay, | ||
314 | GNUNET_YES)); | ||
315 | start = GNUNET_TIME_absolute_get (); | ||
316 | t = GNUNET_SCHEDULER_add_now (&publish_records_bulk, NULL); | ||
317 | return; | ||
318 | } | ||
319 | t = GNUNET_SCHEDULER_add_now (&publish_records_single, | ||
320 | NULL); | ||
321 | } | ||
322 | |||
323 | |||
324 | static void | ||
325 | publish_records_single (void *cls) | ||
326 | { | ||
327 | struct GNUNET_TIME_Relative delay; | ||
328 | |||
329 | (void) cls; | ||
330 | t = NULL; | ||
331 | if (single_put_pos == TEST_RECORD_COUNT) | ||
332 | { | ||
333 | delay = GNUNET_TIME_absolute_get_duration (start); | ||
334 | fprintf (stdout, | ||
335 | "Publishing %u records took %s\n", | ||
336 | TEST_RECORD_COUNT, | ||
337 | GNUNET_STRINGS_relative_time_to_string (delay, | ||
338 | GNUNET_YES)); | ||
339 | GNUNET_SCHEDULER_add_now (&publish_records_bulk, NULL); | ||
340 | } | ||
341 | qe = GNUNET_NAMESTORE_records_store (nsh, | ||
342 | &privkey, | ||
343 | ri[single_put_pos].a_label, | ||
344 | ri[single_put_pos].a_rd_count, | ||
345 | ri[single_put_pos].a_rd, | ||
346 | &put_cont_single, | ||
347 | NULL); | ||
348 | } | ||
349 | |||
350 | |||
351 | static void | ||
352 | run (void *cls, | ||
353 | const struct GNUNET_CONFIGURATION_Handle *cfg, | ||
354 | struct GNUNET_TESTING_Peer *peer) | ||
355 | { | ||
356 | |||
357 | for (int i = 0; i < TEST_RECORD_COUNT; i++) | ||
358 | { | ||
359 | ri[i].a_rd = create_record (1); | ||
360 | ri[i].a_rd_count = 1; | ||
361 | GNUNET_asprintf ((char**) &ri[i].a_label, "label_%d", i); | ||
362 | } | ||
363 | GNUNET_SCHEDULER_add_shutdown (&end, | ||
364 | NULL); | ||
365 | timeout_task = GNUNET_SCHEDULER_add_delayed (TIMEOUT, | ||
366 | &timeout, | ||
367 | NULL); | ||
368 | nsh = GNUNET_NAMESTORE_connect (cfg); | ||
369 | GNUNET_assert (NULL != nsh); | ||
370 | privkey.type = htonl (GNUNET_GNSRECORD_TYPE_PKEY); | ||
371 | GNUNET_CRYPTO_ecdsa_key_create (&privkey.ecdsa_key); | ||
372 | start = GNUNET_TIME_absolute_get (); | ||
373 | t = GNUNET_SCHEDULER_add_now (&publish_records_single, | ||
374 | NULL); | ||
375 | } | ||
376 | |||
377 | |||
378 | #include "test_common.c" | ||
379 | |||
380 | |||
381 | int | ||
382 | main (int argc, | ||
383 | char *argv[]) | ||
384 | { | ||
385 | const char *plugin_name; | ||
386 | char *cfg_name; | ||
387 | |||
388 | SETUP_CFG2 ("perf_namestore_api_%s.conf", plugin_name, cfg_name); | ||
389 | res = 1; | ||
390 | if (0 != | ||
391 | GNUNET_TESTING_peer_run ("perf-namestore-api-import", | ||
392 | cfg_name, | ||
393 | &run, | ||
394 | NULL)) | ||
395 | { | ||
396 | res = 1; | ||
397 | } | ||
398 | GNUNET_DISK_purge_cfg_dir (cfg_name, | ||
399 | "GNUNET_TEST_HOME"); | ||
400 | GNUNET_free (plugin_name); | ||
401 | GNUNET_free (cfg_name); | ||
402 | return res; | ||
403 | } | ||
404 | |||
405 | |||
406 | /* end of perf_namestore_api_zone_iteration.c */ | ||
diff --git a/src/namestore/perf_namestore_api_postgres.conf b/src/namestore/perf_namestore_api_postgres.conf deleted file mode 100644 index 5e02c2df3..000000000 --- a/src/namestore/perf_namestore_api_postgres.conf +++ /dev/null | |||
@@ -1,12 +0,0 @@ | |||
1 | @INLINE@ test_namestore_api_postgres.conf | ||
2 | |||
3 | [namestore] | ||
4 | DATABASE = postgres | ||
5 | |||
6 | [namecache] | ||
7 | DISABLE = YES | ||
8 | |||
9 | [namestore-postgres] | ||
10 | CONFIG = connect_timeout=10 dbname=gnunetcheck | ||
11 | #TEMPORARY_TABLE = YES | ||
12 | INIT_ON_CONNECT = YES | ||
diff --git a/src/namestore/perf_namestore_api_sqlite.conf b/src/namestore/perf_namestore_api_sqlite.conf deleted file mode 100644 index 55c3dc812..000000000 --- a/src/namestore/perf_namestore_api_sqlite.conf +++ /dev/null | |||
@@ -1,8 +0,0 @@ | |||
1 | @INLINE@ test_namestore_api.conf | ||
2 | |||
3 | [namecache] | ||
4 | DISABLE = YES | ||
5 | |||
6 | [namestore-sqlite] | ||
7 | FILENAME = $GNUNET_TEST_HOME/namestore/sqlite_test.db | ||
8 | INIT_ON_CONNECT = YES | ||
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 e16748f5b..000000000 --- a/src/namestore/perf_namestore_api_zone_iteration.c +++ /dev/null | |||
@@ -1,378 +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 | |||
30 | #define TEST_RECORD_TYPE GNUNET_DNSPARSER_TYPE_TXT | ||
31 | |||
32 | /** | ||
33 | * A #BENCHMARK_SIZE of 1000 takes less than a minute on a reasonably | ||
34 | * modern system, so 30 minutes should be OK even for very, very | ||
35 | * slow systems. | ||
36 | */ | ||
37 | #define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 30) | ||
38 | |||
39 | /** | ||
40 | * The runtime of the benchmark is expected to be linear | ||
41 | * for the iteration phase with a *good* database. The FLAT | ||
42 | * database uses a quadratic retrieval algorithm, | ||
43 | * hence it should be quadratic in the size. | ||
44 | */ | ||
45 | #define BENCHMARK_SIZE 1000 | ||
46 | |||
47 | /** | ||
48 | * Maximum record size | ||
49 | */ | ||
50 | #define MAX_REC_SIZE 500 | ||
51 | |||
52 | /** | ||
53 | * How big are the blocks we fetch? Note that the first block is | ||
54 | * always just 1 record set per current API. Smaller block | ||
55 | * sizes will make quadratic iteration-by-offset penalties | ||
56 | * more pronounced. | ||
57 | */ | ||
58 | #define BLOCK_SIZE 100 | ||
59 | |||
60 | static struct GNUNET_NAMESTORE_Handle *nsh; | ||
61 | |||
62 | static struct GNUNET_SCHEDULER_Task *timeout_task; | ||
63 | |||
64 | static struct GNUNET_SCHEDULER_Task *t; | ||
65 | |||
66 | static struct GNUNET_CRYPTO_PrivateKey privkey; | ||
67 | |||
68 | static struct GNUNET_NAMESTORE_ZoneIterator *zi; | ||
69 | |||
70 | static struct GNUNET_NAMESTORE_QueueEntry *qe; | ||
71 | |||
72 | static int res; | ||
73 | |||
74 | static unsigned int off; | ||
75 | |||
76 | static unsigned int left_until_next; | ||
77 | |||
78 | static uint8_t seen[1 + BENCHMARK_SIZE / 8]; | ||
79 | |||
80 | static struct GNUNET_TIME_Absolute start; | ||
81 | |||
82 | |||
83 | /** | ||
84 | * Terminate everything | ||
85 | * | ||
86 | * @param cls NULL | ||
87 | */ | ||
88 | static void | ||
89 | end (void *cls) | ||
90 | { | ||
91 | (void) cls; | ||
92 | if (NULL != qe) | ||
93 | { | ||
94 | GNUNET_NAMESTORE_cancel (qe); | ||
95 | qe = NULL; | ||
96 | } | ||
97 | if (NULL != zi) | ||
98 | { | ||
99 | GNUNET_NAMESTORE_zone_iteration_stop (zi); | ||
100 | zi = NULL; | ||
101 | } | ||
102 | if (NULL != nsh) | ||
103 | { | ||
104 | GNUNET_NAMESTORE_disconnect (nsh); | ||
105 | nsh = NULL; | ||
106 | } | ||
107 | if (NULL != t) | ||
108 | { | ||
109 | GNUNET_SCHEDULER_cancel (t); | ||
110 | t = NULL; | ||
111 | } | ||
112 | if (NULL != timeout_task) | ||
113 | { | ||
114 | GNUNET_SCHEDULER_cancel (timeout_task); | ||
115 | timeout_task = NULL; | ||
116 | } | ||
117 | } | ||
118 | |||
119 | |||
120 | /** | ||
121 | * End with timeout. As this is a benchmark, we do not | ||
122 | * fail hard but return "skipped". | ||
123 | */ | ||
124 | static void | ||
125 | timeout (void *cls) | ||
126 | { | ||
127 | (void) cls; | ||
128 | timeout_task = NULL; | ||
129 | GNUNET_SCHEDULER_shutdown (); | ||
130 | res = 77; | ||
131 | } | ||
132 | |||
133 | |||
134 | static struct GNUNET_GNSRECORD_Data * | ||
135 | create_record (unsigned int count) | ||
136 | { | ||
137 | struct GNUNET_GNSRECORD_Data *rd; | ||
138 | |||
139 | rd = GNUNET_malloc (count + sizeof(struct GNUNET_GNSRECORD_Data)); | ||
140 | rd->expiration_time = GNUNET_TIME_relative_to_absolute ( | ||
141 | GNUNET_TIME_UNIT_HOURS).abs_value_us; | ||
142 | rd->record_type = TEST_RECORD_TYPE; | ||
143 | rd->data_size = count; | ||
144 | rd->data = (void *) &rd[1]; | ||
145 | rd->flags = 0; | ||
146 | memset (&rd[1], | ||
147 | 'a', | ||
148 | count); | ||
149 | return rd; | ||
150 | } | ||
151 | |||
152 | |||
153 | static void | ||
154 | zone_end (void *cls) | ||
155 | { | ||
156 | struct GNUNET_TIME_Relative delay; | ||
157 | |||
158 | zi = NULL; | ||
159 | delay = GNUNET_TIME_absolute_get_duration (start); | ||
160 | fprintf (stdout, | ||
161 | "Iterating over %u records took %s\n", | ||
162 | off, | ||
163 | GNUNET_STRINGS_relative_time_to_string (delay, | ||
164 | GNUNET_YES)); | ||
165 | if (BENCHMARK_SIZE == off) | ||
166 | { | ||
167 | res = 0; | ||
168 | } | ||
169 | else | ||
170 | { | ||
171 | GNUNET_break (0); | ||
172 | res = 1; | ||
173 | } | ||
174 | GNUNET_SCHEDULER_shutdown (); | ||
175 | } | ||
176 | |||
177 | |||
178 | static void | ||
179 | fail_cb (void *cls) | ||
180 | { | ||
181 | zi = NULL; | ||
182 | res = 2; | ||
183 | GNUNET_break (0); | ||
184 | GNUNET_SCHEDULER_shutdown (); | ||
185 | } | ||
186 | |||
187 | |||
188 | static void | ||
189 | zone_proc (void *cls, | ||
190 | const struct GNUNET_CRYPTO_PrivateKey *zone, | ||
191 | const char *label, | ||
192 | unsigned int rd_count, | ||
193 | const struct GNUNET_GNSRECORD_Data *rd) | ||
194 | { | ||
195 | struct GNUNET_GNSRECORD_Data *wrd; | ||
196 | unsigned int xoff; | ||
197 | |||
198 | GNUNET_assert (NULL != zone); | ||
199 | if (1 != sscanf (label, | ||
200 | "l%u", | ||
201 | &xoff)) | ||
202 | { | ||
203 | res = 3; | ||
204 | GNUNET_break (0); | ||
205 | GNUNET_SCHEDULER_shutdown (); | ||
206 | return; | ||
207 | } | ||
208 | if ((xoff > BENCHMARK_SIZE) || | ||
209 | (0 != (seen[xoff / 8] & (1U << (xoff % 8))))) | ||
210 | { | ||
211 | res = 3; | ||
212 | GNUNET_break (0); | ||
213 | GNUNET_SCHEDULER_shutdown (); | ||
214 | return; | ||
215 | } | ||
216 | seen[xoff / 8] |= (1U << (xoff % 8)); | ||
217 | wrd = create_record (xoff % MAX_REC_SIZE); | ||
218 | if ((rd->record_type != wrd->record_type) || | ||
219 | (rd->data_size != wrd->data_size) || | ||
220 | (rd->flags != wrd->flags)) | ||
221 | { | ||
222 | res = 4; | ||
223 | GNUNET_break (0); | ||
224 | GNUNET_SCHEDULER_shutdown (); | ||
225 | GNUNET_free (wrd); | ||
226 | return; | ||
227 | } | ||
228 | if (0 != memcmp (rd->data, | ||
229 | wrd->data, | ||
230 | wrd->data_size)) | ||
231 | { | ||
232 | res = 4; | ||
233 | GNUNET_break (0); | ||
234 | GNUNET_SCHEDULER_shutdown (); | ||
235 | GNUNET_free (wrd); | ||
236 | return; | ||
237 | } | ||
238 | GNUNET_free (wrd); | ||
239 | if (0 != GNUNET_memcmp (zone, | ||
240 | &privkey)) | ||
241 | { | ||
242 | res = 5; | ||
243 | GNUNET_break (0); | ||
244 | GNUNET_SCHEDULER_shutdown (); | ||
245 | return; | ||
246 | } | ||
247 | off++; | ||
248 | left_until_next--; | ||
249 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
250 | "Obtained record %u, expecting %u more until asking for more explicitly\n", | ||
251 | off, | ||
252 | left_until_next); | ||
253 | if (0 == left_until_next) | ||
254 | { | ||
255 | left_until_next = BLOCK_SIZE; | ||
256 | GNUNET_NAMESTORE_zone_iterator_next (zi, | ||
257 | left_until_next); | ||
258 | } | ||
259 | } | ||
260 | |||
261 | |||
262 | static void | ||
263 | publish_record (void *cls); | ||
264 | |||
265 | |||
266 | static void | ||
267 | put_cont (void *cls, | ||
268 | enum GNUNET_ErrorCode ec) | ||
269 | { | ||
270 | (void) cls; | ||
271 | qe = NULL; | ||
272 | if (GNUNET_EC_NONE != ec) | ||
273 | { | ||
274 | GNUNET_break (0); | ||
275 | GNUNET_SCHEDULER_shutdown (); | ||
276 | return; | ||
277 | } | ||
278 | t = GNUNET_SCHEDULER_add_now (&publish_record, | ||
279 | NULL); | ||
280 | } | ||
281 | |||
282 | |||
283 | static void | ||
284 | publish_record (void *cls) | ||
285 | { | ||
286 | struct GNUNET_GNSRECORD_Data *rd; | ||
287 | char *label; | ||
288 | |||
289 | (void) cls; | ||
290 | t = NULL; | ||
291 | if (BENCHMARK_SIZE == off) | ||
292 | { | ||
293 | struct GNUNET_TIME_Relative delay; | ||
294 | |||
295 | delay = GNUNET_TIME_absolute_get_duration (start); | ||
296 | fprintf (stdout, | ||
297 | "Inserting %u records took %s\n", | ||
298 | off, | ||
299 | GNUNET_STRINGS_relative_time_to_string (delay, | ||
300 | GNUNET_YES)); | ||
301 | start = GNUNET_TIME_absolute_get (); | ||
302 | off = 0; | ||
303 | left_until_next = 1; | ||
304 | zi = GNUNET_NAMESTORE_zone_iteration_start (nsh, | ||
305 | NULL, | ||
306 | &fail_cb, | ||
307 | NULL, | ||
308 | &zone_proc, | ||
309 | NULL, | ||
310 | &zone_end, | ||
311 | NULL); | ||
312 | GNUNET_assert (NULL != zi); | ||
313 | return; | ||
314 | } | ||
315 | rd = create_record ((++off) % MAX_REC_SIZE); | ||
316 | GNUNET_asprintf (&label, | ||
317 | "l%u", | ||
318 | off); | ||
319 | qe = GNUNET_NAMESTORE_records_store (nsh, | ||
320 | &privkey, | ||
321 | label, | ||
322 | 1, rd, | ||
323 | &put_cont, | ||
324 | NULL); | ||
325 | GNUNET_free (label); | ||
326 | GNUNET_free (rd); | ||
327 | } | ||
328 | |||
329 | |||
330 | static void | ||
331 | run (void *cls, | ||
332 | const struct GNUNET_CONFIGURATION_Handle *cfg, | ||
333 | struct GNUNET_TESTING_Peer *peer) | ||
334 | { | ||
335 | GNUNET_SCHEDULER_add_shutdown (&end, | ||
336 | NULL); | ||
337 | timeout_task = GNUNET_SCHEDULER_add_delayed (TIMEOUT, | ||
338 | &timeout, | ||
339 | NULL); | ||
340 | nsh = GNUNET_NAMESTORE_connect (cfg); | ||
341 | GNUNET_assert (NULL != nsh); | ||
342 | privkey.type = htonl (GNUNET_GNSRECORD_TYPE_PKEY); | ||
343 | GNUNET_CRYPTO_ecdsa_key_create (&privkey.ecdsa_key); | ||
344 | start = GNUNET_TIME_absolute_get (); | ||
345 | t = GNUNET_SCHEDULER_add_now (&publish_record, | ||
346 | NULL); | ||
347 | } | ||
348 | |||
349 | |||
350 | #include "test_common.c" | ||
351 | |||
352 | |||
353 | int | ||
354 | main (int argc, | ||
355 | char *argv[]) | ||
356 | { | ||
357 | const char *plugin_name; | ||
358 | char *cfg_name; | ||
359 | |||
360 | SETUP_CFG (plugin_name, cfg_name); | ||
361 | res = 1; | ||
362 | if (0 != | ||
363 | GNUNET_TESTING_peer_run ("perf-namestore-api-zone-iteration", | ||
364 | cfg_name, | ||
365 | &run, | ||
366 | NULL)) | ||
367 | { | ||
368 | res = 1; | ||
369 | } | ||
370 | GNUNET_DISK_purge_cfg_dir (cfg_name, | ||
371 | "GNUNET_TEST_HOME"); | ||
372 | GNUNET_free (plugin_name); | ||
373 | GNUNET_free (cfg_name); | ||
374 | return res; | ||
375 | } | ||
376 | |||
377 | |||
378 | /* 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 8b574d2cf..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 | */ | ||
36 | struct 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 | |||
52 | struct FlatFileEntry | ||
53 | { | ||
54 | /** | ||
55 | * Entry zone | ||
56 | */ | ||
57 | struct GNUNET_CRYPTO_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[out] h initialized hash | ||
87 | */ | ||
88 | static void | ||
89 | hash_pkey_and_label (const struct GNUNET_CRYPTO_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_CRYPTO_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_CRYPTO_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 | */ | ||
121 | static int | ||
122 | database_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_CRYPTO_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 | */ | ||
334 | static int | ||
335 | store_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_CRYPTO_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 | */ | ||
410 | static void | ||
411 | database_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 | */ | ||
452 | static int | ||
453 | namestore_flat_store_records (void *cls, | ||
454 | const struct | ||
455 | GNUNET_CRYPTO_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_CRYPTO_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 | */ | ||
518 | static int | ||
519 | namestore_flat_lookup_records (void *cls, | ||
520 | const struct GNUNET_CRYPTO_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 | */ | ||
556 | struct 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_CRYPTO_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 | */ | ||
599 | static int | ||
600 | iterate_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 | */ | ||
647 | static int | ||
648 | namestore_flat_iterate_records (void *cls, | ||
649 | const struct | ||
650 | GNUNET_CRYPTO_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 | */ | ||
675 | struct ZoneToNameContext | ||
676 | { | ||
677 | const struct GNUNET_CRYPTO_PrivateKey *zone; | ||
678 | const struct GNUNET_CRYPTO_PublicKey *value_zone; | ||
679 | GNUNET_NAMESTORE_RecordIterator iter; | ||
680 | void *iter_cls; | ||
681 | |||
682 | int result_found; | ||
683 | }; | ||
684 | |||
685 | |||
686 | static int | ||
687 | zone_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 | */ | ||
734 | static int | ||
735 | namestore_flat_zone_to_name (void *cls, | ||
736 | const struct GNUNET_CRYPTO_PrivateKey *zone, | ||
737 | const struct | ||
738 | GNUNET_CRYPTO_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 | */ | ||
767 | void * | ||
768 | libgnunet_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 | */ | ||
803 | void * | ||
804 | libgnunet_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 c6debf3a9..000000000 --- a/src/namestore/plugin_namestore_postgres.c +++ /dev/null | |||
@@ -1,796 +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 | */ | ||
40 | struct 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 | * Database is prepared and ready | ||
54 | */ | ||
55 | bool ready; | ||
56 | }; | ||
57 | |||
58 | |||
59 | /** | ||
60 | * Initialize the database connections and associated data structures (create | ||
61 | * tables and indices as needed as well). | ||
62 | * | ||
63 | * @param cls the plugin context (state for this module) | ||
64 | * @return #GNUNET_OK on success | ||
65 | */ | ||
66 | static enum GNUNET_GenericReturnValue | ||
67 | namestore_postgres_create_tables (void *cls) | ||
68 | { | ||
69 | struct Plugin *plugin = cls; | ||
70 | struct GNUNET_PQ_Context *dbh; | ||
71 | |||
72 | dbh = GNUNET_PQ_connect_with_cfg (plugin->cfg, | ||
73 | "namestore-postgres", | ||
74 | "namestore-", | ||
75 | NULL, | ||
76 | NULL); | ||
77 | if (NULL == dbh) | ||
78 | return GNUNET_SYSERR; | ||
79 | GNUNET_PQ_disconnect (dbh); | ||
80 | return GNUNET_OK; | ||
81 | } | ||
82 | |||
83 | |||
84 | /** | ||
85 | * Drop existing namestore tables. | ||
86 | * | ||
87 | * @param cls the plugin context (state for this module) | ||
88 | * @return #GNUNET_OK on success | ||
89 | */ | ||
90 | static enum GNUNET_GenericReturnValue | ||
91 | namestore_postgres_drop_tables (void *cls) | ||
92 | { | ||
93 | struct Plugin *plugin = cls; | ||
94 | struct GNUNET_PQ_Context *dbh; | ||
95 | enum GNUNET_GenericReturnValue ret; | ||
96 | |||
97 | dbh = GNUNET_PQ_connect_with_cfg (plugin->cfg, | ||
98 | "namestore-postgres", | ||
99 | NULL, | ||
100 | NULL, | ||
101 | NULL); | ||
102 | if (NULL == dbh) | ||
103 | { | ||
104 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
105 | "Failed to connect to database\n"); | ||
106 | return GNUNET_SYSERR; | ||
107 | } | ||
108 | ret = GNUNET_PQ_exec_sql (dbh, | ||
109 | "namestore-drop"); | ||
110 | GNUNET_PQ_disconnect (dbh); | ||
111 | return ret; | ||
112 | } | ||
113 | |||
114 | |||
115 | static enum GNUNET_GenericReturnValue | ||
116 | database_prepare (struct Plugin *plugin) | ||
117 | { | ||
118 | enum GNUNET_GenericReturnValue ret; | ||
119 | |||
120 | if (plugin->ready) | ||
121 | return GNUNET_OK; | ||
122 | { | ||
123 | struct GNUNET_PQ_PreparedStatement ps[] = { | ||
124 | GNUNET_PQ_make_prepare ("store_records", | ||
125 | "INSERT INTO namestore.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 | GNUNET_PQ_make_prepare ("delete_records", | ||
134 | "DELETE FROM namestore.ns098records " | ||
135 | "WHERE zone_private_key=$1 AND label=$2"), | ||
136 | GNUNET_PQ_make_prepare ("zone_to_name", | ||
137 | "SELECT seq,record_count,record_data,label FROM namestore.ns098records" | ||
138 | " WHERE zone_private_key=$1 AND pkey=$2"), | ||
139 | GNUNET_PQ_make_prepare ("iterate_zone", | ||
140 | "SELECT seq,record_count,record_data,label FROM namestore.ns098records " | ||
141 | "WHERE zone_private_key=$1 AND seq > $2 ORDER BY seq ASC LIMIT $3"), | ||
142 | GNUNET_PQ_make_prepare ("iterate_all_zones", | ||
143 | "SELECT seq,record_count,record_data,label,zone_private_key" | ||
144 | " FROM namestore.ns098records WHERE seq > $1 ORDER BY seq ASC LIMIT $2"), | ||
145 | GNUNET_PQ_make_prepare ("lookup_label", | ||
146 | "SELECT seq,record_count,record_data,label " | ||
147 | "FROM namestore.ns098records WHERE zone_private_key=$1 AND label=$2"), | ||
148 | GNUNET_PQ_make_prepare ("edit_set", | ||
149 | "SELECT seq,record_count,record_data,label " | ||
150 | "FROM namestore.ns098records WHERE zone_private_key=$1 AND label=$2 FOR UPDATE NOWAIT"), | ||
151 | GNUNET_PQ_PREPARED_STATEMENT_END | ||
152 | }; | ||
153 | |||
154 | ret = GNUNET_PQ_prepare_statements (plugin->dbh, | ||
155 | ps); | ||
156 | } | ||
157 | if (GNUNET_OK != ret) | ||
158 | return ret; | ||
159 | plugin->ready = true; | ||
160 | return GNUNET_OK; | ||
161 | } | ||
162 | |||
163 | |||
164 | /** | ||
165 | * Initialize the database connections and associated | ||
166 | * data structures (create tables and indices | ||
167 | * as needed as well). | ||
168 | * | ||
169 | * @param plugin the plugin context (state for this module) | ||
170 | * @return #GNUNET_OK on success | ||
171 | */ | ||
172 | static enum GNUNET_GenericReturnValue | ||
173 | database_connect (struct Plugin *plugin) | ||
174 | { | ||
175 | struct GNUNET_PQ_ExecuteStatement ess[] = { | ||
176 | GNUNET_PQ_make_try_execute ("SET synchronous_commit TO off"), | ||
177 | GNUNET_PQ_EXECUTE_STATEMENT_END | ||
178 | }; | ||
179 | struct GNUNET_PQ_ExecuteStatement *es; | ||
180 | |||
181 | if (GNUNET_YES == | ||
182 | GNUNET_CONFIGURATION_get_value_yesno (plugin->cfg, | ||
183 | "namestore-postgres", | ||
184 | "ASYNC_COMMIT")) | ||
185 | es = &ess[0]; | ||
186 | else | ||
187 | es = &ess[1]; | ||
188 | |||
189 | if (GNUNET_YES == | ||
190 | GNUNET_CONFIGURATION_get_value_yesno (plugin->cfg, | ||
191 | "namestore-postgres", | ||
192 | "INIT_ON_CONNECT")) | ||
193 | { | ||
194 | if (GNUNET_OK != | ||
195 | namestore_postgres_create_tables (plugin)) | ||
196 | { | ||
197 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
198 | "Failed to create tables\n"); | ||
199 | return GNUNET_SYSERR; | ||
200 | } | ||
201 | } | ||
202 | plugin->dbh = GNUNET_PQ_connect_with_cfg (plugin->cfg, | ||
203 | "namestore-postgres", | ||
204 | NULL, | ||
205 | es, | ||
206 | NULL); | ||
207 | if (NULL == plugin->dbh) | ||
208 | return GNUNET_SYSERR; | ||
209 | return GNUNET_OK; | ||
210 | } | ||
211 | |||
212 | |||
213 | /** | ||
214 | * Store a record in the datastore. Removes any existing record in the | ||
215 | * same zone with the same name. | ||
216 | * | ||
217 | * @param cls closure (internal context for the plugin) | ||
218 | * @param zone_key private key of the zone | ||
219 | * @param label name that is being mapped (at most 255 characters long) | ||
220 | * @param rd_count number of entries in @a rd array | ||
221 | * @param rd array of records with data to store | ||
222 | * @return #GNUNET_OK on success, else #GNUNET_SYSERR | ||
223 | */ | ||
224 | static enum GNUNET_GenericReturnValue | ||
225 | namestore_postgres_store_records (void *cls, | ||
226 | const struct | ||
227 | GNUNET_CRYPTO_PrivateKey *zone_key, | ||
228 | const char *label, | ||
229 | unsigned int rd_count, | ||
230 | const struct GNUNET_GNSRECORD_Data *rd) | ||
231 | { | ||
232 | struct Plugin *plugin = cls; | ||
233 | struct GNUNET_CRYPTO_PublicKey pkey; | ||
234 | uint64_t rvalue; | ||
235 | uint32_t rd_count32 = (uint32_t) rd_count; | ||
236 | ssize_t data_size; | ||
237 | |||
238 | GNUNET_assert (GNUNET_OK == database_prepare (plugin)); | ||
239 | memset (&pkey, | ||
240 | 0, | ||
241 | sizeof(pkey)); | ||
242 | for (unsigned int i = 0; i < rd_count; i++) | ||
243 | if (GNUNET_YES == | ||
244 | GNUNET_GNSRECORD_is_zonekey_type (rd[i].record_type)) | ||
245 | { | ||
246 | GNUNET_break (GNUNET_OK == | ||
247 | GNUNET_GNSRECORD_identity_from_data (rd[i].data, | ||
248 | rd[i].data_size, | ||
249 | rd[i].record_type, | ||
250 | &pkey)); | ||
251 | break; | ||
252 | } | ||
253 | rvalue = GNUNET_CRYPTO_random_u64 (GNUNET_CRYPTO_QUALITY_WEAK, | ||
254 | UINT64_MAX); | ||
255 | data_size = GNUNET_GNSRECORD_records_get_size (rd_count, | ||
256 | rd); | ||
257 | if (data_size < 0) | ||
258 | { | ||
259 | GNUNET_break (0); | ||
260 | return GNUNET_SYSERR; | ||
261 | } | ||
262 | if (data_size >= UINT16_MAX) | ||
263 | { | ||
264 | GNUNET_break (0); | ||
265 | return GNUNET_SYSERR; | ||
266 | } | ||
267 | /* if record set is empty, delete existing records */ | ||
268 | if (0 == rd_count) | ||
269 | { | ||
270 | struct GNUNET_PQ_QueryParam params[] = { | ||
271 | GNUNET_PQ_query_param_auto_from_type (zone_key), | ||
272 | GNUNET_PQ_query_param_string (label), | ||
273 | GNUNET_PQ_query_param_end | ||
274 | }; | ||
275 | enum GNUNET_DB_QueryStatus res; | ||
276 | |||
277 | res = GNUNET_PQ_eval_prepared_non_select (plugin->dbh, | ||
278 | "delete_records", | ||
279 | params); | ||
280 | if ((GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != res) && | ||
281 | (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS != res)) | ||
282 | { | ||
283 | GNUNET_break (0); | ||
284 | return GNUNET_SYSERR; | ||
285 | } | ||
286 | GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, | ||
287 | "postgres", | ||
288 | "Record deleted\n"); | ||
289 | return GNUNET_OK; | ||
290 | } | ||
291 | /* otherwise, UPSERT (i.e. UPDATE if exists, otherwise INSERT) */ | ||
292 | { | ||
293 | char data[data_size]; | ||
294 | struct GNUNET_PQ_QueryParam params[] = { | ||
295 | GNUNET_PQ_query_param_auto_from_type (zone_key), | ||
296 | GNUNET_PQ_query_param_auto_from_type (&pkey), | ||
297 | GNUNET_PQ_query_param_uint64 (&rvalue), | ||
298 | GNUNET_PQ_query_param_uint32 (&rd_count32), | ||
299 | GNUNET_PQ_query_param_fixed_size (data, data_size), | ||
300 | GNUNET_PQ_query_param_string (label), | ||
301 | GNUNET_PQ_query_param_end | ||
302 | }; | ||
303 | enum GNUNET_DB_QueryStatus res; | ||
304 | ssize_t ret; | ||
305 | |||
306 | ret = GNUNET_GNSRECORD_records_serialize (rd_count, | ||
307 | rd, | ||
308 | data_size, | ||
309 | data); | ||
310 | if ((ret < 0) || | ||
311 | (data_size != ret)) | ||
312 | { | ||
313 | GNUNET_break (0); | ||
314 | return GNUNET_SYSERR; | ||
315 | } | ||
316 | |||
317 | res = GNUNET_PQ_eval_prepared_non_select (plugin->dbh, | ||
318 | "store_records", | ||
319 | params); | ||
320 | if (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != res) | ||
321 | return GNUNET_SYSERR; | ||
322 | } | ||
323 | return GNUNET_OK; | ||
324 | } | ||
325 | |||
326 | |||
327 | /** | ||
328 | * Closure for #parse_result_call_iterator. | ||
329 | */ | ||
330 | struct ParserContext | ||
331 | { | ||
332 | /** | ||
333 | * Function to call for each result. | ||
334 | */ | ||
335 | GNUNET_NAMESTORE_RecordIterator iter; | ||
336 | |||
337 | /** | ||
338 | * Closure for @e iter. | ||
339 | */ | ||
340 | void *iter_cls; | ||
341 | |||
342 | /** | ||
343 | * Zone key, NULL if part of record. | ||
344 | */ | ||
345 | const struct GNUNET_CRYPTO_PrivateKey *zone_key; | ||
346 | |||
347 | /** | ||
348 | * Number of results still to return (counted down by | ||
349 | * number of results given to iterator). | ||
350 | */ | ||
351 | uint64_t limit; | ||
352 | }; | ||
353 | |||
354 | |||
355 | /** | ||
356 | * A statement has been run. We should evaluate the result, and if possible | ||
357 | * call the @a iter in @a cls with the result. | ||
358 | * | ||
359 | * @param cls closure of type `struct ParserContext *` | ||
360 | * @param res the postgres result | ||
361 | * @param num_results the number of results in @a result | ||
362 | */ | ||
363 | static void | ||
364 | parse_result_call_iterator (void *cls, | ||
365 | PGresult *res, | ||
366 | unsigned int num_results) | ||
367 | { | ||
368 | struct ParserContext *pc = cls; | ||
369 | |||
370 | if (NULL == pc->iter) | ||
371 | return; /* no need to do more work */ | ||
372 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
373 | "Got %d results from PQ.\n", num_results); | ||
374 | for (unsigned int i = 0; i < num_results; i++) | ||
375 | { | ||
376 | uint64_t serial; | ||
377 | void *data; | ||
378 | size_t data_size; | ||
379 | uint32_t record_count; | ||
380 | char *label; | ||
381 | struct GNUNET_CRYPTO_PrivateKey zk; | ||
382 | struct GNUNET_PQ_ResultSpec rs_with_zone[] = { | ||
383 | GNUNET_PQ_result_spec_uint64 ("seq", &serial), | ||
384 | GNUNET_PQ_result_spec_uint32 ("record_count", &record_count), | ||
385 | GNUNET_PQ_result_spec_variable_size ("record_data", &data, &data_size), | ||
386 | GNUNET_PQ_result_spec_string ("label", &label), | ||
387 | GNUNET_PQ_result_spec_auto_from_type ("zone_private_key", &zk), | ||
388 | GNUNET_PQ_result_spec_end | ||
389 | }; | ||
390 | struct GNUNET_PQ_ResultSpec rs_without_zone[] = { | ||
391 | GNUNET_PQ_result_spec_uint64 ("seq", &serial), | ||
392 | GNUNET_PQ_result_spec_uint32 ("record_count", &record_count), | ||
393 | GNUNET_PQ_result_spec_variable_size ("record_data", &data, &data_size), | ||
394 | GNUNET_PQ_result_spec_string ("label", &label), | ||
395 | GNUNET_PQ_result_spec_end | ||
396 | }; | ||
397 | struct GNUNET_PQ_ResultSpec *rs; | ||
398 | |||
399 | rs = (NULL == pc->zone_key) ? rs_with_zone : rs_without_zone; | ||
400 | if (GNUNET_YES != | ||
401 | GNUNET_PQ_extract_result (res, | ||
402 | rs, | ||
403 | i)) | ||
404 | { | ||
405 | GNUNET_break (0); | ||
406 | return; | ||
407 | } | ||
408 | |||
409 | if (record_count > 64 * 1024) | ||
410 | { | ||
411 | /* sanity check, don't stack allocate far too much just | ||
412 | because database might contain a large value here */ | ||
413 | GNUNET_break (0); | ||
414 | GNUNET_PQ_cleanup_result (rs); | ||
415 | return; | ||
416 | } | ||
417 | |||
418 | { | ||
419 | struct GNUNET_GNSRECORD_Data rd[GNUNET_NZL (record_count)]; | ||
420 | |||
421 | GNUNET_assert (0 != serial); | ||
422 | if (GNUNET_OK != | ||
423 | GNUNET_GNSRECORD_records_deserialize (data_size, | ||
424 | data, | ||
425 | record_count, | ||
426 | rd)) | ||
427 | { | ||
428 | GNUNET_break (0); | ||
429 | GNUNET_PQ_cleanup_result (rs); | ||
430 | return; | ||
431 | } | ||
432 | pc->iter (pc->iter_cls, | ||
433 | serial, | ||
434 | (NULL == pc->zone_key) ? &zk : pc->zone_key, | ||
435 | label, | ||
436 | record_count, | ||
437 | rd); | ||
438 | } | ||
439 | GNUNET_PQ_cleanup_result (rs); | ||
440 | } | ||
441 | pc->limit -= num_results; | ||
442 | } | ||
443 | |||
444 | |||
445 | /** | ||
446 | * Lookup records in the datastore for which we are the authority. | ||
447 | * | ||
448 | * @param cls closure (internal context for the plugin) | ||
449 | * @param zone private key of the zone | ||
450 | * @param label name of the record in the zone | ||
451 | * @param iter function to call with the result | ||
452 | * @param iter_cls closure for @a iter | ||
453 | * @param method the method to use "lookup_record" or "edit_set" | ||
454 | * @return #GNUNET_OK on success, #GNUNET_NO for no results, else #GNUNET_SYSERR | ||
455 | */ | ||
456 | static enum GNUNET_GenericReturnValue | ||
457 | lookup_records (void *cls, | ||
458 | const struct | ||
459 | GNUNET_CRYPTO_PrivateKey *zone, | ||
460 | const char *label, | ||
461 | GNUNET_NAMESTORE_RecordIterator iter, | ||
462 | void *iter_cls, | ||
463 | const char*method) | ||
464 | { | ||
465 | struct Plugin *plugin = cls; | ||
466 | GNUNET_assert (GNUNET_OK == database_prepare (plugin)); | ||
467 | struct GNUNET_PQ_QueryParam params[] = { | ||
468 | GNUNET_PQ_query_param_auto_from_type (zone), | ||
469 | GNUNET_PQ_query_param_string (label), | ||
470 | GNUNET_PQ_query_param_end | ||
471 | }; | ||
472 | struct ParserContext pc; | ||
473 | enum GNUNET_DB_QueryStatus res; | ||
474 | |||
475 | if (NULL == zone) | ||
476 | { | ||
477 | GNUNET_break (0); | ||
478 | return GNUNET_SYSERR; | ||
479 | } | ||
480 | pc.iter = iter; | ||
481 | pc.iter_cls = iter_cls; | ||
482 | pc.zone_key = zone; | ||
483 | res = GNUNET_PQ_eval_prepared_multi_select (plugin->dbh, | ||
484 | method, | ||
485 | params, | ||
486 | &parse_result_call_iterator, | ||
487 | &pc); | ||
488 | if (res < 0) | ||
489 | return GNUNET_SYSERR; | ||
490 | if (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS == res) | ||
491 | return GNUNET_NO; | ||
492 | return GNUNET_OK; | ||
493 | } | ||
494 | |||
495 | |||
496 | /** | ||
497 | * Lookup records in the datastore for which we are the authority. | ||
498 | * | ||
499 | * @param cls closure (internal context for the plugin) | ||
500 | * @param zone private key of the zone | ||
501 | * @param label name of the record in the zone | ||
502 | * @param iter function to call with the result | ||
503 | * @param iter_cls closure for @a iter | ||
504 | * @return #GNUNET_OK on success, #GNUNET_NO for no results, else #GNUNET_SYSERR | ||
505 | */ | ||
506 | static enum GNUNET_GenericReturnValue | ||
507 | namestore_postgres_lookup_records (void *cls, | ||
508 | const struct | ||
509 | GNUNET_CRYPTO_PrivateKey *zone, | ||
510 | const char *label, | ||
511 | GNUNET_NAMESTORE_RecordIterator iter, | ||
512 | void *iter_cls) | ||
513 | { | ||
514 | return lookup_records (cls, zone, label, iter, iter_cls, "lookup_label"); | ||
515 | } | ||
516 | |||
517 | |||
518 | /** | ||
519 | * Edit records in the datastore for which we are the authority. | ||
520 | * | ||
521 | * @param cls closure (internal context for the plugin) | ||
522 | * @param zone private key of the zone | ||
523 | * @param label name of the record in the zone | ||
524 | * @param iter function to call with the result | ||
525 | * @param iter_cls closure for @a iter | ||
526 | * @return #GNUNET_OK on success, #GNUNET_NO for no results, else #GNUNET_SYSERR | ||
527 | */ | ||
528 | static int | ||
529 | namestore_postgres_edit_records (void *cls, | ||
530 | const struct | ||
531 | GNUNET_CRYPTO_PrivateKey *zone, | ||
532 | const char *label, | ||
533 | GNUNET_NAMESTORE_RecordIterator iter, | ||
534 | void *iter_cls) | ||
535 | { | ||
536 | return lookup_records (cls, zone, label, iter, iter_cls, "edit_set"); | ||
537 | } | ||
538 | |||
539 | |||
540 | /** | ||
541 | * Iterate over the results for a particular key and zone in the | ||
542 | * datastore. Will return at most one result to the iterator. | ||
543 | * | ||
544 | * @param cls closure (internal context for the plugin) | ||
545 | * @param zone hash of public key of the zone, NULL to iterate over all zones | ||
546 | * @param serial serial number to exclude in the list of all matching records | ||
547 | * @param limit maximum number of results to fetch | ||
548 | * @param iter function to call with the result | ||
549 | * @param iter_cls closure for @a iter | ||
550 | * @return #GNUNET_OK on success, #GNUNET_NO if there were no more results, #GNUNET_SYSERR on error | ||
551 | */ | ||
552 | static enum GNUNET_GenericReturnValue | ||
553 | namestore_postgres_iterate_records (void *cls, | ||
554 | const struct | ||
555 | GNUNET_CRYPTO_PrivateKey *zone, | ||
556 | uint64_t serial, | ||
557 | uint64_t limit, | ||
558 | GNUNET_NAMESTORE_RecordIterator iter, | ||
559 | void *iter_cls) | ||
560 | { | ||
561 | struct Plugin *plugin = cls; | ||
562 | enum GNUNET_DB_QueryStatus res; | ||
563 | struct ParserContext pc; | ||
564 | |||
565 | GNUNET_assert (GNUNET_OK == database_prepare (plugin)); | ||
566 | pc.iter = iter; | ||
567 | pc.iter_cls = iter_cls; | ||
568 | pc.zone_key = zone; | ||
569 | pc.limit = limit; | ||
570 | if (NULL == zone) | ||
571 | { | ||
572 | struct GNUNET_PQ_QueryParam params_without_zone[] = { | ||
573 | GNUNET_PQ_query_param_uint64 (&serial), | ||
574 | GNUNET_PQ_query_param_uint64 (&limit), | ||
575 | GNUNET_PQ_query_param_end | ||
576 | }; | ||
577 | |||
578 | res = GNUNET_PQ_eval_prepared_multi_select (plugin->dbh, | ||
579 | "iterate_all_zones", | ||
580 | params_without_zone, | ||
581 | &parse_result_call_iterator, | ||
582 | &pc); | ||
583 | } | ||
584 | else | ||
585 | { | ||
586 | struct GNUNET_PQ_QueryParam params_with_zone[] = { | ||
587 | GNUNET_PQ_query_param_auto_from_type (zone), | ||
588 | GNUNET_PQ_query_param_uint64 (&serial), | ||
589 | GNUNET_PQ_query_param_uint64 (&limit), | ||
590 | GNUNET_PQ_query_param_end | ||
591 | }; | ||
592 | |||
593 | res = GNUNET_PQ_eval_prepared_multi_select (plugin->dbh, | ||
594 | "iterate_zone", | ||
595 | params_with_zone, | ||
596 | &parse_result_call_iterator, | ||
597 | &pc); | ||
598 | } | ||
599 | if (res < 0) | ||
600 | return GNUNET_SYSERR; | ||
601 | |||
602 | if ((GNUNET_DB_STATUS_SUCCESS_NO_RESULTS == res) || | ||
603 | (pc.limit > 0)) | ||
604 | return GNUNET_NO; | ||
605 | return GNUNET_OK; | ||
606 | } | ||
607 | |||
608 | |||
609 | /** | ||
610 | * Look for an existing PKEY delegation record for a given public key. | ||
611 | * Returns at most one result to the iterator. | ||
612 | * | ||
613 | * @param cls closure (internal context for the plugin) | ||
614 | * @param zone private key of the zone to look up in, never NULL | ||
615 | * @param value_zone public key of the target zone (value), never NULL | ||
616 | * @param iter function to call with the result | ||
617 | * @param iter_cls closure for @a iter | ||
618 | * @return #GNUNET_OK on success, #GNUNET_NO if there were no results, #GNUNET_SYSERR on error | ||
619 | */ | ||
620 | static enum GNUNET_GenericReturnValue | ||
621 | namestore_postgres_zone_to_name (void *cls, | ||
622 | const struct | ||
623 | GNUNET_CRYPTO_PrivateKey *zone, | ||
624 | const struct | ||
625 | GNUNET_CRYPTO_PublicKey *value_zone, | ||
626 | GNUNET_NAMESTORE_RecordIterator iter, | ||
627 | void *iter_cls) | ||
628 | { | ||
629 | struct Plugin *plugin = cls; | ||
630 | GNUNET_assert (GNUNET_OK == database_prepare (plugin)); | ||
631 | struct GNUNET_PQ_QueryParam params[] = { | ||
632 | GNUNET_PQ_query_param_auto_from_type (zone), | ||
633 | GNUNET_PQ_query_param_auto_from_type (value_zone), | ||
634 | GNUNET_PQ_query_param_end | ||
635 | }; | ||
636 | enum GNUNET_DB_QueryStatus res; | ||
637 | struct ParserContext pc; | ||
638 | |||
639 | pc.iter = iter; | ||
640 | pc.iter_cls = iter_cls; | ||
641 | pc.zone_key = zone; | ||
642 | res = GNUNET_PQ_eval_prepared_multi_select (plugin->dbh, | ||
643 | "zone_to_name", | ||
644 | params, | ||
645 | &parse_result_call_iterator, | ||
646 | &pc); | ||
647 | if (res < 0) | ||
648 | return GNUNET_SYSERR; | ||
649 | return GNUNET_OK; | ||
650 | } | ||
651 | |||
652 | |||
653 | /** | ||
654 | * Begin a transaction for a client. | ||
655 | * | ||
656 | * @param cls closure (internal context for the plugin) | ||
657 | * @param emsg error message set of return code is #GNUNET_SYSERR | ||
658 | * @return #GNUNET_YES on success, #GNUNET_SYSERR if transaction cannot be started. | ||
659 | */ | ||
660 | static enum GNUNET_GenericReturnValue | ||
661 | namestore_postgres_transaction_begin (void *cls, | ||
662 | char **emsg) | ||
663 | { | ||
664 | struct Plugin *plugin = cls; | ||
665 | GNUNET_assert (GNUNET_OK == database_prepare (plugin)); | ||
666 | struct GNUNET_PQ_ExecuteStatement es[] = { | ||
667 | GNUNET_PQ_make_execute ("BEGIN"), | ||
668 | GNUNET_PQ_EXECUTE_STATEMENT_END | ||
669 | }; | ||
670 | |||
671 | return GNUNET_PQ_exec_statements (plugin->dbh, es); | ||
672 | } | ||
673 | |||
674 | |||
675 | /** | ||
676 | * Commit a transaction for a client. | ||
677 | * This releases the lock on the database. | ||
678 | * | ||
679 | * @param cls closure (internal context for the plugin) | ||
680 | * @param emsg error message set of return code is #GNUNET_SYSERR | ||
681 | * @return #GNUNET_YES on success, #GNUNET_SYSERR if transaction cannot be started. | ||
682 | */ | ||
683 | static enum GNUNET_GenericReturnValue | ||
684 | namestore_postgres_transaction_rollback (void *cls, | ||
685 | char **emsg) | ||
686 | { | ||
687 | struct Plugin *plugin = cls; | ||
688 | GNUNET_assert (GNUNET_OK == database_prepare (plugin)); | ||
689 | struct GNUNET_PQ_ExecuteStatement es[] = { | ||
690 | GNUNET_PQ_make_execute ("ROLLBACK"), | ||
691 | GNUNET_PQ_EXECUTE_STATEMENT_END | ||
692 | }; | ||
693 | |||
694 | return GNUNET_PQ_exec_statements (plugin->dbh, es); | ||
695 | } | ||
696 | |||
697 | |||
698 | /** | ||
699 | * Roll back a transaction for a client. | ||
700 | * This releases the lock on the database. | ||
701 | * | ||
702 | * @param cls closure (internal context for the plugin) | ||
703 | * @param emsg error message set of return code is #GNUNET_SYSERR | ||
704 | * @return #GNUNET_YES on success, #GNUNET_SYSERR if transaction cannot be started. | ||
705 | */ | ||
706 | static enum GNUNET_GenericReturnValue | ||
707 | namestore_postgres_transaction_commit (void *cls, | ||
708 | char **emsg) | ||
709 | { | ||
710 | struct Plugin *plugin = cls; | ||
711 | GNUNET_assert (GNUNET_OK == database_prepare (plugin)); | ||
712 | struct GNUNET_PQ_ExecuteStatement es[] = { | ||
713 | GNUNET_PQ_make_execute ("COMMIT"), | ||
714 | GNUNET_PQ_EXECUTE_STATEMENT_END | ||
715 | }; | ||
716 | |||
717 | return GNUNET_PQ_exec_statements (plugin->dbh, es); | ||
718 | } | ||
719 | |||
720 | |||
721 | /** | ||
722 | * Shutdown database connection and associate data | ||
723 | * structures. | ||
724 | * | ||
725 | * @param plugin the plugin context (state for this module) | ||
726 | */ | ||
727 | static void | ||
728 | database_shutdown (struct Plugin *plugin) | ||
729 | { | ||
730 | GNUNET_PQ_disconnect (plugin->dbh); | ||
731 | plugin->dbh = NULL; | ||
732 | } | ||
733 | |||
734 | |||
735 | /** | ||
736 | * Entry point for the plugin. | ||
737 | * | ||
738 | * @param cls the `struct GNUNET_NAMESTORE_PluginEnvironment*` | ||
739 | * @return NULL on error, othrewise the plugin context | ||
740 | */ | ||
741 | void * | ||
742 | libgnunet_plugin_namestore_postgres_init (void *cls) | ||
743 | { | ||
744 | struct Plugin *plugin; | ||
745 | const struct GNUNET_CONFIGURATION_Handle *cfg = cls; | ||
746 | struct GNUNET_NAMESTORE_PluginFunctions *api; | ||
747 | |||
748 | plugin = GNUNET_new (struct Plugin); | ||
749 | plugin->cfg = cfg; | ||
750 | if (GNUNET_OK != database_connect (plugin)) | ||
751 | { | ||
752 | database_shutdown (plugin); | ||
753 | GNUNET_free (plugin); | ||
754 | return NULL; | ||
755 | } | ||
756 | api = GNUNET_new (struct GNUNET_NAMESTORE_PluginFunctions); | ||
757 | api->cls = plugin; | ||
758 | api->create_tables = &namestore_postgres_create_tables; | ||
759 | api->drop_tables = &namestore_postgres_drop_tables; | ||
760 | api->store_records = &namestore_postgres_store_records; | ||
761 | api->iterate_records = &namestore_postgres_iterate_records; | ||
762 | api->zone_to_name = &namestore_postgres_zone_to_name; | ||
763 | api->lookup_records = &namestore_postgres_lookup_records; | ||
764 | api->transaction_begin = &namestore_postgres_transaction_begin; | ||
765 | api->transaction_commit = &namestore_postgres_transaction_commit; | ||
766 | api->transaction_rollback = &namestore_postgres_transaction_rollback; | ||
767 | api->edit_records = &namestore_postgres_edit_records; | ||
768 | LOG (GNUNET_ERROR_TYPE_INFO, | ||
769 | "Postgres namestore plugin running\n"); | ||
770 | return api; | ||
771 | } | ||
772 | |||
773 | |||
774 | /** | ||
775 | * Exit point from the plugin. | ||
776 | * | ||
777 | * @param cls the plugin context (as returned by "init") | ||
778 | * @return always NULL | ||
779 | */ | ||
780 | void * | ||
781 | libgnunet_plugin_namestore_postgres_done (void *cls) | ||
782 | { | ||
783 | struct GNUNET_NAMESTORE_PluginFunctions *api = cls; | ||
784 | struct Plugin *plugin = api->cls; | ||
785 | |||
786 | database_shutdown (plugin); | ||
787 | plugin->cfg = NULL; | ||
788 | GNUNET_free (plugin); | ||
789 | GNUNET_free (api); | ||
790 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
791 | "Postgres namestore plugin is finished\n"); | ||
792 | return NULL; | ||
793 | } | ||
794 | |||
795 | |||
796 | /* 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 d66271ffa..000000000 --- a/src/namestore/plugin_namestore_sqlite.c +++ /dev/null | |||
@@ -1,983 +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 { \ | ||
54 | GNUNET_log_from (level, \ | ||
55 | "namestore-sqlite", _ ( \ | ||
56 | "`%s' failed at %s:%d with error: %s\n"), \ | ||
57 | cmd, \ | ||
58 | __FILE__, __LINE__, \ | ||
59 | sqlite3_errmsg ( \ | ||
60 | db->dbh)); \ | ||
61 | } while (0) | ||
62 | |||
63 | #define LOG(kind, ...) GNUNET_log_from (kind, "namestore-sqlite", __VA_ARGS__) | ||
64 | |||
65 | |||
66 | /** | ||
67 | * Context for all functions in this plugin. | ||
68 | */ | ||
69 | struct Plugin | ||
70 | { | ||
71 | const struct GNUNET_CONFIGURATION_Handle *cfg; | ||
72 | |||
73 | /** | ||
74 | * Database filename. | ||
75 | */ | ||
76 | char *fn; | ||
77 | |||
78 | /** | ||
79 | * Statements prepared, we are ready to go if true. | ||
80 | */ | ||
81 | bool ready; | ||
82 | |||
83 | /** | ||
84 | * Native SQLite database handle. | ||
85 | */ | ||
86 | sqlite3 *dbh; | ||
87 | |||
88 | /** | ||
89 | * Precompiled SQL to store records. | ||
90 | */ | ||
91 | sqlite3_stmt *store_records; | ||
92 | |||
93 | /** | ||
94 | * Precompiled SQL to deltete existing records. | ||
95 | */ | ||
96 | sqlite3_stmt *delete_records; | ||
97 | |||
98 | /** | ||
99 | * Precompiled SQL for iterate records within a zone. | ||
100 | */ | ||
101 | sqlite3_stmt *iterate_zone; | ||
102 | |||
103 | /** | ||
104 | * Precompiled SQL for iterate all records within all zones. | ||
105 | */ | ||
106 | sqlite3_stmt *iterate_all_zones; | ||
107 | |||
108 | /** | ||
109 | * Precompiled SQL to for reverse lookup based on PKEY. | ||
110 | */ | ||
111 | sqlite3_stmt *zone_to_name; | ||
112 | |||
113 | /** | ||
114 | * Precompiled SQL to lookup records based on label. | ||
115 | */ | ||
116 | sqlite3_stmt *lookup_label; | ||
117 | }; | ||
118 | |||
119 | |||
120 | /** | ||
121 | * Initialize the database connections and associated | ||
122 | * data structures (create tables and indices | ||
123 | * as needed as well). | ||
124 | * | ||
125 | * @param plugin the plugin context (state for this module) | ||
126 | * @return #GNUNET_OK on success | ||
127 | */ | ||
128 | static enum GNUNET_GenericReturnValue | ||
129 | database_prepare (struct Plugin *plugin) | ||
130 | { | ||
131 | if (plugin->ready) | ||
132 | return GNUNET_OK; | ||
133 | struct GNUNET_SQ_ExecuteStatement es[] = { | ||
134 | GNUNET_SQ_make_try_execute ("PRAGMA temp_store=MEMORY"), | ||
135 | GNUNET_SQ_make_try_execute ("PRAGMA synchronous=NORMAL"), | ||
136 | GNUNET_SQ_make_try_execute ("PRAGMA legacy_file_format=OFF"), | ||
137 | GNUNET_SQ_make_try_execute ("PRAGMA auto_vacuum=INCREMENTAL"), | ||
138 | GNUNET_SQ_make_try_execute ("PRAGMA encoding=\"UTF-8\""), | ||
139 | GNUNET_SQ_make_try_execute ("PRAGMA locking_mode=NORMAL"), | ||
140 | GNUNET_SQ_make_try_execute ("PRAGMA journal_mode=WAL"), | ||
141 | GNUNET_SQ_make_try_execute ("PRAGMA page_size=4092"), | ||
142 | GNUNET_SQ_EXECUTE_STATEMENT_END | ||
143 | }; | ||
144 | struct GNUNET_SQ_PrepareStatement ps[] = { | ||
145 | GNUNET_SQ_make_prepare ("INSERT INTO ns098records " | ||
146 | "(zone_private_key,pkey,rvalue,record_count,record_data,label)" | ||
147 | " VALUES (?, ?, ?, ?, ?, ?)", | ||
148 | &plugin->store_records), | ||
149 | GNUNET_SQ_make_prepare ("DELETE FROM ns098records " | ||
150 | "WHERE zone_private_key=? AND label=?", | ||
151 | &plugin->delete_records), | ||
152 | GNUNET_SQ_make_prepare ("SELECT uid,record_count,record_data,label" | ||
153 | " FROM ns098records" | ||
154 | " WHERE zone_private_key=? AND pkey=?", | ||
155 | &plugin->zone_to_name), | ||
156 | GNUNET_SQ_make_prepare ("SELECT uid,record_count,record_data,label" | ||
157 | " FROM ns098records" | ||
158 | " WHERE zone_private_key=? AND uid > ?" | ||
159 | " ORDER BY uid ASC" | ||
160 | " LIMIT ?", | ||
161 | &plugin->iterate_zone), | ||
162 | GNUNET_SQ_make_prepare ( | ||
163 | "SELECT uid,record_count,record_data,label,zone_private_key" | ||
164 | " FROM ns098records" | ||
165 | " WHERE uid > ?" | ||
166 | " ORDER BY uid ASC" | ||
167 | " LIMIT ?", | ||
168 | &plugin->iterate_all_zones), | ||
169 | GNUNET_SQ_make_prepare ("SELECT uid,record_count,record_data,label" | ||
170 | " FROM ns098records" | ||
171 | " WHERE zone_private_key=? AND label=?", | ||
172 | &plugin->lookup_label), | ||
173 | GNUNET_SQ_PREPARE_END | ||
174 | }; | ||
175 | |||
176 | if (GNUNET_OK != | ||
177 | GNUNET_SQ_exec_statements (plugin->dbh, | ||
178 | es)) | ||
179 | { | ||
180 | LOG (GNUNET_ERROR_TYPE_ERROR, | ||
181 | _ ("Failed to setup database with: `%s'\n"), | ||
182 | sqlite3_errmsg (plugin->dbh)); | ||
183 | return GNUNET_SYSERR; | ||
184 | } | ||
185 | if (GNUNET_OK != | ||
186 | GNUNET_SQ_prepare (plugin->dbh, | ||
187 | ps)) | ||
188 | { | ||
189 | GNUNET_break (0); | ||
190 | LOG (GNUNET_ERROR_TYPE_ERROR, | ||
191 | _ ("Failed to setup database with: `%s'\n"), | ||
192 | sqlite3_errmsg (plugin->dbh)); | ||
193 | return GNUNET_SYSERR; | ||
194 | } | ||
195 | plugin->ready = GNUNET_YES; | ||
196 | return GNUNET_OK; | ||
197 | } | ||
198 | |||
199 | |||
200 | /** | ||
201 | * Shutdown database connection and associate data | ||
202 | * structures. | ||
203 | * @param plugin the plugin context (state for this module) | ||
204 | */ | ||
205 | static void | ||
206 | database_shutdown (struct Plugin *plugin) | ||
207 | { | ||
208 | int result; | ||
209 | sqlite3_stmt *stmt; | ||
210 | |||
211 | if (NULL != plugin->store_records) | ||
212 | sqlite3_finalize (plugin->store_records); | ||
213 | if (NULL != plugin->delete_records) | ||
214 | sqlite3_finalize (plugin->delete_records); | ||
215 | if (NULL != plugin->iterate_zone) | ||
216 | sqlite3_finalize (plugin->iterate_zone); | ||
217 | if (NULL != plugin->iterate_all_zones) | ||
218 | sqlite3_finalize (plugin->iterate_all_zones); | ||
219 | if (NULL != plugin->zone_to_name) | ||
220 | sqlite3_finalize (plugin->zone_to_name); | ||
221 | if (NULL != plugin->lookup_label) | ||
222 | sqlite3_finalize (plugin->lookup_label); | ||
223 | result = sqlite3_close (plugin->dbh); | ||
224 | if (result == SQLITE_BUSY) | ||
225 | { | ||
226 | LOG (GNUNET_ERROR_TYPE_WARNING, | ||
227 | _ ( | ||
228 | "Tried to close sqlite without finalizing all prepared statements.\n")); | ||
229 | stmt = sqlite3_next_stmt (plugin->dbh, | ||
230 | NULL); | ||
231 | while (NULL != stmt) | ||
232 | { | ||
233 | GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, | ||
234 | "sqlite", | ||
235 | "Closing statement %p\n", | ||
236 | stmt); | ||
237 | result = sqlite3_finalize (stmt); | ||
238 | if (result != SQLITE_OK) | ||
239 | GNUNET_log_from (GNUNET_ERROR_TYPE_WARNING, | ||
240 | "sqlite", | ||
241 | "Failed to close statement %p: %d\n", | ||
242 | stmt, | ||
243 | result); | ||
244 | stmt = sqlite3_next_stmt (plugin->dbh, | ||
245 | NULL); | ||
246 | } | ||
247 | result = sqlite3_close (plugin->dbh); | ||
248 | } | ||
249 | if (SQLITE_OK != result) | ||
250 | LOG_SQLITE (plugin, | ||
251 | GNUNET_ERROR_TYPE_ERROR, | ||
252 | "sqlite3_close"); | ||
253 | |||
254 | } | ||
255 | |||
256 | |||
257 | /** | ||
258 | * Store a record in the datastore. Removes any existing record in the | ||
259 | * same zone with the same name. | ||
260 | * | ||
261 | * @param cls closure (internal context for the plugin) | ||
262 | * @param zone_key private key of the zone | ||
263 | * @param label name that is being mapped (at most 255 characters long) | ||
264 | * @param rd_count number of entries in @a rd array | ||
265 | * @param rd array of records with data to store | ||
266 | * @return #GNUNET_OK on success, else #GNUNET_SYSERR | ||
267 | */ | ||
268 | static enum GNUNET_GenericReturnValue | ||
269 | namestore_sqlite_store_records (void *cls, | ||
270 | const struct | ||
271 | GNUNET_CRYPTO_PrivateKey *zone_key, | ||
272 | const char *label, | ||
273 | unsigned int rd_count, | ||
274 | const struct GNUNET_GNSRECORD_Data *rd) | ||
275 | { | ||
276 | struct Plugin *plugin = cls; | ||
277 | int n; | ||
278 | struct GNUNET_CRYPTO_PublicKey pkey; | ||
279 | uint64_t rvalue; | ||
280 | ssize_t data_size; | ||
281 | |||
282 | GNUNET_assert (GNUNET_OK == database_prepare (plugin)); | ||
283 | memset (&pkey, | ||
284 | 0, | ||
285 | sizeof(pkey)); | ||
286 | for (unsigned int i = 0; i < rd_count; i++) | ||
287 | { | ||
288 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
289 | "Checking if `%d' is zonekey type\n", | ||
290 | rd[i].record_type); | ||
291 | |||
292 | if (GNUNET_YES == GNUNET_GNSRECORD_is_zonekey_type (rd[i].record_type)) | ||
293 | { | ||
294 | GNUNET_break (GNUNET_YES == | ||
295 | GNUNET_GNSRECORD_identity_from_data (rd[i].data, | ||
296 | rd[i].data_size, | ||
297 | rd[i].record_type, | ||
298 | &pkey)); | ||
299 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
300 | "Storing delegation zone record value `%s'\n", | ||
301 | GNUNET_GNSRECORD_z2s (&pkey)); | ||
302 | |||
303 | break; | ||
304 | } | ||
305 | } | ||
306 | rvalue = GNUNET_CRYPTO_random_u64 (GNUNET_CRYPTO_QUALITY_WEAK, | ||
307 | UINT64_MAX); | ||
308 | data_size = GNUNET_GNSRECORD_records_get_size (rd_count, | ||
309 | rd); | ||
310 | if (data_size < 0) | ||
311 | { | ||
312 | GNUNET_break (0); | ||
313 | return GNUNET_SYSERR; | ||
314 | } | ||
315 | if (data_size > 64 * 65536) | ||
316 | { | ||
317 | GNUNET_break (0); | ||
318 | return GNUNET_SYSERR; | ||
319 | } | ||
320 | { | ||
321 | /* First delete 'old' records */ | ||
322 | char data[data_size]; | ||
323 | struct GNUNET_SQ_QueryParam dparams[] = { | ||
324 | GNUNET_SQ_query_param_auto_from_type (zone_key), | ||
325 | GNUNET_SQ_query_param_string (label), | ||
326 | GNUNET_SQ_query_param_end | ||
327 | }; | ||
328 | ssize_t ret; | ||
329 | |||
330 | ret = GNUNET_GNSRECORD_records_serialize (rd_count, | ||
331 | rd, | ||
332 | data_size, | ||
333 | data); | ||
334 | if ((ret < 0) || | ||
335 | (data_size != ret)) | ||
336 | { | ||
337 | GNUNET_break (0); | ||
338 | return GNUNET_SYSERR; | ||
339 | } | ||
340 | if (GNUNET_OK != | ||
341 | GNUNET_SQ_bind (plugin->delete_records, | ||
342 | dparams)) | ||
343 | { | ||
344 | LOG_SQLITE (plugin, | ||
345 | GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, | ||
346 | "sqlite3_bind_XXXX"); | ||
347 | GNUNET_SQ_reset (plugin->dbh, | ||
348 | plugin->delete_records); | ||
349 | return GNUNET_SYSERR; | ||
350 | } | ||
351 | n = sqlite3_step (plugin->delete_records); | ||
352 | GNUNET_SQ_reset (plugin->dbh, | ||
353 | plugin->delete_records); | ||
354 | |||
355 | if (0 != rd_count) | ||
356 | { | ||
357 | uint32_t rd_count32 = (uint32_t) rd_count; | ||
358 | struct GNUNET_SQ_QueryParam sparams[] = { | ||
359 | GNUNET_SQ_query_param_auto_from_type (zone_key), | ||
360 | GNUNET_SQ_query_param_auto_from_type (&pkey), | ||
361 | GNUNET_SQ_query_param_uint64 (&rvalue), | ||
362 | GNUNET_SQ_query_param_uint32 (&rd_count32), | ||
363 | GNUNET_SQ_query_param_fixed_size (data, data_size), | ||
364 | GNUNET_SQ_query_param_string (label), | ||
365 | GNUNET_SQ_query_param_end | ||
366 | }; | ||
367 | |||
368 | if (GNUNET_OK != | ||
369 | GNUNET_SQ_bind (plugin->store_records, | ||
370 | sparams)) | ||
371 | { | ||
372 | LOG_SQLITE (plugin, | ||
373 | GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, | ||
374 | "sqlite3_bind_XXXX"); | ||
375 | GNUNET_SQ_reset (plugin->dbh, | ||
376 | plugin->store_records); | ||
377 | return GNUNET_SYSERR; | ||
378 | } | ||
379 | n = sqlite3_step (plugin->store_records); | ||
380 | GNUNET_SQ_reset (plugin->dbh, | ||
381 | plugin->store_records); | ||
382 | } | ||
383 | } | ||
384 | switch (n) | ||
385 | { | ||
386 | case SQLITE_DONE: | ||
387 | if (0 != rd_count) | ||
388 | GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, | ||
389 | "sqlite", | ||
390 | "Record stored\n"); | ||
391 | else | ||
392 | GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, | ||
393 | "sqlite", | ||
394 | "Record deleted\n"); | ||
395 | return GNUNET_OK; | ||
396 | |||
397 | case SQLITE_BUSY: | ||
398 | LOG_SQLITE (plugin, | ||
399 | GNUNET_ERROR_TYPE_WARNING | GNUNET_ERROR_TYPE_BULK, | ||
400 | "sqlite3_step"); | ||
401 | return GNUNET_NO; | ||
402 | |||
403 | default: | ||
404 | LOG_SQLITE (plugin, | ||
405 | GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, | ||
406 | "sqlite3_step"); | ||
407 | return GNUNET_SYSERR; | ||
408 | } | ||
409 | } | ||
410 | |||
411 | |||
412 | /** | ||
413 | * The given 'sqlite' statement has been prepared to be run. | ||
414 | * It will return a record which should be given to the iterator. | ||
415 | * Runs the statement and parses the returned record. | ||
416 | * | ||
417 | * @param plugin plugin context | ||
418 | * @param stmt to run (and then clean up) | ||
419 | * @param zone_key private key of the zone | ||
420 | * @param limit maximum number of results to fetch | ||
421 | * @param iter iterator to call with the result | ||
422 | * @param iter_cls closure for @a iter | ||
423 | * @return #GNUNET_OK on success, #GNUNET_NO if there were no results, #GNUNET_SYSERR on error | ||
424 | */ | ||
425 | static enum GNUNET_GenericReturnValue | ||
426 | get_records_and_call_iterator (struct Plugin *plugin, | ||
427 | sqlite3_stmt *stmt, | ||
428 | const struct | ||
429 | GNUNET_CRYPTO_PrivateKey *zone_key, | ||
430 | uint64_t limit, | ||
431 | GNUNET_NAMESTORE_RecordIterator iter, | ||
432 | void *iter_cls) | ||
433 | { | ||
434 | int ret; | ||
435 | int sret; | ||
436 | |||
437 | ret = GNUNET_OK; | ||
438 | for (uint64_t i = 0; i < limit; i++) | ||
439 | { | ||
440 | sret = sqlite3_step (stmt); | ||
441 | |||
442 | if (SQLITE_DONE == sret) | ||
443 | { | ||
444 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
445 | "Iteration done (no results)\n"); | ||
446 | ret = GNUNET_NO; | ||
447 | break; | ||
448 | } | ||
449 | if (SQLITE_ROW != sret) | ||
450 | { | ||
451 | LOG_SQLITE (plugin, | ||
452 | GNUNET_ERROR_TYPE_ERROR, | ||
453 | "sqlite_step"); | ||
454 | ret = GNUNET_SYSERR; | ||
455 | break; | ||
456 | } | ||
457 | |||
458 | { | ||
459 | uint64_t seq; | ||
460 | uint32_t record_count; | ||
461 | size_t data_size; | ||
462 | void *data; | ||
463 | char *label; | ||
464 | struct GNUNET_CRYPTO_PrivateKey zk; | ||
465 | struct GNUNET_SQ_ResultSpec rs[] = { | ||
466 | GNUNET_SQ_result_spec_uint64 (&seq), | ||
467 | GNUNET_SQ_result_spec_uint32 (&record_count), | ||
468 | GNUNET_SQ_result_spec_variable_size (&data, | ||
469 | &data_size), | ||
470 | GNUNET_SQ_result_spec_string (&label), | ||
471 | GNUNET_SQ_result_spec_end | ||
472 | }; | ||
473 | struct GNUNET_SQ_ResultSpec rsx[] = { | ||
474 | GNUNET_SQ_result_spec_uint64 (&seq), | ||
475 | GNUNET_SQ_result_spec_uint32 (&record_count), | ||
476 | GNUNET_SQ_result_spec_variable_size (&data, | ||
477 | &data_size), | ||
478 | GNUNET_SQ_result_spec_string (&label), | ||
479 | GNUNET_SQ_result_spec_auto_from_type (&zk), | ||
480 | GNUNET_SQ_result_spec_end | ||
481 | }; | ||
482 | |||
483 | ret = GNUNET_SQ_extract_result (stmt, | ||
484 | (NULL == zone_key) | ||
485 | ? rsx | ||
486 | : rs); | ||
487 | if ((GNUNET_OK != ret) || | ||
488 | (record_count > 64 * 1024)) | ||
489 | { | ||
490 | /* sanity check, don't stack allocate far too much just | ||
491 | because database might contain a large value here */ | ||
492 | GNUNET_break (0); | ||
493 | ret = GNUNET_SYSERR; | ||
494 | break; | ||
495 | } | ||
496 | else | ||
497 | { | ||
498 | struct GNUNET_GNSRECORD_Data rd[record_count]; | ||
499 | |||
500 | GNUNET_assert (0 != seq); | ||
501 | if (GNUNET_OK != | ||
502 | GNUNET_GNSRECORD_records_deserialize (data_size, | ||
503 | data, | ||
504 | record_count, | ||
505 | rd)) | ||
506 | { | ||
507 | GNUNET_break (0); | ||
508 | ret = GNUNET_SYSERR; | ||
509 | break; | ||
510 | } | ||
511 | else | ||
512 | { | ||
513 | if (NULL != zone_key) | ||
514 | zk = *zone_key; | ||
515 | if (NULL != iter) | ||
516 | iter (iter_cls, | ||
517 | seq, | ||
518 | &zk, | ||
519 | label, | ||
520 | record_count, | ||
521 | rd); | ||
522 | } | ||
523 | } | ||
524 | GNUNET_SQ_cleanup_result (rs); | ||
525 | } | ||
526 | } | ||
527 | GNUNET_SQ_reset (plugin->dbh, | ||
528 | stmt); | ||
529 | return ret; | ||
530 | } | ||
531 | |||
532 | |||
533 | /** | ||
534 | * Lookup records in the datastore for which we are the authority. | ||
535 | * | ||
536 | * @param cls closure (internal context for the plugin) | ||
537 | * @param zone private key of the zone | ||
538 | * @param label name of the record in the zone | ||
539 | * @param iter function to call with the result | ||
540 | * @param iter_cls closure for @a iter | ||
541 | * @return #GNUNET_OK on success, #GNUNET_NO for no results, else #GNUNET_SYSERR | ||
542 | */ | ||
543 | static enum GNUNET_GenericReturnValue | ||
544 | namestore_sqlite_lookup_records (void *cls, | ||
545 | const struct | ||
546 | GNUNET_CRYPTO_PrivateKey *zone, | ||
547 | const char *label, | ||
548 | GNUNET_NAMESTORE_RecordIterator iter, | ||
549 | void *iter_cls) | ||
550 | { | ||
551 | struct Plugin *plugin = cls; | ||
552 | GNUNET_assert (GNUNET_OK == database_prepare (plugin)); | ||
553 | struct GNUNET_SQ_QueryParam params[] = { | ||
554 | GNUNET_SQ_query_param_auto_from_type (zone), | ||
555 | GNUNET_SQ_query_param_string (label), | ||
556 | GNUNET_SQ_query_param_end | ||
557 | }; | ||
558 | |||
559 | if (NULL == zone) | ||
560 | { | ||
561 | GNUNET_break (0); | ||
562 | return GNUNET_SYSERR; | ||
563 | } | ||
564 | if (GNUNET_OK != | ||
565 | GNUNET_SQ_bind (plugin->lookup_label, | ||
566 | params)) | ||
567 | { | ||
568 | LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, | ||
569 | "sqlite3_bind_XXXX"); | ||
570 | GNUNET_SQ_reset (plugin->dbh, | ||
571 | plugin->lookup_label); | ||
572 | return GNUNET_SYSERR; | ||
573 | } | ||
574 | return get_records_and_call_iterator (plugin, | ||
575 | plugin->lookup_label, | ||
576 | zone, | ||
577 | 1, | ||
578 | iter, | ||
579 | iter_cls); | ||
580 | } | ||
581 | |||
582 | |||
583 | /** | ||
584 | * Iterate over the results for a particular key and zone in the | ||
585 | * datastore. Will return at most one result to the iterator. | ||
586 | * | ||
587 | * @param cls closure (internal context for the plugin) | ||
588 | * @param zone hash of public key of the zone, NULL to iterate over all zones | ||
589 | * @param serial serial number to exclude in the list of all matching records | ||
590 | * @param limit maximum number of results to return | ||
591 | * @param iter function to call with the result | ||
592 | * @param iter_cls closure for @a iter | ||
593 | * @return #GNUNET_OK on success, #GNUNET_NO if there were no more results, #GNUNET_SYSERR on error | ||
594 | */ | ||
595 | static enum GNUNET_GenericReturnValue | ||
596 | namestore_sqlite_iterate_records (void *cls, | ||
597 | const struct | ||
598 | GNUNET_CRYPTO_PrivateKey *zone, | ||
599 | uint64_t serial, | ||
600 | uint64_t limit, | ||
601 | GNUNET_NAMESTORE_RecordIterator iter, | ||
602 | void *iter_cls) | ||
603 | { | ||
604 | struct Plugin *plugin = cls; | ||
605 | sqlite3_stmt *stmt; | ||
606 | int err; | ||
607 | |||
608 | GNUNET_assert (GNUNET_OK == database_prepare (plugin)); | ||
609 | if (NULL == zone) | ||
610 | { | ||
611 | struct GNUNET_SQ_QueryParam params[] = { | ||
612 | GNUNET_SQ_query_param_uint64 (&serial), | ||
613 | GNUNET_SQ_query_param_uint64 (&limit), | ||
614 | GNUNET_SQ_query_param_end | ||
615 | }; | ||
616 | |||
617 | stmt = plugin->iterate_all_zones; | ||
618 | err = GNUNET_SQ_bind (stmt, | ||
619 | params); | ||
620 | } | ||
621 | else | ||
622 | { | ||
623 | struct GNUNET_SQ_QueryParam params[] = { | ||
624 | GNUNET_SQ_query_param_auto_from_type (zone), | ||
625 | GNUNET_SQ_query_param_uint64 (&serial), | ||
626 | GNUNET_SQ_query_param_uint64 (&limit), | ||
627 | GNUNET_SQ_query_param_end | ||
628 | }; | ||
629 | |||
630 | stmt = plugin->iterate_zone; | ||
631 | err = GNUNET_SQ_bind (stmt, | ||
632 | params); | ||
633 | } | ||
634 | if (GNUNET_OK != err) | ||
635 | { | ||
636 | LOG_SQLITE (plugin, | ||
637 | GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, | ||
638 | "sqlite3_bind_XXXX"); | ||
639 | GNUNET_SQ_reset (plugin->dbh, | ||
640 | stmt); | ||
641 | return GNUNET_SYSERR; | ||
642 | } | ||
643 | return get_records_and_call_iterator (plugin, | ||
644 | stmt, | ||
645 | zone, | ||
646 | limit, | ||
647 | iter, | ||
648 | iter_cls); | ||
649 | } | ||
650 | |||
651 | |||
652 | /** | ||
653 | * Look for an existing PKEY delegation record for a given public key. | ||
654 | * Returns at most one result to the iterator. | ||
655 | * | ||
656 | * @param cls closure (internal context for the plugin) | ||
657 | * @param zone private key of the zone to look up in, never NULL | ||
658 | * @param value_zone public key of the target zone (value), never NULL | ||
659 | * @param iter function to call with the result | ||
660 | * @param iter_cls closure for @a iter | ||
661 | * @return #GNUNET_OK on success, #GNUNET_NO if there were no results, #GNUNET_SYSERR on error | ||
662 | */ | ||
663 | static enum GNUNET_GenericReturnValue | ||
664 | namestore_sqlite_zone_to_name (void *cls, | ||
665 | const struct GNUNET_CRYPTO_PrivateKey *zone, | ||
666 | const struct | ||
667 | GNUNET_CRYPTO_PublicKey *value_zone, | ||
668 | GNUNET_NAMESTORE_RecordIterator iter, | ||
669 | void *iter_cls) | ||
670 | { | ||
671 | struct Plugin *plugin = cls; | ||
672 | GNUNET_assert (GNUNET_OK == database_prepare (plugin)); | ||
673 | struct GNUNET_SQ_QueryParam params[] = { | ||
674 | GNUNET_SQ_query_param_auto_from_type (zone), | ||
675 | GNUNET_SQ_query_param_auto_from_type (value_zone), | ||
676 | GNUNET_SQ_query_param_end | ||
677 | }; | ||
678 | |||
679 | if (GNUNET_OK != | ||
680 | GNUNET_SQ_bind (plugin->zone_to_name, | ||
681 | params)) | ||
682 | { | ||
683 | LOG_SQLITE (plugin, | ||
684 | GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, | ||
685 | "sqlite3_bind_XXXX"); | ||
686 | GNUNET_SQ_reset (plugin->dbh, | ||
687 | plugin->zone_to_name); | ||
688 | return GNUNET_SYSERR; | ||
689 | } | ||
690 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
691 | "Performing reverse lookup for `%s'\n", | ||
692 | GNUNET_GNSRECORD_z2s (value_zone)); | ||
693 | return get_records_and_call_iterator (plugin, | ||
694 | plugin->zone_to_name, | ||
695 | zone, | ||
696 | 1, | ||
697 | iter, | ||
698 | iter_cls); | ||
699 | } | ||
700 | |||
701 | |||
702 | /** | ||
703 | * Begin a transaction for a client. | ||
704 | * This locks the database. SQLite is unable to discern between different | ||
705 | * rows with a specific zone key but the API looks like this anyway. | ||
706 | * https://www.sqlite.org/lang_transaction.html | ||
707 | * | ||
708 | * @param cls closure (internal context for the plugin) | ||
709 | * @param emsg error message set of return code is #GNUNET_SYSERR | ||
710 | * @return #GNUNET_YES on success, #GNUNET_SYSERR if transaction cannot be started. | ||
711 | */ | ||
712 | static enum GNUNET_GenericReturnValue | ||
713 | namestore_sqlite_transaction_begin (void *cls, | ||
714 | char **emsg) | ||
715 | { | ||
716 | struct Plugin *plugin = cls; | ||
717 | int rc; | ||
718 | char *sqlEmsg; | ||
719 | |||
720 | GNUNET_assert (GNUNET_OK == database_prepare (plugin)); | ||
721 | rc = sqlite3_exec (plugin->dbh, "BEGIN IMMEDIATE TRANSACTION;", | ||
722 | NULL, NULL, &sqlEmsg); | ||
723 | if (SQLITE_OK != rc) | ||
724 | { | ||
725 | *emsg = GNUNET_strdup (sqlEmsg); | ||
726 | sqlite3_free (sqlEmsg); | ||
727 | } | ||
728 | return (SQLITE_OK != rc) ? GNUNET_SYSERR : GNUNET_YES; | ||
729 | } | ||
730 | |||
731 | |||
732 | /** | ||
733 | * Commit a transaction for a client. | ||
734 | * This releases the lock on the database. | ||
735 | * | ||
736 | * @param cls closure (internal context for the plugin) | ||
737 | * @param emsg error message set of return code is #GNUNET_SYSERR | ||
738 | * @return #GNUNET_YES on success, #GNUNET_SYSERR if transaction cannot be started. | ||
739 | */ | ||
740 | static enum GNUNET_GenericReturnValue | ||
741 | namestore_sqlite_transaction_rollback (void *cls, | ||
742 | char **emsg) | ||
743 | { | ||
744 | struct Plugin *plugin = cls; | ||
745 | int rc; | ||
746 | char *sqlEmsg; | ||
747 | |||
748 | GNUNET_assert (GNUNET_OK == database_prepare (plugin)); | ||
749 | rc = sqlite3_exec (plugin->dbh, "ROLLBACK;", | ||
750 | NULL, NULL, &sqlEmsg); | ||
751 | if (SQLITE_OK != rc) | ||
752 | { | ||
753 | *emsg = GNUNET_strdup (sqlEmsg); | ||
754 | sqlite3_free (sqlEmsg); | ||
755 | } | ||
756 | return (SQLITE_OK != rc) ? GNUNET_SYSERR : GNUNET_YES; | ||
757 | } | ||
758 | |||
759 | |||
760 | /** | ||
761 | * Roll back a transaction for a client. | ||
762 | * This releases the lock on the database. | ||
763 | * | ||
764 | * @param cls closure (internal context for the plugin) | ||
765 | * @param emsg error message set of return code is #GNUNET_SYSERR | ||
766 | * @return #GNUNET_YES on success, #GNUNET_SYSERR if transaction cannot be started. | ||
767 | */ | ||
768 | static enum GNUNET_GenericReturnValue | ||
769 | namestore_sqlite_transaction_commit (void *cls, | ||
770 | char **emsg) | ||
771 | { | ||
772 | struct Plugin *plugin = cls; | ||
773 | int rc; | ||
774 | char *sqlEmsg; | ||
775 | |||
776 | GNUNET_assert (GNUNET_OK == database_prepare (plugin)); | ||
777 | rc = sqlite3_exec (plugin->dbh, "END TRANSACTION;", | ||
778 | NULL, NULL, &sqlEmsg); | ||
779 | if (SQLITE_OK != rc) | ||
780 | { | ||
781 | *emsg = GNUNET_strdup (sqlEmsg); | ||
782 | sqlite3_free (sqlEmsg); | ||
783 | } | ||
784 | return (SQLITE_OK != rc) ? GNUNET_SYSERR : GNUNET_YES; | ||
785 | } | ||
786 | |||
787 | |||
788 | static enum GNUNET_GenericReturnValue | ||
789 | namestore_sqlite_create_tables (void *cls) | ||
790 | { | ||
791 | struct Plugin *plugin = cls; | ||
792 | struct GNUNET_SQ_ExecuteStatement es[] = { | ||
793 | GNUNET_SQ_make_try_execute ("PRAGMA temp_store=MEMORY"), | ||
794 | GNUNET_SQ_make_try_execute ("PRAGMA synchronous=NORMAL"), | ||
795 | GNUNET_SQ_make_try_execute ("PRAGMA legacy_file_format=OFF"), | ||
796 | GNUNET_SQ_make_try_execute ("PRAGMA auto_vacuum=INCREMENTAL"), | ||
797 | GNUNET_SQ_make_try_execute ("PRAGMA encoding=\"UTF-8\""), | ||
798 | GNUNET_SQ_make_try_execute ("PRAGMA locking_mode=NORMAL"), | ||
799 | GNUNET_SQ_make_try_execute ("PRAGMA journal_mode=WAL"), | ||
800 | GNUNET_SQ_make_try_execute ("PRAGMA page_size=4092"), | ||
801 | GNUNET_SQ_make_execute ("CREATE TABLE IF NOT EXISTS ns098records (" | ||
802 | " uid INTEGER PRIMARY KEY," | ||
803 | " zone_private_key BLOB NOT NULL," | ||
804 | " pkey BLOB," | ||
805 | " rvalue INT8 NOT NULL," | ||
806 | " record_count INT NOT NULL," | ||
807 | " record_data BLOB NOT NULL," | ||
808 | " label TEXT NOT NULL" | ||
809 | ")"), | ||
810 | GNUNET_SQ_make_try_execute ("CREATE INDEX ir_pkey_reverse " | ||
811 | "ON ns098records (zone_private_key,pkey)"), | ||
812 | GNUNET_SQ_make_try_execute ("CREATE INDEX ir_pkey_iter " | ||
813 | "ON ns098records (zone_private_key,uid)"), | ||
814 | GNUNET_SQ_EXECUTE_STATEMENT_END | ||
815 | }; | ||
816 | |||
817 | if (GNUNET_OK != | ||
818 | GNUNET_SQ_exec_statements (plugin->dbh, | ||
819 | es)) | ||
820 | { | ||
821 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
822 | "Failed to setup database with: `%s'\n", | ||
823 | sqlite3_errmsg (plugin->dbh)); | ||
824 | return GNUNET_SYSERR; | ||
825 | } | ||
826 | return GNUNET_OK; | ||
827 | } | ||
828 | |||
829 | |||
830 | static enum GNUNET_GenericReturnValue | ||
831 | namestore_sqlite_drop_tables (void *cls) | ||
832 | { | ||
833 | struct Plugin *plugin = cls; | ||
834 | struct GNUNET_SQ_ExecuteStatement es_drop[] = { | ||
835 | GNUNET_SQ_make_execute ("DROP TABLE IF EXISTS ns098records"), | ||
836 | GNUNET_SQ_EXECUTE_STATEMENT_END | ||
837 | }; | ||
838 | |||
839 | if (GNUNET_OK != | ||
840 | GNUNET_SQ_exec_statements (plugin->dbh, | ||
841 | es_drop)) | ||
842 | { | ||
843 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
844 | "Failed to drop database with: `%s'\n", | ||
845 | sqlite3_errmsg (plugin->dbh)); | ||
846 | return GNUNET_SYSERR; | ||
847 | } | ||
848 | return GNUNET_OK; | ||
849 | } | ||
850 | |||
851 | |||
852 | /** | ||
853 | * Initialize the database connections and associated | ||
854 | * data structures (create tables and indices | ||
855 | * as needed as well). | ||
856 | * | ||
857 | * @param plugin the plugin context (state for this module) | ||
858 | * @return #GNUNET_OK on success | ||
859 | */ | ||
860 | static enum GNUNET_GenericReturnValue | ||
861 | database_connect (struct Plugin *plugin) | ||
862 | { | ||
863 | char *sqlite_filename; | ||
864 | |||
865 | if (GNUNET_OK != | ||
866 | GNUNET_CONFIGURATION_get_value_filename (plugin->cfg, | ||
867 | "namestore-sqlite", | ||
868 | "FILENAME", | ||
869 | &sqlite_filename)) | ||
870 | { | ||
871 | GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR, | ||
872 | "namestore-sqlite", | ||
873 | "FILENAME"); | ||
874 | return GNUNET_SYSERR; | ||
875 | } | ||
876 | if (GNUNET_OK != | ||
877 | GNUNET_DISK_file_test (sqlite_filename)) | ||
878 | { | ||
879 | if (GNUNET_OK != | ||
880 | GNUNET_DISK_directory_create_for_file (sqlite_filename)) | ||
881 | { | ||
882 | GNUNET_break (0); | ||
883 | GNUNET_free (sqlite_filename); | ||
884 | return GNUNET_SYSERR; | ||
885 | } | ||
886 | } | ||
887 | |||
888 | /* Open database and precompile statements */ | ||
889 | if ((NULL == plugin->dbh) && | ||
890 | (SQLITE_OK != sqlite3_open (sqlite_filename, | ||
891 | &plugin->dbh))) | ||
892 | { | ||
893 | LOG (GNUNET_ERROR_TYPE_ERROR, | ||
894 | _ ("Unable to initialize SQLite: %s.\n"), | ||
895 | sqlite3_errmsg (plugin->dbh)); | ||
896 | GNUNET_free (sqlite_filename); | ||
897 | return GNUNET_SYSERR; | ||
898 | } | ||
899 | GNUNET_free (sqlite_filename); | ||
900 | GNUNET_break (SQLITE_OK == | ||
901 | sqlite3_busy_timeout (plugin->dbh, | ||
902 | BUSY_TIMEOUT_MS)); | ||
903 | if (GNUNET_YES == | ||
904 | GNUNET_CONFIGURATION_get_value_yesno (plugin->cfg, | ||
905 | "namestore-sqlite", | ||
906 | "INIT_ON_CONNECT")) | ||
907 | { | ||
908 | if (GNUNET_OK != | ||
909 | namestore_sqlite_create_tables (plugin)) | ||
910 | return GNUNET_SYSERR; | ||
911 | } | ||
912 | return GNUNET_OK; | ||
913 | } | ||
914 | |||
915 | |||
916 | /** | ||
917 | * Entry point for the plugin. | ||
918 | * | ||
919 | * @param cls the "struct GNUNET_NAMESTORE_PluginEnvironment*" | ||
920 | * @return NULL on error, otherwise the plugin context | ||
921 | */ | ||
922 | void * | ||
923 | libgnunet_plugin_namestore_sqlite_init (void *cls) | ||
924 | { | ||
925 | struct Plugin *plugin; | ||
926 | const struct GNUNET_CONFIGURATION_Handle *cfg = cls; | ||
927 | struct GNUNET_NAMESTORE_PluginFunctions *api; | ||
928 | |||
929 | plugin = GNUNET_new (struct Plugin); | ||
930 | plugin->cfg = cfg; | ||
931 | if (GNUNET_OK != database_connect (plugin)) | ||
932 | { | ||
933 | LOG (GNUNET_ERROR_TYPE_ERROR, | ||
934 | "Database could not be connected to.\n"); | ||
935 | GNUNET_free (plugin); | ||
936 | return NULL; | ||
937 | } | ||
938 | api = GNUNET_new (struct GNUNET_NAMESTORE_PluginFunctions); | ||
939 | api->cls = plugin; | ||
940 | api->store_records = &namestore_sqlite_store_records; | ||
941 | api->iterate_records = &namestore_sqlite_iterate_records; | ||
942 | api->zone_to_name = &namestore_sqlite_zone_to_name; | ||
943 | api->lookup_records = &namestore_sqlite_lookup_records; | ||
944 | api->transaction_begin = &namestore_sqlite_transaction_begin; | ||
945 | api->transaction_commit = &namestore_sqlite_transaction_commit; | ||
946 | api->transaction_rollback = &namestore_sqlite_transaction_rollback; | ||
947 | api->create_tables = &namestore_sqlite_create_tables; | ||
948 | api->drop_tables = &namestore_sqlite_drop_tables; | ||
949 | /** | ||
950 | * NOTE: Since SQlite does not support SELECT ... FOR UPDATE this is | ||
951 | * just an alias to lookup_records. The BEGIN IMMEDIATE mechanic currently | ||
952 | * implicitly ensures this API behaves as it should | ||
953 | */ | ||
954 | api->edit_records = &namestore_sqlite_lookup_records; | ||
955 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
956 | _ ("SQlite database running\n")); | ||
957 | return api; | ||
958 | } | ||
959 | |||
960 | |||
961 | /** | ||
962 | * Exit point from the plugin. | ||
963 | * | ||
964 | * @param cls the plugin context (as returned by "init") | ||
965 | * @return always NULL | ||
966 | */ | ||
967 | void * | ||
968 | libgnunet_plugin_namestore_sqlite_done (void *cls) | ||
969 | { | ||
970 | struct GNUNET_NAMESTORE_PluginFunctions *api = cls; | ||
971 | struct Plugin *plugin = api->cls; | ||
972 | |||
973 | database_shutdown (plugin); | ||
974 | plugin->cfg = NULL; | ||
975 | GNUNET_free (plugin); | ||
976 | GNUNET_free (api); | ||
977 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
978 | "SQlite plugin is finished\n"); | ||
979 | return NULL; | ||
980 | } | ||
981 | |||
982 | |||
983 | /* 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 31e78e6dd..000000000 --- a/src/namestore/plugin_rest_namestore.c +++ /dev/null | |||
@@ -1,1364 +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_error_codes.h" | ||
29 | #include "gnunet_rest_plugin.h" | ||
30 | #include "gnunet_gns_service.h" | ||
31 | #include "gnunet_namestore_service.h" | ||
32 | #include "gnunet_identity_service.h" | ||
33 | #include "gnunet_rest_lib.h" | ||
34 | #include "gnunet_gnsrecord_json_lib.h" | ||
35 | #include "microhttpd.h" | ||
36 | #include <jansson.h> | ||
37 | |||
38 | /** | ||
39 | * Namestore namespace | ||
40 | */ | ||
41 | #define GNUNET_REST_API_NS_NAMESTORE "/namestore" | ||
42 | |||
43 | /** | ||
44 | * Namestore import API namespace | ||
45 | */ | ||
46 | #define GNUNET_REST_API_NS_NAMESTORE_IMPORT "/namestore/import" | ||
47 | |||
48 | /** | ||
49 | * State while collecting all egos | ||
50 | */ | ||
51 | #define ID_REST_STATE_INIT 0 | ||
52 | |||
53 | /** | ||
54 | * Done collecting egos | ||
55 | */ | ||
56 | #define ID_REST_STATE_POST_INIT 1 | ||
57 | /** | ||
58 | * The configuration handle | ||
59 | */ | ||
60 | const struct GNUNET_CONFIGURATION_Handle *cfg; | ||
61 | |||
62 | /** | ||
63 | * HTTP methods allows for this plugin | ||
64 | */ | ||
65 | static char *allow_methods; | ||
66 | |||
67 | /** | ||
68 | * Ego list | ||
69 | */ | ||
70 | static struct EgoEntry *ego_head; | ||
71 | |||
72 | /** | ||
73 | * Ego list | ||
74 | */ | ||
75 | static struct EgoEntry *ego_tail; | ||
76 | |||
77 | /** | ||
78 | * The processing state | ||
79 | */ | ||
80 | static int state; | ||
81 | |||
82 | /** | ||
83 | * Handle to NAMESTORE | ||
84 | */ | ||
85 | static struct GNUNET_NAMESTORE_Handle *ns_handle; | ||
86 | |||
87 | /** | ||
88 | * Handle to Identity service. | ||
89 | */ | ||
90 | static struct GNUNET_IDENTITY_Handle *identity_handle; | ||
91 | |||
92 | /** | ||
93 | * @brief struct returned by the initialization function of the plugin | ||
94 | */ | ||
95 | struct Plugin | ||
96 | { | ||
97 | const struct GNUNET_CONFIGURATION_Handle *cfg; | ||
98 | }; | ||
99 | |||
100 | /** | ||
101 | * The default namestore ego | ||
102 | */ | ||
103 | struct EgoEntry | ||
104 | { | ||
105 | /** | ||
106 | * DLL | ||
107 | */ | ||
108 | struct EgoEntry *next; | ||
109 | |||
110 | /** | ||
111 | * DLL | ||
112 | */ | ||
113 | struct EgoEntry *prev; | ||
114 | |||
115 | /** | ||
116 | * Ego Identifier | ||
117 | */ | ||
118 | char *identifier; | ||
119 | |||
120 | /** | ||
121 | * Public key string | ||
122 | */ | ||
123 | char *keystring; | ||
124 | |||
125 | /** | ||
126 | * The Ego | ||
127 | */ | ||
128 | struct GNUNET_IDENTITY_Ego *ego; | ||
129 | }; | ||
130 | |||
131 | |||
132 | enum UpdateStrategy | ||
133 | { | ||
134 | UPDATE_STRATEGY_REPLACE, | ||
135 | UPDATE_STRATEGY_APPEND | ||
136 | }; | ||
137 | |||
138 | /** | ||
139 | * The request handle | ||
140 | */ | ||
141 | struct RequestHandle | ||
142 | { | ||
143 | /** | ||
144 | * DLL | ||
145 | */ | ||
146 | struct RequestHandle *next; | ||
147 | |||
148 | /** | ||
149 | * DLL | ||
150 | */ | ||
151 | struct RequestHandle *prev; | ||
152 | |||
153 | /** | ||
154 | * Records to store | ||
155 | */ | ||
156 | char *record_name; | ||
157 | |||
158 | /** | ||
159 | * Record type filter | ||
160 | */ | ||
161 | uint32_t record_type; | ||
162 | |||
163 | /** | ||
164 | * How to update the record set | ||
165 | */ | ||
166 | enum UpdateStrategy update_strategy; | ||
167 | |||
168 | /** | ||
169 | * Records to store | ||
170 | */ | ||
171 | struct GNUNET_GNSRECORD_Data *rd; | ||
172 | |||
173 | /** | ||
174 | * Number of records in rd | ||
175 | */ | ||
176 | unsigned int rd_count; | ||
177 | |||
178 | /** | ||
179 | * RecordInfo array | ||
180 | */ | ||
181 | struct GNUNET_NAMESTORE_RecordInfo *ri; | ||
182 | |||
183 | /** | ||
184 | * Size of record info | ||
185 | */ | ||
186 | unsigned int rd_set_count; | ||
187 | |||
188 | /** | ||
189 | * Position of record info | ||
190 | */ | ||
191 | unsigned int rd_set_pos; | ||
192 | |||
193 | /** | ||
194 | * NAMESTORE Operation | ||
195 | */ | ||
196 | struct GNUNET_NAMESTORE_QueueEntry *ns_qe; | ||
197 | |||
198 | /** | ||
199 | * For bulk import, we need a dedicated Namestore handle | ||
200 | */ | ||
201 | struct GNUNET_NAMESTORE_Handle *nc; | ||
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_CRYPTO_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 code | ||
261 | */ | ||
262 | enum GNUNET_ErrorCode ec; | ||
263 | |||
264 | }; | ||
265 | |||
266 | /** | ||
267 | * DLL | ||
268 | */ | ||
269 | static struct RequestHandle *requests_head; | ||
270 | |||
271 | /** | ||
272 | * DLL | ||
273 | */ | ||
274 | static struct RequestHandle *requests_tail; | ||
275 | |||
276 | |||
277 | /** | ||
278 | * Cleanup lookup handle | ||
279 | * @param cls Handle to clean up | ||
280 | */ | ||
281 | static void | ||
282 | cleanup_handle (void *cls) | ||
283 | { | ||
284 | struct RequestHandle *handle = cls; | ||
285 | |||
286 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Cleaning up\n"); | ||
287 | if (NULL != handle->timeout_task) | ||
288 | { | ||
289 | GNUNET_SCHEDULER_cancel (handle->timeout_task); | ||
290 | handle->timeout_task = NULL; | ||
291 | } | ||
292 | if (NULL != handle->record_name) | ||
293 | GNUNET_free (handle->record_name); | ||
294 | if (NULL != handle->url) | ||
295 | GNUNET_free (handle->url); | ||
296 | if (NULL != handle->rd) | ||
297 | { | ||
298 | for (int i = 0; i < handle->rd_count; i++) | ||
299 | { | ||
300 | if (NULL != handle->rd[i].data) | ||
301 | GNUNET_free_nz ((void *) handle->rd[i].data); | ||
302 | } | ||
303 | GNUNET_free (handle->rd); | ||
304 | } | ||
305 | if (NULL != handle->timeout_task) | ||
306 | GNUNET_SCHEDULER_cancel (handle->timeout_task); | ||
307 | if (NULL != handle->list_it) | ||
308 | GNUNET_NAMESTORE_zone_iteration_stop (handle->list_it); | ||
309 | if (NULL != handle->ns_qe) | ||
310 | GNUNET_NAMESTORE_cancel (handle->ns_qe); | ||
311 | if (NULL != handle->nc) | ||
312 | GNUNET_NAMESTORE_disconnect (handle->nc); | ||
313 | if (NULL != handle->resp_object) | ||
314 | { | ||
315 | json_decref (handle->resp_object); | ||
316 | } | ||
317 | GNUNET_CONTAINER_DLL_remove (requests_head, | ||
318 | requests_tail, | ||
319 | handle); | ||
320 | GNUNET_free (handle); | ||
321 | } | ||
322 | |||
323 | |||
324 | /** | ||
325 | * Task run on errors. Reports an error and cleans up everything. | ||
326 | * | ||
327 | * @param cls the `struct RequestHandle` | ||
328 | */ | ||
329 | static void | ||
330 | do_error (void *cls) | ||
331 | { | ||
332 | struct RequestHandle *handle = cls; | ||
333 | struct MHD_Response *resp; | ||
334 | json_t *json_error = json_object (); | ||
335 | char *response; | ||
336 | const char* emsg; | ||
337 | int response_code; | ||
338 | |||
339 | emsg = GNUNET_ErrorCode_get_hint (handle->ec); | ||
340 | json_object_set_new (json_error, "error", json_string (emsg)); | ||
341 | json_object_set_new (json_error, "error_code", json_integer (handle->ec)); | ||
342 | response_code = GNUNET_ErrorCode_get_http_status (handle->ec); | ||
343 | if (0 == response_code) | ||
344 | response_code = MHD_HTTP_INTERNAL_SERVER_ERROR; | ||
345 | response = json_dumps (json_error, 0); | ||
346 | resp = GNUNET_REST_create_response (response); | ||
347 | GNUNET_assert (MHD_YES == | ||
348 | MHD_add_response_header (resp, "Content-Type", | ||
349 | "application/json")); | ||
350 | handle->proc (handle->proc_cls, resp, response_code); | ||
351 | json_decref (json_error); | ||
352 | GNUNET_free (response); | ||
353 | cleanup_handle (handle); | ||
354 | } | ||
355 | |||
356 | |||
357 | /** | ||
358 | * Get EgoEntry from list with either a public key or a name | ||
359 | * If public key and name are not NULL, it returns the public key result first | ||
360 | * | ||
361 | * @param handle the RequestHandle | ||
362 | * @param pubkey the public key of an identity (only one can be NULL) | ||
363 | * @param name the name of an identity (only one can be NULL) | ||
364 | * @return EgoEntry or NULL if not found | ||
365 | */ | ||
366 | struct EgoEntry * | ||
367 | get_egoentry_namestore (struct RequestHandle *handle, char *name) | ||
368 | { | ||
369 | struct EgoEntry *ego_entry; | ||
370 | char *copy = GNUNET_strdup (name); | ||
371 | char *tmp; | ||
372 | |||
373 | if (NULL == name) | ||
374 | return NULL; | ||
375 | tmp = strtok (copy, "/"); | ||
376 | if (NULL == tmp) | ||
377 | return NULL; | ||
378 | for (ego_entry = ego_head; NULL != ego_entry; | ||
379 | ego_entry = ego_entry->next) | ||
380 | { | ||
381 | if (0 != strcasecmp (tmp, ego_entry->identifier)) | ||
382 | continue; | ||
383 | GNUNET_free (copy); | ||
384 | return ego_entry; | ||
385 | } | ||
386 | GNUNET_free (copy); | ||
387 | return NULL; | ||
388 | } | ||
389 | |||
390 | |||
391 | /** | ||
392 | * Does internal server error when iteration failed. | ||
393 | * | ||
394 | * @param cls the `struct RequestHandle` | ||
395 | */ | ||
396 | static void | ||
397 | namestore_iteration_error (void *cls) | ||
398 | { | ||
399 | struct RequestHandle *handle = cls; | ||
400 | |||
401 | handle->ec = GNUNET_EC_NAMESTORE_ITERATION_FAILED; | ||
402 | GNUNET_SCHEDULER_add_now (&do_error, handle); | ||
403 | return; | ||
404 | } | ||
405 | |||
406 | |||
407 | static void | ||
408 | create_finished (void *cls, enum GNUNET_ErrorCode ec) | ||
409 | { | ||
410 | struct RequestHandle *handle = cls; | ||
411 | struct MHD_Response *resp; | ||
412 | |||
413 | handle->ns_qe = NULL; | ||
414 | handle->ec = ec; | ||
415 | if (GNUNET_EC_NONE != ec) | ||
416 | { | ||
417 | GNUNET_SCHEDULER_add_now (&do_error, handle); | ||
418 | return; | ||
419 | } | ||
420 | resp = GNUNET_REST_create_response (NULL); | ||
421 | handle->proc (handle->proc_cls, resp, MHD_HTTP_NO_CONTENT); | ||
422 | GNUNET_SCHEDULER_add_now (&cleanup_handle, handle); | ||
423 | } | ||
424 | |||
425 | |||
426 | static void | ||
427 | del_finished (void *cls, enum GNUNET_ErrorCode ec) | ||
428 | { | ||
429 | struct RequestHandle *handle = cls; | ||
430 | |||
431 | handle->ns_qe = NULL; | ||
432 | handle->ec = ec; | ||
433 | if (GNUNET_EC_NONE != ec) | ||
434 | { | ||
435 | GNUNET_SCHEDULER_add_now (&do_error, handle); | ||
436 | return; | ||
437 | } | ||
438 | handle->proc (handle->proc_cls, | ||
439 | GNUNET_REST_create_response (NULL), | ||
440 | MHD_HTTP_NO_CONTENT); | ||
441 | GNUNET_SCHEDULER_add_now (&cleanup_handle, handle); | ||
442 | } | ||
443 | |||
444 | |||
445 | /** | ||
446 | * Iteration over all results finished, build final | ||
447 | * response. | ||
448 | * | ||
449 | * @param cls the `struct RequestHandle` | ||
450 | */ | ||
451 | static void | ||
452 | namestore_list_finished (void *cls) | ||
453 | { | ||
454 | struct RequestHandle *handle = cls; | ||
455 | char *result_str; | ||
456 | struct MHD_Response *resp; | ||
457 | |||
458 | handle->list_it = NULL; | ||
459 | |||
460 | if (NULL == handle->resp_object) | ||
461 | { | ||
462 | handle->ec = GNUNET_EC_NAMESTORE_ZONE_EMPTY; | ||
463 | GNUNET_SCHEDULER_add_now (&do_error, handle); | ||
464 | return; | ||
465 | } | ||
466 | result_str = json_dumps (handle->resp_object, 0); | ||
467 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Result %s\n", result_str); | ||
468 | resp = GNUNET_REST_create_response (result_str); | ||
469 | GNUNET_assert (MHD_YES == | ||
470 | MHD_add_response_header (resp, "Content-Type", | ||
471 | "application/json")); | ||
472 | handle->proc (handle->proc_cls, resp, MHD_HTTP_OK); | ||
473 | GNUNET_free (result_str); | ||
474 | GNUNET_SCHEDULER_add_now (&cleanup_handle, handle); | ||
475 | } | ||
476 | |||
477 | |||
478 | /** | ||
479 | * Create a response with requested records | ||
480 | * | ||
481 | * @param handle the RequestHandle | ||
482 | */ | ||
483 | static void | ||
484 | namestore_list_iteration (void *cls, | ||
485 | const struct GNUNET_CRYPTO_PrivateKey *zone_key, | ||
486 | const char *rname, | ||
487 | unsigned int rd_len, | ||
488 | const struct GNUNET_GNSRECORD_Data *rd, | ||
489 | struct GNUNET_TIME_Absolute expiry) | ||
490 | { | ||
491 | struct RequestHandle *handle = cls; | ||
492 | struct GNUNET_GNSRECORD_Data rd_filtered[rd_len]; | ||
493 | json_t *record_obj; | ||
494 | int i = 0; | ||
495 | int j = 0; | ||
496 | |||
497 | if (rd_len == 0) | ||
498 | { | ||
499 | /** skip **/ | ||
500 | GNUNET_NAMESTORE_zone_iterator_next (handle->list_it, 1); | ||
501 | return; | ||
502 | } | ||
503 | |||
504 | for (i = 0; i < rd_len; i++) | ||
505 | { | ||
506 | if ((GNUNET_GNSRECORD_TYPE_ANY != handle->record_type) && | ||
507 | (rd[i].record_type != handle->record_type)) | ||
508 | continue; /* Apply filter */ | ||
509 | rd_filtered[j] = rd[i]; | ||
510 | rd_filtered[j].data = rd[i].data; | ||
511 | j++; | ||
512 | } | ||
513 | /** Only add if not empty **/ | ||
514 | if (j > 0) | ||
515 | { | ||
516 | if (NULL == handle->resp_object) | ||
517 | handle->resp_object = json_array (); | ||
518 | record_obj = GNUNET_GNSRECORD_JSON_from_gnsrecord (rname, | ||
519 | rd_filtered, | ||
520 | j); | ||
521 | json_array_append_new (handle->resp_object, record_obj); | ||
522 | } | ||
523 | GNUNET_NAMESTORE_zone_iterator_next (handle->list_it, 1); | ||
524 | } | ||
525 | |||
526 | |||
527 | /** | ||
528 | * Handle lookup error | ||
529 | * | ||
530 | * @param cls the request handle | ||
531 | */ | ||
532 | static void | ||
533 | ns_lookup_error_cb (void *cls) | ||
534 | { | ||
535 | struct RequestHandle *handle = cls; | ||
536 | |||
537 | handle->ec = GNUNET_EC_NAMESTORE_LOOKUP_ERROR; | ||
538 | GNUNET_SCHEDULER_add_now (&do_error, handle); | ||
539 | } | ||
540 | |||
541 | |||
542 | static void | ||
543 | ns_get_lookup_cb (void *cls, | ||
544 | const struct GNUNET_CRYPTO_PrivateKey *zone, | ||
545 | const char *label, | ||
546 | unsigned int rd_len, | ||
547 | const struct GNUNET_GNSRECORD_Data *rd) | ||
548 | { | ||
549 | struct RequestHandle *handle = cls; | ||
550 | struct GNUNET_GNSRECORD_Data rd_filtered[rd_len]; | ||
551 | int i = 0; | ||
552 | int j = 0; | ||
553 | |||
554 | handle->ns_qe = NULL; | ||
555 | for (i = 0; i < rd_len; i++) | ||
556 | { | ||
557 | if ((GNUNET_GNSRECORD_TYPE_ANY != handle->record_type) && | ||
558 | (rd[i].record_type != handle->record_type)) | ||
559 | continue; /* Apply filter */ | ||
560 | rd_filtered[j] = rd[i]; | ||
561 | rd_filtered[j].data = rd[i].data; | ||
562 | j++; | ||
563 | } | ||
564 | /** Return 404 if no set was found **/ | ||
565 | if (j == 0) | ||
566 | { | ||
567 | handle->ec = GNUNET_EC_NAMESTORE_RECORD_NOT_FOUND; | ||
568 | GNUNET_SCHEDULER_add_now (&do_error, handle); | ||
569 | return; | ||
570 | } | ||
571 | handle->resp_object = GNUNET_GNSRECORD_JSON_from_gnsrecord (label, | ||
572 | rd_filtered, | ||
573 | j); | ||
574 | GNUNET_SCHEDULER_add_now (&namestore_list_finished, handle); | ||
575 | } | ||
576 | |||
577 | |||
578 | /** | ||
579 | * Handle namestore GET request | ||
580 | * | ||
581 | * @param con_handle the connection handle | ||
582 | * @param url the url | ||
583 | * @param cls the RequestHandle | ||
584 | */ | ||
585 | void | ||
586 | namestore_get (struct GNUNET_REST_RequestHandle *con_handle, | ||
587 | const char *url, | ||
588 | void *cls) | ||
589 | { | ||
590 | struct RequestHandle *handle = cls; | ||
591 | struct EgoEntry *ego_entry; | ||
592 | struct GNUNET_HashCode key; | ||
593 | enum GNUNET_GNSRECORD_Filter filter_flags; | ||
594 | char *egoname; | ||
595 | char *labelname; | ||
596 | char *typename; | ||
597 | char *boolstring; | ||
598 | |||
599 | egoname = NULL; | ||
600 | ego_entry = NULL; | ||
601 | |||
602 | // set zone to name if given | ||
603 | if (strlen (GNUNET_REST_API_NS_NAMESTORE) + 1 >= strlen (handle->url)) | ||
604 | { | ||
605 | handle->ec = GNUNET_EC_NAMESTORE_ZONE_NOT_FOUND; | ||
606 | GNUNET_SCHEDULER_add_now (&do_error, handle); | ||
607 | return; | ||
608 | } | ||
609 | egoname = &handle->url[strlen (GNUNET_REST_API_NS_NAMESTORE) + 1]; | ||
610 | ego_entry = get_egoentry_namestore (handle, egoname); | ||
611 | if (NULL == ego_entry) | ||
612 | { | ||
613 | handle->ec = GNUNET_EC_NAMESTORE_ZONE_NOT_FOUND; | ||
614 | GNUNET_SCHEDULER_add_now (&do_error, handle); | ||
615 | return; | ||
616 | } | ||
617 | handle->zone_pkey = GNUNET_IDENTITY_ego_get_private_key (ego_entry->ego); | ||
618 | |||
619 | GNUNET_CRYPTO_hash ("record_type", strlen ("record_type"), &key); | ||
620 | handle->record_type = GNUNET_GNSRECORD_TYPE_ANY; | ||
621 | if (GNUNET_YES == | ||
622 | GNUNET_CONTAINER_multihashmap_contains (con_handle->url_param_map, &key)) | ||
623 | { | ||
624 | typename = GNUNET_CONTAINER_multihashmap_get (con_handle->url_param_map, | ||
625 | &key); | ||
626 | if (NULL != typename) | ||
627 | handle->record_type = GNUNET_GNSRECORD_typename_to_number (typename); | ||
628 | } | ||
629 | GNUNET_CRYPTO_hash ("omit_private", strlen ("omit_private"), &key); | ||
630 | filter_flags = GNUNET_GNSRECORD_FILTER_NONE; | ||
631 | if (GNUNET_YES == | ||
632 | GNUNET_CONTAINER_multihashmap_contains (con_handle->url_param_map, &key)) | ||
633 | { | ||
634 | boolstring = GNUNET_CONTAINER_multihashmap_get (con_handle->url_param_map, | ||
635 | &key); | ||
636 | if ((0 == strcmp (boolstring, "1")) || | ||
637 | (0 == strcmp (boolstring, "yes")) || | ||
638 | (0 == strcmp (boolstring, "true"))) | ||
639 | filter_flags = GNUNET_GNSRECORD_FILTER_OMIT_PRIVATE; | ||
640 | } | ||
641 | GNUNET_CRYPTO_hash ("include_maintenance", strlen ("include_maintenance"), | ||
642 | &key); | ||
643 | if (GNUNET_YES == | ||
644 | GNUNET_CONTAINER_multihashmap_contains (con_handle->url_param_map, &key)) | ||
645 | { | ||
646 | boolstring = GNUNET_CONTAINER_multihashmap_get (con_handle->url_param_map, | ||
647 | &key); | ||
648 | if ((0 == strcmp (boolstring, "1")) || | ||
649 | (0 == strcmp (boolstring, "yes")) || | ||
650 | (0 == strcmp (boolstring, "true"))) | ||
651 | filter_flags |= GNUNET_GNSRECORD_FILTER_INCLUDE_MAINTENANCE; | ||
652 | } | ||
653 | labelname = &egoname[strlen (ego_entry->identifier)]; | ||
654 | if (1 >= strlen (labelname)) | ||
655 | { | ||
656 | /* Iterate over all records */ | ||
657 | handle->list_it = | ||
658 | GNUNET_NAMESTORE_zone_iteration_start2 (ns_handle, | ||
659 | handle->zone_pkey, | ||
660 | &namestore_iteration_error, | ||
661 | handle, | ||
662 | &namestore_list_iteration, | ||
663 | handle, | ||
664 | &namestore_list_finished, | ||
665 | handle, | ||
666 | filter_flags); | ||
667 | if (NULL == handle->list_it) | ||
668 | { | ||
669 | handle->ec = GNUNET_EC_NAMESTORE_UNKNOWN; | ||
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_lookup2 (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 | filter_flags); | ||
684 | if (NULL == handle->ns_qe) | ||
685 | { | ||
686 | handle->ec = GNUNET_EC_NAMESTORE_UNKNOWN; | ||
687 | GNUNET_SCHEDULER_add_now (&do_error, handle); | ||
688 | return; | ||
689 | } | ||
690 | } | ||
691 | |||
692 | |||
693 | static void | ||
694 | ns_lookup_cb (void *cls, | ||
695 | const struct GNUNET_CRYPTO_PrivateKey *zone, | ||
696 | const char *label, | ||
697 | unsigned int rd_count, | ||
698 | const struct GNUNET_GNSRECORD_Data *rd) | ||
699 | { | ||
700 | struct RequestHandle *handle = cls; | ||
701 | struct GNUNET_GNSRECORD_Data rd_new[rd_count + handle->rd_count]; | ||
702 | int i = 0; | ||
703 | int j = 0; | ||
704 | |||
705 | if (UPDATE_STRATEGY_APPEND == handle->update_strategy) | ||
706 | { | ||
707 | for (i = 0; i < rd_count; i++) | ||
708 | rd_new[i] = rd[i]; | ||
709 | } | ||
710 | for (j = 0; j < handle->rd_count; j++) | ||
711 | rd_new[i + j] = handle->rd[j]; | ||
712 | handle->ns_qe = GNUNET_NAMESTORE_records_store (ns_handle, | ||
713 | handle->zone_pkey, | ||
714 | handle->record_name, | ||
715 | i + j, | ||
716 | rd_new, | ||
717 | &create_finished, | ||
718 | handle); | ||
719 | if (NULL == handle->ns_qe) | ||
720 | { | ||
721 | handle->ec = GNUNET_EC_NAMESTORE_UNKNOWN; | ||
722 | GNUNET_SCHEDULER_add_now (&do_error, handle); | ||
723 | return; | ||
724 | } | ||
725 | } | ||
726 | |||
727 | |||
728 | static void | ||
729 | bulk_tx_commit_cb (void *cls, enum GNUNET_ErrorCode ec) | ||
730 | { | ||
731 | struct RequestHandle *handle = cls; | ||
732 | struct MHD_Response *resp; | ||
733 | |||
734 | handle->ns_qe = NULL; | ||
735 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
736 | "Commit finished (%d)\n", ec); | ||
737 | handle->ec = ec; | ||
738 | if (GNUNET_EC_NONE != ec) | ||
739 | { | ||
740 | GNUNET_SCHEDULER_add_now (&do_error, handle); | ||
741 | return; | ||
742 | } | ||
743 | resp = GNUNET_REST_create_response (NULL); | ||
744 | handle->proc (handle->proc_cls, resp, MHD_HTTP_NO_CONTENT); | ||
745 | GNUNET_SCHEDULER_add_now (&cleanup_handle, handle); | ||
746 | } | ||
747 | |||
748 | |||
749 | static void | ||
750 | import_next_cb (void *cls, enum GNUNET_ErrorCode ec) | ||
751 | { | ||
752 | struct RequestHandle *handle = cls; | ||
753 | |||
754 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
755 | "Import finished (%d)\n", ec); | ||
756 | handle->ns_qe = NULL; | ||
757 | handle->ec = ec; | ||
758 | if (GNUNET_EC_NONE != ec) | ||
759 | { | ||
760 | GNUNET_SCHEDULER_add_now (&do_error, handle); | ||
761 | return; | ||
762 | } | ||
763 | unsigned int remaining = handle->rd_set_count - handle->rd_set_pos; | ||
764 | if (0 == remaining) | ||
765 | { | ||
766 | handle->ns_qe = GNUNET_NAMESTORE_transaction_commit (handle->nc, | ||
767 | &bulk_tx_commit_cb, | ||
768 | handle); | ||
769 | return; | ||
770 | } | ||
771 | unsigned int sent_rds = 0; | ||
772 | // Find the smallest set of records we can send with our message size | ||
773 | // restriction of 16 bit | ||
774 | handle->ns_qe = GNUNET_NAMESTORE_records_store2 (handle->nc, | ||
775 | handle->zone_pkey, | ||
776 | remaining, | ||
777 | &handle->ri[handle-> | ||
778 | rd_set_pos], | ||
779 | &sent_rds, | ||
780 | &import_next_cb, | ||
781 | handle); | ||
782 | if ((NULL == handle->ns_qe) && (0 == sent_rds)) | ||
783 | { | ||
784 | handle->ec = GNUNET_EC_NAMESTORE_UNKNOWN; | ||
785 | GNUNET_SCHEDULER_add_now (&do_error, handle); | ||
786 | return; | ||
787 | } | ||
788 | handle->rd_set_pos += sent_rds; | ||
789 | } | ||
790 | |||
791 | static void | ||
792 | bulk_tx_start (void *cls, enum GNUNET_ErrorCode ec) | ||
793 | { | ||
794 | struct RequestHandle *handle = cls; | ||
795 | json_t *data_js; | ||
796 | json_error_t err; | ||
797 | |||
798 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
799 | "Transaction started...\n"); | ||
800 | handle->ec = ec; | ||
801 | if (GNUNET_EC_NONE != ec) | ||
802 | { | ||
803 | GNUNET_SCHEDULER_add_now (&do_error, handle); | ||
804 | return; | ||
805 | } | ||
806 | if (0 >= handle->rest_handle->data_size) | ||
807 | { | ||
808 | handle->ec = GNUNET_EC_NAMESTORE_NO_RECORDS_GIVEN; | ||
809 | GNUNET_SCHEDULER_add_now (&do_error, handle); | ||
810 | return; | ||
811 | } | ||
812 | char term_data[handle->rest_handle->data_size + 1]; | ||
813 | term_data[handle->rest_handle->data_size] = '\0'; | ||
814 | GNUNET_memcpy (term_data, | ||
815 | handle->rest_handle->data, | ||
816 | handle->rest_handle->data_size); | ||
817 | data_js = json_loads (term_data, JSON_DECODE_ANY, &err); | ||
818 | if (NULL == data_js) | ||
819 | { | ||
820 | handle->ec = GNUNET_EC_NAMESTORE_RECORD_DATA_INVALID; | ||
821 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
822 | "Error parsing data: %s", err.text); | ||
823 | GNUNET_SCHEDULER_add_now (&do_error, handle); | ||
824 | return; | ||
825 | } | ||
826 | if (! json_is_array (data_js)) | ||
827 | { | ||
828 | handle->ec = GNUNET_EC_NAMESTORE_RECORD_DATA_INVALID; | ||
829 | GNUNET_SCHEDULER_add_now (&do_error, handle); | ||
830 | json_decref (data_js); | ||
831 | return; | ||
832 | } | ||
833 | handle->rd_set_count = json_array_size (data_js); | ||
834 | handle->ri = GNUNET_malloc (handle->rd_set_count | ||
835 | * sizeof (struct GNUNET_NAMESTORE_RecordInfo)); | ||
836 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
837 | "Got record set of size %d\n", handle->rd_set_count); | ||
838 | char *albl; | ||
839 | size_t index; | ||
840 | json_t *value; | ||
841 | json_array_foreach (data_js, index, value) { | ||
842 | { | ||
843 | struct GNUNET_GNSRECORD_Data *rd; | ||
844 | struct GNUNET_JSON_Specification gnsspec[] = | ||
845 | { GNUNET_GNSRECORD_JSON_spec_gnsrecord (&rd, | ||
846 | &handle->ri[index].a_rd_count, | ||
847 | &albl), | ||
848 | GNUNET_JSON_spec_end () }; | ||
849 | if (GNUNET_OK != GNUNET_JSON_parse (value, gnsspec, NULL, NULL)) | ||
850 | { | ||
851 | handle->ec = GNUNET_EC_NAMESTORE_RECORD_DATA_INVALID; | ||
852 | GNUNET_SCHEDULER_add_now (&do_error, handle); | ||
853 | json_decref (data_js); | ||
854 | return; | ||
855 | } | ||
856 | handle->ri[index].a_rd = rd; | ||
857 | handle->ri[index].a_label = albl; | ||
858 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
859 | "Parsed record set for name %s\n", | ||
860 | handle->ri[index].a_label); | ||
861 | } | ||
862 | } | ||
863 | // json_decref (data_js); | ||
864 | |||
865 | unsigned int sent_rds = 0; | ||
866 | // Find the smallest set of records we can send with our message size | ||
867 | // restriction of 16 bit | ||
868 | handle->ns_qe = GNUNET_NAMESTORE_records_store2 (handle->nc, | ||
869 | handle->zone_pkey, | ||
870 | handle->rd_set_count, | ||
871 | handle->ri, | ||
872 | &sent_rds, | ||
873 | &import_next_cb, | ||
874 | handle); | ||
875 | if ((NULL == handle->ns_qe) && (0 == sent_rds)) | ||
876 | { | ||
877 | handle->ec = GNUNET_EC_NAMESTORE_UNKNOWN; | ||
878 | GNUNET_SCHEDULER_add_now (&do_error, handle); | ||
879 | return; | ||
880 | } | ||
881 | handle->rd_set_pos += sent_rds; | ||
882 | } | ||
883 | |||
884 | |||
885 | /** | ||
886 | * Handle namestore POST import | ||
887 | * | ||
888 | * @param con_handle the connection handle | ||
889 | * @param url the url | ||
890 | * @param cls the RequestHandle | ||
891 | */ | ||
892 | void | ||
893 | namestore_import (struct GNUNET_REST_RequestHandle *con_handle, | ||
894 | const char *url, | ||
895 | void *cls) | ||
896 | { | ||
897 | struct RequestHandle *handle = cls; | ||
898 | struct EgoEntry *ego_entry; | ||
899 | char *egoname; | ||
900 | |||
901 | // set zone to name if given | ||
902 | if (strlen (GNUNET_REST_API_NS_NAMESTORE_IMPORT) + 1 >= strlen ( | ||
903 | handle->url)) | ||
904 | { | ||
905 | handle->ec = GNUNET_EC_NAMESTORE_ZONE_NOT_FOUND; | ||
906 | GNUNET_SCHEDULER_add_now (&do_error, handle); | ||
907 | return; | ||
908 | } | ||
909 | ego_entry = NULL; | ||
910 | |||
911 | egoname = &handle->url[strlen (GNUNET_REST_API_NS_NAMESTORE_IMPORT) + 1]; | ||
912 | ego_entry = get_egoentry_namestore (handle, egoname); | ||
913 | |||
914 | if (NULL == ego_entry) | ||
915 | { | ||
916 | handle->ec = GNUNET_EC_NAMESTORE_ZONE_NOT_FOUND; | ||
917 | GNUNET_SCHEDULER_add_now (&do_error, handle); | ||
918 | return; | ||
919 | } | ||
920 | handle->zone_pkey = GNUNET_IDENTITY_ego_get_private_key (ego_entry->ego); | ||
921 | |||
922 | // We need a per-client connection for a transactional bulk import | ||
923 | handle->nc = GNUNET_NAMESTORE_connect (cfg); | ||
924 | if (NULL == handle->nc) | ||
925 | { | ||
926 | handle->ec = GNUNET_EC_NAMESTORE_UNKNOWN; | ||
927 | GNUNET_SCHEDULER_add_now (&do_error, handle); | ||
928 | return; | ||
929 | } | ||
930 | handle->ns_qe = GNUNET_NAMESTORE_transaction_begin (handle->nc, | ||
931 | &bulk_tx_start, | ||
932 | handle); | ||
933 | } | ||
934 | |||
935 | /** | ||
936 | * Handle namestore POST/PUT request | ||
937 | * | ||
938 | * @param con_handle the connection handle | ||
939 | * @param url the url | ||
940 | * @param cls the RequestHandle | ||
941 | */ | ||
942 | void | ||
943 | namestore_add_or_update (struct GNUNET_REST_RequestHandle *con_handle, | ||
944 | const char *url, | ||
945 | void *cls) | ||
946 | { | ||
947 | struct RequestHandle *handle = cls; | ||
948 | struct EgoEntry *ego_entry; | ||
949 | char *egoname; | ||
950 | json_t *data_js; | ||
951 | json_error_t err; | ||
952 | |||
953 | char term_data[handle->rest_handle->data_size + 1]; | ||
954 | |||
955 | if (0 >= handle->rest_handle->data_size) | ||
956 | { | ||
957 | handle->ec = GNUNET_EC_NAMESTORE_NO_RECORDS_GIVEN; | ||
958 | GNUNET_SCHEDULER_add_now (&do_error, handle); | ||
959 | return; | ||
960 | } | ||
961 | term_data[handle->rest_handle->data_size] = '\0'; | ||
962 | GNUNET_memcpy (term_data, | ||
963 | handle->rest_handle->data, | ||
964 | handle->rest_handle->data_size); | ||
965 | data_js = json_loads (term_data, JSON_DECODE_ANY, &err); | ||
966 | struct GNUNET_JSON_Specification gnsspec[] = | ||
967 | { GNUNET_GNSRECORD_JSON_spec_gnsrecord (&handle->rd, &handle->rd_count, | ||
968 | &handle->record_name), | ||
969 | GNUNET_JSON_spec_end () }; | ||
970 | if (GNUNET_OK != GNUNET_JSON_parse (data_js, gnsspec, NULL, NULL)) | ||
971 | { | ||
972 | handle->ec = GNUNET_EC_NAMESTORE_RECORD_DATA_INVALID; | ||
973 | GNUNET_SCHEDULER_add_now (&do_error, handle); | ||
974 | json_decref (data_js); | ||
975 | return; | ||
976 | } | ||
977 | GNUNET_JSON_parse_free (gnsspec); | ||
978 | if (0 >= strlen (handle->record_name)) | ||
979 | { | ||
980 | handle->ec = GNUNET_EC_NAMESTORE_RECORD_DATA_INVALID; | ||
981 | GNUNET_SCHEDULER_add_now (&do_error, handle); | ||
982 | json_decref (data_js); | ||
983 | return; | ||
984 | } | ||
985 | json_decref (data_js); | ||
986 | |||
987 | egoname = NULL; | ||
988 | ego_entry = NULL; | ||
989 | |||
990 | // set zone to name if given | ||
991 | if (strlen (GNUNET_REST_API_NS_NAMESTORE) + 1 >= strlen (handle->url)) | ||
992 | { | ||
993 | handle->ec = GNUNET_EC_NAMESTORE_ZONE_NOT_FOUND; | ||
994 | GNUNET_SCHEDULER_add_now (&do_error, handle); | ||
995 | return; | ||
996 | } | ||
997 | egoname = &handle->url[strlen (GNUNET_REST_API_NS_NAMESTORE) + 1]; | ||
998 | ego_entry = get_egoentry_namestore (handle, egoname); | ||
999 | |||
1000 | if (NULL == ego_entry) | ||
1001 | { | ||
1002 | handle->ec = GNUNET_EC_NAMESTORE_ZONE_NOT_FOUND; | ||
1003 | GNUNET_SCHEDULER_add_now (&do_error, handle); | ||
1004 | return; | ||
1005 | } | ||
1006 | handle->zone_pkey = GNUNET_IDENTITY_ego_get_private_key (ego_entry->ego); | ||
1007 | handle->ns_qe = GNUNET_NAMESTORE_records_lookup (ns_handle, | ||
1008 | handle->zone_pkey, | ||
1009 | handle->record_name, | ||
1010 | &ns_lookup_error_cb, | ||
1011 | handle, | ||
1012 | &ns_lookup_cb, | ||
1013 | handle); | ||
1014 | if (NULL == handle->ns_qe) | ||
1015 | { | ||
1016 | handle->ec = GNUNET_EC_NAMESTORE_UNKNOWN; | ||
1017 | GNUNET_SCHEDULER_add_now (&do_error, handle); | ||
1018 | return; | ||
1019 | } | ||
1020 | } | ||
1021 | |||
1022 | |||
1023 | /** | ||
1024 | * Handle namestore PUT request | ||
1025 | * | ||
1026 | * @param con_handle the connection handle | ||
1027 | * @param url the url | ||
1028 | * @param cls the RequestHandle | ||
1029 | */ | ||
1030 | void | ||
1031 | namestore_update (struct GNUNET_REST_RequestHandle *con_handle, | ||
1032 | const char *url, | ||
1033 | void *cls) | ||
1034 | { | ||
1035 | struct RequestHandle *handle = cls; | ||
1036 | handle->update_strategy = UPDATE_STRATEGY_REPLACE; | ||
1037 | namestore_add_or_update (con_handle, url, cls); | ||
1038 | } | ||
1039 | |||
1040 | |||
1041 | /** | ||
1042 | * Handle namestore POST request | ||
1043 | * | ||
1044 | * @param con_handle the connection handle | ||
1045 | * @param url the url | ||
1046 | * @param cls the RequestHandle | ||
1047 | */ | ||
1048 | void | ||
1049 | namestore_add (struct GNUNET_REST_RequestHandle *con_handle, | ||
1050 | const char *url, | ||
1051 | void *cls) | ||
1052 | { | ||
1053 | struct RequestHandle *handle = cls; | ||
1054 | handle->update_strategy = UPDATE_STRATEGY_APPEND; | ||
1055 | namestore_add_or_update (con_handle, url, cls); | ||
1056 | } | ||
1057 | |||
1058 | |||
1059 | /** | ||
1060 | * Handle namestore DELETE request | ||
1061 | * | ||
1062 | * @param con_handle the connection handle | ||
1063 | * @param url the url | ||
1064 | * @param cls the RequestHandle | ||
1065 | */ | ||
1066 | void | ||
1067 | namestore_delete (struct GNUNET_REST_RequestHandle *con_handle, | ||
1068 | const char *url, | ||
1069 | void *cls) | ||
1070 | { | ||
1071 | struct RequestHandle *handle = cls; | ||
1072 | struct EgoEntry *ego_entry; | ||
1073 | char *egoname; | ||
1074 | char *labelname; | ||
1075 | |||
1076 | egoname = NULL; | ||
1077 | ego_entry = NULL; | ||
1078 | |||
1079 | // set zone to name if given | ||
1080 | if (strlen (GNUNET_REST_API_NS_NAMESTORE) + 1 >= strlen (handle->url)) | ||
1081 | { | ||
1082 | handle->ec = GNUNET_EC_NAMESTORE_ZONE_NOT_FOUND; | ||
1083 | GNUNET_SCHEDULER_add_now (&do_error, handle); | ||
1084 | return; | ||
1085 | } | ||
1086 | egoname = &handle->url[strlen (GNUNET_REST_API_NS_NAMESTORE) + 1]; | ||
1087 | ego_entry = get_egoentry_namestore (handle, egoname); | ||
1088 | if (NULL == ego_entry) | ||
1089 | { | ||
1090 | handle->ec = GNUNET_EC_NAMESTORE_ZONE_NOT_FOUND; | ||
1091 | GNUNET_SCHEDULER_add_now (&do_error, handle); | ||
1092 | return; | ||
1093 | } | ||
1094 | handle->zone_pkey = GNUNET_IDENTITY_ego_get_private_key (ego_entry->ego); | ||
1095 | labelname = &egoname[strlen (ego_entry->identifier)]; | ||
1096 | // set zone to name if given | ||
1097 | if (1 >= strlen (labelname)) | ||
1098 | { | ||
1099 | /* label is only "/" */ | ||
1100 | handle->ec = GNUNET_EC_NAMESTORE_NO_LABEL_GIVEN; | ||
1101 | GNUNET_SCHEDULER_add_now (&do_error, handle); | ||
1102 | } | ||
1103 | |||
1104 | handle->record_name = GNUNET_strdup (labelname + 1); | ||
1105 | handle->ns_qe = GNUNET_NAMESTORE_records_store (ns_handle, | ||
1106 | handle->zone_pkey, | ||
1107 | handle->record_name, | ||
1108 | 0, | ||
1109 | NULL, | ||
1110 | &del_finished, | ||
1111 | handle); | ||
1112 | if (NULL == handle->ns_qe) | ||
1113 | { | ||
1114 | handle->ec = GNUNET_EC_NAMESTORE_UNKNOWN; | ||
1115 | GNUNET_SCHEDULER_add_now (&do_error, handle); | ||
1116 | return; | ||
1117 | } | ||
1118 | } | ||
1119 | |||
1120 | |||
1121 | /** | ||
1122 | * Respond to OPTIONS request | ||
1123 | * | ||
1124 | * @param con_handle the connection handle | ||
1125 | * @param url the url | ||
1126 | * @param cls the RequestHandle | ||
1127 | */ | ||
1128 | static void | ||
1129 | options_cont (struct GNUNET_REST_RequestHandle *con_handle, | ||
1130 | const char *url, | ||
1131 | void *cls) | ||
1132 | { | ||
1133 | struct MHD_Response *resp; | ||
1134 | struct RequestHandle *handle = cls; | ||
1135 | |||
1136 | // independent of path return all options | ||
1137 | resp = GNUNET_REST_create_response (NULL); | ||
1138 | GNUNET_assert (MHD_YES == | ||
1139 | MHD_add_response_header (resp, | ||
1140 | "Access-Control-Allow-Methods", | ||
1141 | allow_methods)); | ||
1142 | handle->proc (handle->proc_cls, resp, MHD_HTTP_OK); | ||
1143 | GNUNET_SCHEDULER_add_now (&cleanup_handle, handle); | ||
1144 | return; | ||
1145 | } | ||
1146 | |||
1147 | |||
1148 | static void | ||
1149 | list_ego (void *cls, | ||
1150 | struct GNUNET_IDENTITY_Ego *ego, | ||
1151 | void **ctx, | ||
1152 | const char *identifier) | ||
1153 | { | ||
1154 | struct EgoEntry *ego_entry; | ||
1155 | struct GNUNET_CRYPTO_PublicKey pk; | ||
1156 | |||
1157 | if ((NULL == ego) && (ID_REST_STATE_INIT == state)) | ||
1158 | { | ||
1159 | state = ID_REST_STATE_POST_INIT; | ||
1160 | return; | ||
1161 | } | ||
1162 | if (NULL == ego) | ||
1163 | { | ||
1164 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, | ||
1165 | "Called with NULL ego\n"); | ||
1166 | return; | ||
1167 | } | ||
1168 | if (ID_REST_STATE_INIT == state) | ||
1169 | { | ||
1170 | ego_entry = GNUNET_new (struct EgoEntry); | ||
1171 | GNUNET_IDENTITY_ego_get_public_key (ego, &pk); | ||
1172 | ego_entry->keystring = GNUNET_CRYPTO_public_key_to_string (&pk); | ||
1173 | ego_entry->ego = ego; | ||
1174 | ego_entry->identifier = GNUNET_strdup (identifier); | ||
1175 | GNUNET_CONTAINER_DLL_insert_tail (ego_head, | ||
1176 | ego_tail, | ||
1177 | ego_entry); | ||
1178 | } | ||
1179 | /* Ego renamed or added */ | ||
1180 | if (identifier != NULL) | ||
1181 | { | ||
1182 | for (ego_entry = ego_head; NULL != ego_entry; | ||
1183 | ego_entry = ego_entry->next) | ||
1184 | { | ||
1185 | if (ego_entry->ego == ego) | ||
1186 | { | ||
1187 | /* Rename */ | ||
1188 | GNUNET_free (ego_entry->identifier); | ||
1189 | ego_entry->identifier = GNUNET_strdup (identifier); | ||
1190 | break; | ||
1191 | } | ||
1192 | } | ||
1193 | if (NULL == ego_entry) | ||
1194 | { | ||
1195 | /* Add */ | ||
1196 | ego_entry = GNUNET_new (struct EgoEntry); | ||
1197 | GNUNET_IDENTITY_ego_get_public_key (ego, &pk); | ||
1198 | ego_entry->keystring = GNUNET_CRYPTO_public_key_to_string (&pk); | ||
1199 | ego_entry->ego = ego; | ||
1200 | ego_entry->identifier = GNUNET_strdup (identifier); | ||
1201 | GNUNET_CONTAINER_DLL_insert_tail (ego_head, | ||
1202 | ego_tail, | ||
1203 | ego_entry); | ||
1204 | } | ||
1205 | } | ||
1206 | else | ||
1207 | { | ||
1208 | /* Delete */ | ||
1209 | for (ego_entry = ego_head; NULL != ego_entry; | ||
1210 | ego_entry = ego_entry->next) | ||
1211 | { | ||
1212 | if (ego_entry->ego == ego) | ||
1213 | break; | ||
1214 | } | ||
1215 | if (NULL == ego_entry) | ||
1216 | return; /* Not found */ | ||
1217 | |||
1218 | GNUNET_CONTAINER_DLL_remove (ego_head, | ||
1219 | ego_tail, | ||
1220 | ego_entry); | ||
1221 | GNUNET_free (ego_entry->identifier); | ||
1222 | GNUNET_free (ego_entry->keystring); | ||
1223 | GNUNET_free (ego_entry); | ||
1224 | return; | ||
1225 | } | ||
1226 | |||
1227 | } | ||
1228 | |||
1229 | |||
1230 | /** | ||
1231 | * Function processing the REST call | ||
1232 | * | ||
1233 | * @param method HTTP method | ||
1234 | * @param url URL of the HTTP request | ||
1235 | * @param data body of the HTTP request (optional) | ||
1236 | * @param data_size length of the body | ||
1237 | * @param proc callback function for the result | ||
1238 | * @param proc_cls closure for callback function | ||
1239 | * @return GNUNET_OK if request accepted | ||
1240 | */ | ||
1241 | static enum GNUNET_GenericReturnValue | ||
1242 | rest_process_request (struct GNUNET_REST_RequestHandle *rest_handle, | ||
1243 | GNUNET_REST_ResultProcessor proc, | ||
1244 | void *proc_cls) | ||
1245 | { | ||
1246 | struct RequestHandle *handle = GNUNET_new (struct RequestHandle); | ||
1247 | struct GNUNET_REST_RequestHandlerError err; | ||
1248 | static const struct GNUNET_REST_RequestHandler handlers[] = | ||
1249 | { { MHD_HTTP_METHOD_GET, GNUNET_REST_API_NS_NAMESTORE, &namestore_get }, | ||
1250 | { MHD_HTTP_METHOD_POST, GNUNET_REST_API_NS_NAMESTORE_IMPORT, | ||
1251 | &namestore_import }, | ||
1252 | { MHD_HTTP_METHOD_POST, GNUNET_REST_API_NS_NAMESTORE, &namestore_add }, | ||
1253 | { MHD_HTTP_METHOD_PUT, GNUNET_REST_API_NS_NAMESTORE, &namestore_update }, | ||
1254 | { MHD_HTTP_METHOD_DELETE, GNUNET_REST_API_NS_NAMESTORE, | ||
1255 | &namestore_delete }, | ||
1256 | { MHD_HTTP_METHOD_OPTIONS, GNUNET_REST_API_NS_NAMESTORE, &options_cont }, | ||
1257 | GNUNET_REST_HANDLER_END }; | ||
1258 | |||
1259 | handle->ec = GNUNET_EC_NONE; | ||
1260 | handle->timeout = GNUNET_TIME_UNIT_FOREVER_REL; | ||
1261 | handle->proc_cls = proc_cls; | ||
1262 | handle->proc = proc; | ||
1263 | handle->rest_handle = rest_handle; | ||
1264 | handle->zone_pkey = NULL; | ||
1265 | handle->timeout_task = | ||
1266 | GNUNET_SCHEDULER_add_delayed (handle->timeout, &do_error, handle); | ||
1267 | handle->url = GNUNET_strdup (rest_handle->url); | ||
1268 | if (handle->url[strlen (handle->url) - 1] == '/') | ||
1269 | handle->url[strlen (handle->url) - 1] = '\0'; | ||
1270 | GNUNET_CONTAINER_DLL_insert (requests_head, | ||
1271 | requests_tail, | ||
1272 | handle); | ||
1273 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Connecting...\n"); | ||
1274 | if (GNUNET_NO == | ||
1275 | GNUNET_REST_handle_request (handle->rest_handle, handlers, &err, | ||
1276 | handle)) | ||
1277 | { | ||
1278 | cleanup_handle (handle); | ||
1279 | return GNUNET_NO; | ||
1280 | } | ||
1281 | |||
1282 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Connected\n"); | ||
1283 | return GNUNET_YES; | ||
1284 | } | ||
1285 | |||
1286 | |||
1287 | /** | ||
1288 | * Entry point for the plugin. | ||
1289 | * | ||
1290 | * @param cls Config info | ||
1291 | * @return NULL on error, otherwise the plugin context | ||
1292 | */ | ||
1293 | void * | ||
1294 | libgnunet_plugin_rest_namestore_init (void *cls) | ||
1295 | { | ||
1296 | static struct Plugin plugin; | ||
1297 | struct GNUNET_REST_Plugin *api; | ||
1298 | |||
1299 | cfg = cls; | ||
1300 | if (NULL != plugin.cfg) | ||
1301 | return NULL; /* can only initialize once! */ | ||
1302 | memset (&plugin, 0, sizeof(struct Plugin)); | ||
1303 | plugin.cfg = cfg; | ||
1304 | api = GNUNET_new (struct GNUNET_REST_Plugin); | ||
1305 | api->cls = &plugin; | ||
1306 | api->name = GNUNET_REST_API_NS_NAMESTORE; | ||
1307 | api->process_request = &rest_process_request; | ||
1308 | state = ID_REST_STATE_INIT; | ||
1309 | GNUNET_asprintf (&allow_methods, | ||
1310 | "%s, %s, %s, %s, %s", | ||
1311 | MHD_HTTP_METHOD_GET, | ||
1312 | MHD_HTTP_METHOD_POST, | ||
1313 | MHD_HTTP_METHOD_PUT, | ||
1314 | MHD_HTTP_METHOD_DELETE, | ||
1315 | MHD_HTTP_METHOD_OPTIONS); | ||
1316 | ns_handle = GNUNET_NAMESTORE_connect (cfg); | ||
1317 | identity_handle = GNUNET_IDENTITY_connect (cfg, &list_ego, NULL); | ||
1318 | |||
1319 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, _ ( | ||
1320 | "Namestore REST API initialized\n")); | ||
1321 | return api; | ||
1322 | } | ||
1323 | |||
1324 | |||
1325 | /** | ||
1326 | * Exit point from the plugin. | ||
1327 | * | ||
1328 | * @param cls the plugin context (as returned by "init") | ||
1329 | * @return always NULL | ||
1330 | */ | ||
1331 | void * | ||
1332 | libgnunet_plugin_rest_namestore_done (void *cls) | ||
1333 | { | ||
1334 | struct GNUNET_REST_Plugin *api = cls; | ||
1335 | struct Plugin *plugin = api->cls; | ||
1336 | struct RequestHandle *request; | ||
1337 | struct EgoEntry *ego_entry; | ||
1338 | struct EgoEntry *ego_tmp; | ||
1339 | |||
1340 | plugin->cfg = NULL; | ||
1341 | while (NULL != (request = requests_head)) | ||
1342 | do_error (request); | ||
1343 | if (NULL != identity_handle) | ||
1344 | GNUNET_IDENTITY_disconnect (identity_handle); | ||
1345 | if (NULL != ns_handle) | ||
1346 | GNUNET_NAMESTORE_disconnect (ns_handle); | ||
1347 | |||
1348 | for (ego_entry = ego_head; NULL != ego_entry;) | ||
1349 | { | ||
1350 | ego_tmp = ego_entry; | ||
1351 | ego_entry = ego_entry->next; | ||
1352 | GNUNET_free (ego_tmp->identifier); | ||
1353 | GNUNET_free (ego_tmp->keystring); | ||
1354 | GNUNET_free (ego_tmp); | ||
1355 | } | ||
1356 | |||
1357 | GNUNET_free (allow_methods); | ||
1358 | GNUNET_free (api); | ||
1359 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Namestore REST plugin is finished\n"); | ||
1360 | return NULL; | ||
1361 | } | ||
1362 | |||
1363 | |||
1364 | /* 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 4df24a7f7..000000000 --- a/src/namestore/test_common.c +++ /dev/null | |||
@@ -1,128 +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 | #include "platform.h" | ||
25 | #include <gnunet_namestore_plugin.h> | ||
26 | |||
27 | /** | ||
28 | * test if we can load the plugin @a name. | ||
29 | */ | ||
30 | static int | ||
31 | TNC_test_plugin (const char *cfg_name) | ||
32 | { | ||
33 | char *database; | ||
34 | char *db_lib_name; | ||
35 | struct GNUNET_NAMESTORE_PluginFunctions *db; | ||
36 | struct GNUNET_CONFIGURATION_Handle *cfg; | ||
37 | |||
38 | cfg = GNUNET_CONFIGURATION_create (); | ||
39 | if (GNUNET_OK != | ||
40 | GNUNET_CONFIGURATION_load (cfg, | ||
41 | cfg_name)) | ||
42 | { | ||
43 | GNUNET_break (0); | ||
44 | GNUNET_CONFIGURATION_destroy (cfg); | ||
45 | return GNUNET_SYSERR; | ||
46 | } | ||
47 | if (GNUNET_OK != | ||
48 | GNUNET_CONFIGURATION_get_value_string (cfg, | ||
49 | "namestore", | ||
50 | "database", | ||
51 | &database)) | ||
52 | { | ||
53 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
54 | "No database backend configured\n"); | ||
55 | GNUNET_CONFIGURATION_destroy (cfg); | ||
56 | return GNUNET_SYSERR; | ||
57 | } | ||
58 | GNUNET_asprintf (&db_lib_name, | ||
59 | "libgnunet_plugin_namestore_%s", | ||
60 | database); | ||
61 | GNUNET_free (database); | ||
62 | db = GNUNET_PLUGIN_load (db_lib_name, (void *) cfg); | ||
63 | if (NULL == db) | ||
64 | { | ||
65 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
66 | "Failed to load plugin `%s'\n", | ||
67 | db_lib_name); | ||
68 | } | ||
69 | else | ||
70 | { | ||
71 | if (GNUNET_OK != db->create_tables (db->cls)) | ||
72 | { | ||
73 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
74 | "Error creating tables\n"); | ||
75 | return GNUNET_SYSERR; | ||
76 | } | ||
77 | if (GNUNET_OK != db->drop_tables (db->cls)) | ||
78 | { | ||
79 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
80 | "Error dropping tables\n"); | ||
81 | return GNUNET_SYSERR; | ||
82 | } | ||
83 | GNUNET_break (NULL == GNUNET_PLUGIN_unload (db_lib_name, db)); | ||
84 | } | ||
85 | GNUNET_free (db_lib_name); | ||
86 | GNUNET_CONFIGURATION_destroy (cfg); | ||
87 | if (NULL == db) | ||
88 | return GNUNET_NO; | ||
89 | return GNUNET_YES; | ||
90 | } | ||
91 | |||
92 | |||
93 | /** | ||
94 | * General setup logic for starting the tests. Obtains the @a | ||
95 | * plugin_name and initializes the @a cfg_name. | ||
96 | */ | ||
97 | #define SETUP_CFG2(file_template, plugin_name, cfg_name) \ | ||
98 | do \ | ||
99 | { \ | ||
100 | GNUNET_log_setup (__FILE__, "WARNING", NULL); \ | ||
101 | plugin_name = GNUNET_STRINGS_get_suffix_from_binary_name (argv[0]); \ | ||
102 | GNUNET_asprintf (&cfg_name, file_template, plugin_name); \ | ||
103 | if (! TNC_test_plugin (cfg_name)) \ | ||
104 | { \ | ||
105 | GNUNET_free (plugin_name); \ | ||
106 | GNUNET_free (cfg_name); \ | ||
107 | return 77; \ | ||
108 | } \ | ||
109 | GNUNET_DISK_purge_cfg_dir (cfg_name, "GNUNET_TEST_HOME"); \ | ||
110 | } while (0) | ||
111 | /** | ||
112 | * General setup logic for starting the tests. Obtains the @a | ||
113 | * plugin_name and initializes the @a cfg_name. | ||
114 | */ | ||
115 | #define SETUP_CFG(plugin_name, cfg_name) \ | ||
116 | do \ | ||
117 | { \ | ||
118 | GNUNET_log_setup (__FILE__, "WARNING", NULL); \ | ||
119 | plugin_name = GNUNET_STRINGS_get_suffix_from_binary_name (argv[0]); \ | ||
120 | GNUNET_asprintf (&cfg_name, "test_namestore_api_%s.conf", plugin_name); \ | ||
121 | if (! TNC_test_plugin (cfg_name)) \ | ||
122 | { \ | ||
123 | GNUNET_free (plugin_name); \ | ||
124 | GNUNET_free (cfg_name); \ | ||
125 | return 77; \ | ||
126 | } \ | ||
127 | GNUNET_DISK_purge_cfg_dir (cfg_name, "GNUNET_TEST_HOME"); \ | ||
128 | } 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 1648c7cae..000000000 --- a/src/namestore/test_namestore_api.conf +++ /dev/null | |||
@@ -1,43 +0,0 @@ | |||
1 | @INLINE@ ../../contrib/conf/gnunet/no_forcestart.conf | ||
2 | @INLINE@ ../../contrib/conf/gnunet/no_autostart_above_core.conf | ||
3 | |||
4 | [PATHS] | ||
5 | GNUNET_TEST_HOME = $GNUNET_TMP/test-gnunet-namestore/ | ||
6 | |||
7 | [namestore] | ||
8 | DATABASE = sqlite | ||
9 | START_ON_DEMAND = YES | ||
10 | #PREFIX = valgrind --track-origins=yes --log-file=/tmp/ns_tx.log | ||
11 | RETURN_ORPHANED = YES | ||
12 | |||
13 | [namecache] | ||
14 | DATABASE = sqlite | ||
15 | START_ON_DEMAND = YES | ||
16 | |||
17 | [zonemaster] | ||
18 | START_ON_DEMAND = YES | ||
19 | IMMEDIATE_START = NO | ||
20 | |||
21 | [dht] | ||
22 | START_ON_DEMAND = YES | ||
23 | IMMEDIATE_START = NO | ||
24 | |||
25 | |||
26 | [zonemaster-monitor] | ||
27 | START_ON_DEMAND = YES | ||
28 | IMMEDIATE_START = YES | ||
29 | |||
30 | [identity] | ||
31 | START_ON_DEMAND = YES | ||
32 | |||
33 | [nse] | ||
34 | WORKBITS = 0 | ||
35 | |||
36 | [rest] | ||
37 | BASIC_AUTH_ENABLED=NO | ||
38 | # PREFIX = valgrind --leak-check=full --track-origins=yes --log-file=/tmp/v_log | ||
39 | |||
40 | |||
41 | |||
42 | [transport] | ||
43 | PLUGINS = | ||
diff --git a/src/namestore/test_namestore_api_edit_records.c b/src/namestore/test_namestore_api_edit_records.c deleted file mode 100644 index a6bce7c17..000000000 --- a/src/namestore/test_namestore_api_edit_records.c +++ /dev/null | |||
@@ -1,399 +0,0 @@ | |||
1 | /* | ||
2 | This file is part of GNUnet. | ||
3 | Copyright (C) 2022 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_edit_records.c | ||
22 | * @brief testcase for namestore_api.c: Multiple clients work with record set. | ||
23 | */ | ||
24 | #include "platform.h" | ||
25 | #include "gnunet_namestore_service.h" | ||
26 | #include "gnunet_testing_lib.h" | ||
27 | |||
28 | #define TEST_RECORD_TYPE GNUNET_DNSPARSER_TYPE_TXT | ||
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 | |||
37 | static struct GNUNET_NAMESTORE_Handle *nsh; | ||
38 | |||
39 | static struct GNUNET_NAMESTORE_Handle *nsh2; | ||
40 | |||
41 | static struct GNUNET_SCHEDULER_Task *endbadly_task; | ||
42 | |||
43 | static struct GNUNET_CRYPTO_PrivateKey privkey; | ||
44 | |||
45 | static struct GNUNET_CRYPTO_PublicKey pubkey; | ||
46 | |||
47 | static int res; | ||
48 | |||
49 | static int removed; | ||
50 | |||
51 | static struct GNUNET_NAMESTORE_QueueEntry *nsqe; | ||
52 | |||
53 | static int nonce = 0; | ||
54 | |||
55 | static void | ||
56 | cleanup () | ||
57 | { | ||
58 | if (NULL != nsh) | ||
59 | { | ||
60 | GNUNET_NAMESTORE_disconnect (nsh); | ||
61 | nsh = NULL; | ||
62 | } | ||
63 | GNUNET_SCHEDULER_shutdown (); | ||
64 | } | ||
65 | |||
66 | |||
67 | /** | ||
68 | * Re-establish the connection to the service. | ||
69 | * | ||
70 | * @param cls handle to use to re-connect. | ||
71 | */ | ||
72 | static void | ||
73 | endbadly (void *cls) | ||
74 | { | ||
75 | if (NULL != nsqe) | ||
76 | { | ||
77 | GNUNET_NAMESTORE_cancel (nsqe); | ||
78 | nsqe = NULL; | ||
79 | } | ||
80 | cleanup (); | ||
81 | res = 1; | ||
82 | } | ||
83 | |||
84 | |||
85 | static void | ||
86 | end (void *cls) | ||
87 | { | ||
88 | cleanup (); | ||
89 | res = 0; | ||
90 | } | ||
91 | |||
92 | static void | ||
93 | lookup_it (void *cls, | ||
94 | const struct GNUNET_CRYPTO_PrivateKey *zone, | ||
95 | const char *label, | ||
96 | unsigned int rd_count, | ||
97 | const struct GNUNET_GNSRECORD_Data *rd) | ||
98 | { | ||
99 | GNUNET_assert (0 == rd_count); | ||
100 | GNUNET_SCHEDULER_add_now (&end, NULL); | ||
101 | } | ||
102 | |||
103 | static void | ||
104 | fail_cb (void *cls) | ||
105 | { | ||
106 | if (endbadly_task != NULL) | ||
107 | GNUNET_SCHEDULER_cancel (endbadly_task); | ||
108 | endbadly_task = GNUNET_SCHEDULER_add_now (&endbadly, NULL); | ||
109 | return; | ||
110 | } | ||
111 | |||
112 | static void | ||
113 | remove_cont (void *cls, | ||
114 | enum GNUNET_ErrorCode ec) | ||
115 | { | ||
116 | nsqe = NULL; | ||
117 | if (GNUNET_EC_NONE != ec) | ||
118 | { | ||
119 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
120 | _ ("Unable to roll back: `%s'\n"), | ||
121 | GNUNET_ErrorCode_get_hint (ec)); | ||
122 | if (NULL != endbadly_task) | ||
123 | GNUNET_SCHEDULER_cancel (endbadly_task); | ||
124 | endbadly_task = GNUNET_SCHEDULER_add_now (&endbadly, | ||
125 | NULL); | ||
126 | return; | ||
127 | } | ||
128 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, | ||
129 | "Rolled back, perform lookup\n"); | ||
130 | removed = GNUNET_YES; | ||
131 | if (NULL != endbadly_task) | ||
132 | GNUNET_SCHEDULER_cancel (endbadly_task); | ||
133 | GNUNET_SCHEDULER_add_now (&end, NULL); | ||
134 | } | ||
135 | |||
136 | static void | ||
137 | fail_cb_lock (void *cls); | ||
138 | |||
139 | static void | ||
140 | edit_cont_b (void *cls, | ||
141 | const struct GNUNET_CRYPTO_PrivateKey *zone, | ||
142 | const char *label, | ||
143 | unsigned int rd_count, | ||
144 | const struct GNUNET_GNSRECORD_Data *rd) | ||
145 | { | ||
146 | const char *name = cls; | ||
147 | /** | ||
148 | * We should probably never get here right at first. | ||
149 | * We may want to change the blocking of nsh2 so that we do get this | ||
150 | * eventually instead of the error callback above when locked. | ||
151 | */ | ||
152 | if (0 == nonce) | ||
153 | { | ||
154 | if (endbadly_task != NULL) | ||
155 | GNUNET_SCHEDULER_cancel (endbadly_task); | ||
156 | endbadly_task = GNUNET_SCHEDULER_add_now (&endbadly, NULL); | ||
157 | return; | ||
158 | |||
159 | } | ||
160 | /* Abort transaction for B */ | ||
161 | nsqe = GNUNET_NAMESTORE_transaction_rollback (nsh2, remove_cont, | ||
162 | (void *) name); | ||
163 | } | ||
164 | |||
165 | |||
166 | static void | ||
167 | commit_cont_a (void *cls, | ||
168 | enum GNUNET_ErrorCode ec) | ||
169 | { | ||
170 | const char *name = cls; | ||
171 | |||
172 | GNUNET_assert (NULL != cls); | ||
173 | nsqe = NULL; | ||
174 | if (GNUNET_EC_NONE != ec) | ||
175 | { | ||
176 | GNUNET_break (0); | ||
177 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
178 | "Namestore could not store record: `%s'\n", | ||
179 | GNUNET_ErrorCode_get_hint (ec)); | ||
180 | if (endbadly_task != NULL) | ||
181 | GNUNET_SCHEDULER_cancel (endbadly_task); | ||
182 | endbadly_task = GNUNET_SCHEDULER_add_now (&endbadly, NULL); | ||
183 | return; | ||
184 | } | ||
185 | |||
186 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
187 | "Name store added record for `%s': %s\n", | ||
188 | name, | ||
189 | (GNUNET_EC_NONE == ec) ? "SUCCESS" : "FAIL"); | ||
190 | /** | ||
191 | * Try again for B | ||
192 | */ | ||
193 | nsqe = GNUNET_NAMESTORE_records_edit (nsh2, | ||
194 | &privkey, | ||
195 | name, | ||
196 | &fail_cb_lock, | ||
197 | (void *) name, | ||
198 | &edit_cont_b, | ||
199 | (void *) name); | ||
200 | |||
201 | GNUNET_assert (NULL != nsqe); | ||
202 | } | ||
203 | |||
204 | static void | ||
205 | fail_cb_lock (void *cls) | ||
206 | { | ||
207 | const char *name = cls; | ||
208 | if (1 == nonce) | ||
209 | { | ||
210 | if (endbadly_task != NULL) | ||
211 | GNUNET_SCHEDULER_cancel (endbadly_task); | ||
212 | endbadly_task = GNUNET_SCHEDULER_add_now (&endbadly, NULL); | ||
213 | return; | ||
214 | } | ||
215 | nonce = 1; | ||
216 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, | ||
217 | "Failed to aquire additional lock\n"); | ||
218 | /* Now, we stop the transaction for B */ | ||
219 | nsqe = GNUNET_NAMESTORE_transaction_commit (nsh, commit_cont_a, | ||
220 | (void *) name); | ||
221 | } | ||
222 | |||
223 | |||
224 | static void | ||
225 | begin_cont_b (void *cls, | ||
226 | enum GNUNET_ErrorCode ec) | ||
227 | { | ||
228 | const char *name = cls; | ||
229 | |||
230 | GNUNET_assert (GNUNET_EC_NONE == ec); | ||
231 | /** Now, we expect this to "hang" let's see how this behaves in practice. */ | ||
232 | nsqe = GNUNET_NAMESTORE_records_edit (nsh2, | ||
233 | &privkey, | ||
234 | name, | ||
235 | &fail_cb_lock, | ||
236 | (void *) name, | ||
237 | &edit_cont_b, | ||
238 | (void *) name); | ||
239 | |||
240 | GNUNET_assert (NULL != nsqe); | ||
241 | } | ||
242 | |||
243 | |||
244 | static void | ||
245 | edit_cont (void *cls, | ||
246 | const struct GNUNET_CRYPTO_PrivateKey *zone, | ||
247 | const char *label, | ||
248 | unsigned int rd_count, | ||
249 | const struct GNUNET_GNSRECORD_Data *rd) | ||
250 | { | ||
251 | const char *name = cls; | ||
252 | |||
253 | GNUNET_assert (1 == rd_count); | ||
254 | /* Now, we start a transaction for B */ | ||
255 | nsqe = GNUNET_NAMESTORE_transaction_begin (nsh2, begin_cont_b, (void *) name); | ||
256 | } | ||
257 | |||
258 | |||
259 | static void | ||
260 | begin_cont (void *cls, | ||
261 | enum GNUNET_ErrorCode ec) | ||
262 | { | ||
263 | const char *name = cls; | ||
264 | |||
265 | GNUNET_assert (GNUNET_EC_NONE == ec); | ||
266 | nsqe = GNUNET_NAMESTORE_records_edit (nsh, | ||
267 | &privkey, | ||
268 | name, | ||
269 | &fail_cb, | ||
270 | (void *) name, | ||
271 | &edit_cont, | ||
272 | (void *) name); | ||
273 | |||
274 | GNUNET_assert (NULL != nsqe); | ||
275 | } | ||
276 | |||
277 | static void | ||
278 | preload_cont (void *cls, | ||
279 | enum GNUNET_ErrorCode ec) | ||
280 | { | ||
281 | const char *name = cls; | ||
282 | |||
283 | GNUNET_assert (NULL != cls); | ||
284 | nsqe = NULL; | ||
285 | if (GNUNET_EC_NONE != ec) | ||
286 | { | ||
287 | GNUNET_break (0); | ||
288 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
289 | "Namestore could not store record: `%s'\n", | ||
290 | GNUNET_ErrorCode_get_hint (ec)); | ||
291 | if (endbadly_task != NULL) | ||
292 | GNUNET_SCHEDULER_cancel (endbadly_task); | ||
293 | endbadly_task = GNUNET_SCHEDULER_add_now (&endbadly, NULL); | ||
294 | return; | ||
295 | } | ||
296 | |||
297 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
298 | "Name store added record for `%s': %s\n", | ||
299 | name, | ||
300 | (GNUNET_EC_NONE == ec) ? "SUCCESS" : "FAIL"); | ||
301 | /* We start transaction for A */ | ||
302 | nsqe = GNUNET_NAMESTORE_transaction_begin (nsh, begin_cont, (void *) name); | ||
303 | |||
304 | } | ||
305 | |||
306 | |||
307 | static void | ||
308 | run (void *cls, | ||
309 | const struct GNUNET_CONFIGURATION_Handle *cfg, | ||
310 | struct GNUNET_TESTING_Peer *peer) | ||
311 | { | ||
312 | struct GNUNET_GNSRECORD_Data rd; | ||
313 | const char *name = "dummy"; | ||
314 | |||
315 | endbadly_task = GNUNET_SCHEDULER_add_delayed (TIMEOUT, | ||
316 | &endbadly, | ||
317 | NULL); | ||
318 | nsh = GNUNET_NAMESTORE_connect (cfg); | ||
319 | nsh2 = GNUNET_NAMESTORE_connect (cfg); | ||
320 | GNUNET_break (NULL != nsh); | ||
321 | GNUNET_break (NULL != nsh2); | ||
322 | |||
323 | privkey.type = htonl (GNUNET_GNSRECORD_TYPE_PKEY); | ||
324 | GNUNET_CRYPTO_ecdsa_key_create (&privkey.ecdsa_key); | ||
325 | GNUNET_CRYPTO_key_get_public (&privkey, | ||
326 | &pubkey); | ||
327 | |||
328 | removed = GNUNET_NO; | ||
329 | |||
330 | rd.expiration_time = GNUNET_TIME_absolute_get ().abs_value_us; | ||
331 | rd.record_type = TEST_RECORD_TYPE; | ||
332 | rd.data_size = TEST_RECORD_DATALEN; | ||
333 | rd.data = GNUNET_malloc (TEST_RECORD_DATALEN); | ||
334 | rd.flags = 0; | ||
335 | memset ((char *) rd.data, | ||
336 | 'a', | ||
337 | TEST_RECORD_DATALEN); | ||
338 | nsqe = GNUNET_NAMESTORE_records_store (nsh, | ||
339 | &privkey, | ||
340 | name, | ||
341 | 1, | ||
342 | &rd, | ||
343 | &preload_cont, | ||
344 | (void *) name); | ||
345 | GNUNET_assert (NULL != nsqe); | ||
346 | GNUNET_free_nz ((void *) rd.data); | ||
347 | |||
348 | /*nsqe = GNUNET_NAMESTORE_transaction_commit (nsh, commit_cont); | ||
349 | nsqe = GNUNET_NAMESTORE_transaction_rollback (nsh, rollback_cont); Must also happen on disconnect | ||
350 | nsqe = GNUNET_NAMESTORE_records_edit (nsh, | ||
351 | &privkey, | ||
352 | name, | ||
353 | 1, | ||
354 | &rd, | ||
355 | &edit_cont, | ||
356 | (void *) name); | ||
357 | nsqe = GNUNET_NAMESTORE_records_insert_bulk (nsh, | ||
358 | count, | ||
359 | &rd, | ||
360 | & | ||
361 | nsqe = GNUNET_NAMESTORE_records_store (nsh, | ||
362 | &privkey, | ||
363 | name, | ||
364 | 1, | ||
365 | &rd, | ||
366 | &put_cont, | ||
367 | (void *) name);*/ | ||
368 | GNUNET_assert (NULL != nsqe); | ||
369 | } | ||
370 | |||
371 | |||
372 | #include "test_common.c" | ||
373 | |||
374 | |||
375 | int | ||
376 | main (int argc, char *argv[]) | ||
377 | { | ||
378 | const char *plugin_name; | ||
379 | char *cfg_name; | ||
380 | |||
381 | SETUP_CFG (plugin_name, cfg_name); | ||
382 | res = 1; | ||
383 | if (0 != | ||
384 | GNUNET_TESTING_peer_run ("test-namestore-api-remove", | ||
385 | cfg_name, | ||
386 | &run, | ||
387 | NULL)) | ||
388 | { | ||
389 | res = 1; | ||
390 | } | ||
391 | GNUNET_DISK_purge_cfg_dir (cfg_name, | ||
392 | "GNUNET_TEST_HOME"); | ||
393 | GNUNET_free (plugin_name); | ||
394 | GNUNET_free (cfg_name); | ||
395 | return res; | ||
396 | } | ||
397 | |||
398 | |||
399 | /* end of test_namestore_api_remove.c */ | ||
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 21fc1ef79..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 | |||
29 | #define TEST_RECORD_TYPE GNUNET_DNSPARSER_TYPE_TXT | ||
30 | |||
31 | #define TEST_RECORD_DATALEN 123 | ||
32 | |||
33 | #define TEST_NICK "gnunettestnick" | ||
34 | |||
35 | #define TEST_RECORD_DATA 'a' | ||
36 | |||
37 | #define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 10) | ||
38 | |||
39 | static struct GNUNET_NAMESTORE_Handle *nsh; | ||
40 | |||
41 | static struct GNUNET_SCHEDULER_Task *endbadly_task; | ||
42 | |||
43 | static struct GNUNET_CRYPTO_PrivateKey privkey; | ||
44 | |||
45 | static struct GNUNET_CRYPTO_PublicKey pubkey; | ||
46 | |||
47 | static int res; | ||
48 | |||
49 | static struct GNUNET_GNSRECORD_Data rd_orig; | ||
50 | |||
51 | static struct GNUNET_NAMESTORE_QueueEntry *nsqe; | ||
52 | |||
53 | // static const char * name = "dummy.dummy.gnunet"; | ||
54 | static const char *name = "d"; | ||
55 | |||
56 | static char *record_data; | ||
57 | |||
58 | static void | ||
59 | cleanup () | ||
60 | { | ||
61 | GNUNET_free (record_data); | ||
62 | if (NULL != nsh) | ||
63 | { | ||
64 | GNUNET_NAMESTORE_disconnect (nsh); | ||
65 | nsh = NULL; | ||
66 | } | ||
67 | GNUNET_SCHEDULER_shutdown (); | ||
68 | } | ||
69 | |||
70 | |||
71 | /** | ||
72 | * Re-establish the connection to the service. | ||
73 | * | ||
74 | * @param cls handle to use to re-connect. | ||
75 | * @param tc scheduler context | ||
76 | */ | ||
77 | static void | ||
78 | endbadly (void *cls) | ||
79 | { | ||
80 | if (NULL != nsqe) | ||
81 | { | ||
82 | GNUNET_NAMESTORE_cancel (nsqe); | ||
83 | nsqe = NULL; | ||
84 | } | ||
85 | cleanup (); | ||
86 | res = 1; | ||
87 | } | ||
88 | |||
89 | |||
90 | static void | ||
91 | end (void *cls) | ||
92 | { | ||
93 | cleanup (); | ||
94 | res = 0; | ||
95 | } | ||
96 | |||
97 | |||
98 | static void | ||
99 | lookup_it (void *cls, | ||
100 | const struct GNUNET_CRYPTO_PrivateKey *zone, | ||
101 | const char *label, | ||
102 | unsigned int rd_count, | ||
103 | const struct GNUNET_GNSRECORD_Data *rd) | ||
104 | { | ||
105 | nsqe = NULL; | ||
106 | int c; | ||
107 | int found_record = GNUNET_NO; | ||
108 | int found_nick = GNUNET_NO; | ||
109 | |||
110 | if (0 != GNUNET_memcmp (&privkey, zone)) | ||
111 | { | ||
112 | GNUNET_break (0); | ||
113 | GNUNET_SCHEDULER_cancel (endbadly_task); | ||
114 | endbadly_task = GNUNET_SCHEDULER_add_now (&endbadly, NULL); | ||
115 | return; | ||
116 | } | ||
117 | |||
118 | if (NULL == label) | ||
119 | { | ||
120 | GNUNET_break (0); | ||
121 | GNUNET_SCHEDULER_cancel (endbadly_task); | ||
122 | endbadly_task = GNUNET_SCHEDULER_add_now (&endbadly, NULL); | ||
123 | return; | ||
124 | } | ||
125 | |||
126 | if (0 != strcmp (label, name)) | ||
127 | { | ||
128 | GNUNET_break (0); | ||
129 | GNUNET_SCHEDULER_cancel (endbadly_task); | ||
130 | endbadly_task = GNUNET_SCHEDULER_add_now (&endbadly, NULL); | ||
131 | return; | ||
132 | } | ||
133 | |||
134 | if (2 != rd_count) | ||
135 | { | ||
136 | GNUNET_break (0); | ||
137 | GNUNET_SCHEDULER_cancel (endbadly_task); | ||
138 | endbadly_task = GNUNET_SCHEDULER_add_now (&endbadly, NULL); | ||
139 | return; | ||
140 | } | ||
141 | |||
142 | for (c = 0; c < rd_count; c++) | ||
143 | { | ||
144 | if (GNUNET_GNSRECORD_TYPE_NICK == rd[c].record_type) | ||
145 | { | ||
146 | if (rd[c].data_size != strlen (TEST_NICK) + 1) | ||
147 | { | ||
148 | GNUNET_break (0); | ||
149 | GNUNET_SCHEDULER_cancel (endbadly_task); | ||
150 | endbadly_task = GNUNET_SCHEDULER_add_now (&endbadly, NULL); | ||
151 | return; | ||
152 | } | ||
153 | if (0 != (rd[c].flags & GNUNET_GNSRECORD_RF_PRIVATE)) | ||
154 | { | ||
155 | GNUNET_break (0); | ||
156 | GNUNET_SCHEDULER_cancel (endbadly_task); | ||
157 | endbadly_task = GNUNET_SCHEDULER_add_now (&endbadly, NULL); | ||
158 | return; | ||
159 | } | ||
160 | if (0 != strcmp (rd[c].data, TEST_NICK)) | ||
161 | { | ||
162 | GNUNET_SCHEDULER_cancel (endbadly_task); | ||
163 | endbadly_task = GNUNET_SCHEDULER_add_now (&endbadly, NULL); | ||
164 | return; | ||
165 | } | ||
166 | found_nick = GNUNET_YES; | ||
167 | } | ||
168 | else | ||
169 | { | ||
170 | if (rd[c].record_type != TEST_RECORD_TYPE) | ||
171 | { | ||
172 | GNUNET_break (0); | ||
173 | GNUNET_SCHEDULER_cancel (endbadly_task); | ||
174 | endbadly_task = GNUNET_SCHEDULER_add_now (&endbadly, NULL); | ||
175 | return; | ||
176 | } | ||
177 | if (rd[c].data_size != TEST_RECORD_DATALEN) | ||
178 | { | ||
179 | GNUNET_break (0); | ||
180 | GNUNET_SCHEDULER_cancel (endbadly_task); | ||
181 | endbadly_task = GNUNET_SCHEDULER_add_now (&endbadly, NULL); | ||
182 | return; | ||
183 | } | ||
184 | if (0 != memcmp (rd[c].data, rd_orig.data, TEST_RECORD_DATALEN)) | ||
185 | { | ||
186 | GNUNET_break (0); | ||
187 | GNUNET_SCHEDULER_cancel (endbadly_task); | ||
188 | endbadly_task = GNUNET_SCHEDULER_add_now (&endbadly, NULL); | ||
189 | return; | ||
190 | } | ||
191 | if (rd[c].flags != rd->flags) | ||
192 | { | ||
193 | GNUNET_break (0); | ||
194 | GNUNET_SCHEDULER_cancel (endbadly_task); | ||
195 | endbadly_task = GNUNET_SCHEDULER_add_now (&endbadly, NULL); | ||
196 | return; | ||
197 | } | ||
198 | found_record = GNUNET_YES; | ||
199 | } | ||
200 | } | ||
201 | |||
202 | /* Done */ | ||
203 | if ((GNUNET_YES == found_nick) && (GNUNET_YES == found_record)) | ||
204 | { | ||
205 | GNUNET_SCHEDULER_cancel (endbadly_task); | ||
206 | endbadly_task = NULL; | ||
207 | GNUNET_SCHEDULER_add_now (&end, NULL); | ||
208 | } | ||
209 | else | ||
210 | { | ||
211 | GNUNET_break (0); | ||
212 | GNUNET_SCHEDULER_cancel (endbadly_task); | ||
213 | endbadly_task = NULL; | ||
214 | GNUNET_SCHEDULER_add_now (&endbadly, NULL); | ||
215 | } | ||
216 | } | ||
217 | |||
218 | |||
219 | static void | ||
220 | fail_cb (void *cls) | ||
221 | { | ||
222 | GNUNET_assert (0); | ||
223 | } | ||
224 | |||
225 | |||
226 | static void | ||
227 | put_cont (void *cls, enum GNUNET_ErrorCode ec) | ||
228 | { | ||
229 | const char *name = cls; | ||
230 | |||
231 | nsqe = NULL; | ||
232 | GNUNET_assert (NULL != cls); | ||
233 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
234 | "Name store added record for `%s': %s\n", | ||
235 | name, | ||
236 | (ec == GNUNET_EC_NONE) ? "SUCCESS" : "FAIL"); | ||
237 | |||
238 | if (GNUNET_EC_NONE != ec) | ||
239 | { | ||
240 | GNUNET_SCHEDULER_cancel (endbadly_task); | ||
241 | endbadly_task = GNUNET_SCHEDULER_add_now (&endbadly, NULL); | ||
242 | return; | ||
243 | } | ||
244 | /* Lookup */ | ||
245 | nsqe = GNUNET_NAMESTORE_records_lookup (nsh, | ||
246 | &privkey, | ||
247 | name, | ||
248 | &fail_cb, | ||
249 | NULL, | ||
250 | &lookup_it, | ||
251 | NULL); | ||
252 | } | ||
253 | |||
254 | |||
255 | static void | ||
256 | nick_cont (void *cls, enum GNUNET_ErrorCode ec) | ||
257 | { | ||
258 | const char *name = cls; | ||
259 | |||
260 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
261 | "Nick added : %s\n", | ||
262 | (ec == GNUNET_EC_NONE) ? "SUCCESS" : "FAIL"); | ||
263 | |||
264 | rd_orig.expiration_time = GNUNET_TIME_UNIT_HOURS.rel_value_us; | ||
265 | rd_orig.record_type = TEST_RECORD_TYPE; | ||
266 | rd_orig.data_size = TEST_RECORD_DATALEN; | ||
267 | record_data = GNUNET_malloc (TEST_RECORD_DATALEN); | ||
268 | rd_orig.data = record_data; | ||
269 | rd_orig.flags = GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION; | ||
270 | memset ((char *) rd_orig.data, 'a', TEST_RECORD_DATALEN); | ||
271 | |||
272 | nsqe = GNUNET_NAMESTORE_records_store (nsh, &privkey, | ||
273 | name, | ||
274 | 1, | ||
275 | &rd_orig, | ||
276 | &put_cont, (void *) name); | ||
277 | } | ||
278 | |||
279 | |||
280 | static void | ||
281 | run (void *cls, | ||
282 | const struct GNUNET_CONFIGURATION_Handle *cfg, | ||
283 | struct GNUNET_TESTING_Peer *peer) | ||
284 | { | ||
285 | struct GNUNET_GNSRECORD_Data rd; | ||
286 | |||
287 | endbadly_task = GNUNET_SCHEDULER_add_delayed (TIMEOUT, | ||
288 | &endbadly, | ||
289 | NULL); | ||
290 | privkey.type = htonl (GNUNET_GNSRECORD_TYPE_PKEY); | ||
291 | GNUNET_CRYPTO_ecdsa_key_create (&privkey.ecdsa_key); | ||
292 | GNUNET_CRYPTO_key_get_public (&privkey, | ||
293 | &pubkey); | ||
294 | |||
295 | nsh = GNUNET_NAMESTORE_connect (cfg); | ||
296 | GNUNET_break (NULL != nsh); | ||
297 | |||
298 | memset (&rd, 0, sizeof(rd)); | ||
299 | rd.data = TEST_NICK; | ||
300 | rd.data_size = strlen (TEST_NICK) + 1; | ||
301 | rd.record_type = GNUNET_GNSRECORD_TYPE_NICK; | ||
302 | rd.expiration_time = GNUNET_TIME_UNIT_FOREVER_ABS.abs_value_us; | ||
303 | rd.flags |= GNUNET_GNSRECORD_RF_PRIVATE; | ||
304 | nsqe = GNUNET_NAMESTORE_records_store (nsh, | ||
305 | &privkey, | ||
306 | GNUNET_GNS_EMPTY_LABEL_AT, | ||
307 | 1, | ||
308 | &rd, | ||
309 | &nick_cont, | ||
310 | (void *) name); | ||
311 | |||
312 | if (NULL == nsqe) | ||
313 | { | ||
314 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
315 | _ ("Namestore cannot store no block\n")); | ||
316 | } | ||
317 | } | ||
318 | |||
319 | |||
320 | #include "test_common.c" | ||
321 | |||
322 | |||
323 | int | ||
324 | main (int argc, char *argv[]) | ||
325 | { | ||
326 | const char *plugin_name; | ||
327 | char *cfg_name; | ||
328 | |||
329 | SETUP_CFG (plugin_name, cfg_name); | ||
330 | res = 1; | ||
331 | if (0 != | ||
332 | GNUNET_TESTING_peer_run ("test-namestore-api-lookup-nick", | ||
333 | cfg_name, | ||
334 | &run, | ||
335 | NULL)) | ||
336 | { | ||
337 | res = 1; | ||
338 | } | ||
339 | GNUNET_DISK_purge_cfg_dir (cfg_name, | ||
340 | "GNUNET_TEST_HOME"); | ||
341 | GNUNET_free (plugin_name); | ||
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_monitoring.c b/src/namestore/test_namestore_api_monitoring.c deleted file mode 100644 index 74dad3749..000000000 --- a/src/namestore/test_namestore_api_monitoring.c +++ /dev/null | |||
@@ -1,378 +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 | |||
29 | #define TEST_RECORD_TYPE GNUNET_DNSPARSER_TYPE_TXT | ||
30 | |||
31 | |||
32 | #define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 100) | ||
33 | |||
34 | |||
35 | static struct GNUNET_NAMESTORE_Handle *nsh; | ||
36 | |||
37 | static struct GNUNET_SCHEDULER_Task *endbadly_task; | ||
38 | |||
39 | static struct GNUNET_CRYPTO_PrivateKey privkey; | ||
40 | |||
41 | static struct GNUNET_CRYPTO_PrivateKey privkey2; | ||
42 | |||
43 | static struct GNUNET_NAMESTORE_ZoneMonitor *zm; | ||
44 | |||
45 | static int res; | ||
46 | |||
47 | static char *s_name_1; | ||
48 | |||
49 | static struct GNUNET_GNSRECORD_Data *s_rd_1; | ||
50 | |||
51 | static char *s_name_2; | ||
52 | |||
53 | static struct GNUNET_GNSRECORD_Data *s_rd_2; | ||
54 | |||
55 | static char *s_name_3; | ||
56 | |||
57 | static struct GNUNET_GNSRECORD_Data *s_rd_3; | ||
58 | |||
59 | struct GNUNET_NAMESTORE_QueueEntry *ns_ops[3]; | ||
60 | |||
61 | |||
62 | static void | ||
63 | do_shutdown () | ||
64 | { | ||
65 | if (NULL != zm) | ||
66 | { | ||
67 | GNUNET_NAMESTORE_zone_monitor_stop (zm); | ||
68 | zm = NULL; | ||
69 | } | ||
70 | if (NULL != ns_ops[0]) | ||
71 | { | ||
72 | GNUNET_NAMESTORE_cancel (ns_ops[0]); | ||
73 | ns_ops[0] = NULL; | ||
74 | } | ||
75 | if (NULL != ns_ops[1]) | ||
76 | { | ||
77 | GNUNET_NAMESTORE_cancel (ns_ops[1]); | ||
78 | ns_ops[1] = NULL; | ||
79 | } | ||
80 | if (NULL != ns_ops[2]) | ||
81 | { | ||
82 | GNUNET_NAMESTORE_cancel (ns_ops[2]); | ||
83 | ns_ops[2] = NULL; | ||
84 | } | ||
85 | if (NULL != nsh) | ||
86 | { | ||
87 | GNUNET_NAMESTORE_disconnect (nsh); | ||
88 | nsh = NULL; | ||
89 | } | ||
90 | GNUNET_free (s_name_1); | ||
91 | GNUNET_free (s_name_2); | ||
92 | GNUNET_free (s_name_3); | ||
93 | |||
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 | } | ||
110 | |||
111 | |||
112 | /** | ||
113 | * Re-establish the connection to the service. | ||
114 | * | ||
115 | * @param cls handle to use to re-connect. | ||
116 | */ | ||
117 | static void | ||
118 | endbadly (void *cls) | ||
119 | { | ||
120 | do_shutdown (); | ||
121 | res = 1; | ||
122 | } | ||
123 | |||
124 | |||
125 | static void | ||
126 | end (void *cls) | ||
127 | { | ||
128 | do_shutdown (); | ||
129 | res = 0; | ||
130 | } | ||
131 | |||
132 | |||
133 | static void | ||
134 | zone_proc (void *cls, | ||
135 | const struct GNUNET_CRYPTO_PrivateKey *zone_key, | ||
136 | const char *name, | ||
137 | unsigned int rd_count, | ||
138 | const struct GNUNET_GNSRECORD_Data *rd) | ||
139 | { | ||
140 | static int returned_records; | ||
141 | static int fail = GNUNET_NO; | ||
142 | |||
143 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
144 | "Comparing results name %s\n", | ||
145 | name); | ||
146 | if (0 != GNUNET_memcmp (zone_key, | ||
147 | &privkey)) | ||
148 | { | ||
149 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
150 | "Monitoring returned wrong zone key\n"); | ||
151 | GNUNET_break (0); | ||
152 | GNUNET_SCHEDULER_cancel (endbadly_task); | ||
153 | endbadly_task = GNUNET_SCHEDULER_add_now (&endbadly, NULL); | ||
154 | return; | ||
155 | } | ||
156 | |||
157 | if (0 == strcmp (name, s_name_1)) | ||
158 | { | ||
159 | if (GNUNET_YES != GNUNET_GNSRECORD_records_cmp (rd, s_rd_1)) | ||
160 | { | ||
161 | GNUNET_break (0); | ||
162 | fail = GNUNET_YES; | ||
163 | } | ||
164 | } | ||
165 | else if (0 == strcmp (name, s_name_2)) | ||
166 | { | ||
167 | if (GNUNET_YES != GNUNET_GNSRECORD_records_cmp (rd, s_rd_2)) | ||
168 | { | ||
169 | GNUNET_break (0); | ||
170 | fail = GNUNET_YES; | ||
171 | } | ||
172 | } | ||
173 | else | ||
174 | { | ||
175 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
176 | "Invalid name %s\n", | ||
177 | name); | ||
178 | GNUNET_break (0); | ||
179 | fail = GNUNET_YES; | ||
180 | } | ||
181 | GNUNET_NAMESTORE_zone_monitor_next (zm, | ||
182 | 1); | ||
183 | if (2 == ++returned_records) | ||
184 | { | ||
185 | if (endbadly_task != NULL) | ||
186 | { | ||
187 | GNUNET_SCHEDULER_cancel (endbadly_task); | ||
188 | endbadly_task = NULL; | ||
189 | } | ||
190 | if (GNUNET_YES == fail) | ||
191 | GNUNET_SCHEDULER_add_now (&endbadly, NULL); | ||
192 | else | ||
193 | GNUNET_SCHEDULER_add_now (&end, NULL); | ||
194 | } | ||
195 | } | ||
196 | |||
197 | |||
198 | static void | ||
199 | put_cont (void *cls, | ||
200 | enum GNUNET_ErrorCode ec) | ||
201 | { | ||
202 | static int c = 0; | ||
203 | char *label = cls; | ||
204 | |||
205 | if (0 == strcmp (label, s_name_1)) | ||
206 | ns_ops[0] = NULL; | ||
207 | else if (0 == strcmp (label, s_name_2)) | ||
208 | ns_ops[1] = NULL; | ||
209 | else if (0 == strcmp (label, s_name_3)) | ||
210 | ns_ops[2] = NULL; | ||
211 | |||
212 | if (GNUNET_EC_NONE == ec) | ||
213 | { | ||
214 | c++; | ||
215 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
216 | "Created record %u: `%s'\n", | ||
217 | c, | ||
218 | label); | ||
219 | } | ||
220 | else | ||
221 | { | ||
222 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
223 | "Failed to create record `%s'\n", | ||
224 | label); | ||
225 | GNUNET_break (0); | ||
226 | GNUNET_SCHEDULER_cancel (endbadly_task); | ||
227 | endbadly_task = GNUNET_SCHEDULER_add_now (&endbadly, | ||
228 | NULL); | ||
229 | } | ||
230 | } | ||
231 | |||
232 | |||
233 | static struct GNUNET_GNSRECORD_Data * | ||
234 | create_record (unsigned int count) | ||
235 | { | ||
236 | struct GNUNET_GNSRECORD_Data *rd; | ||
237 | |||
238 | rd = GNUNET_new_array (count, | ||
239 | struct GNUNET_GNSRECORD_Data); | ||
240 | for (unsigned int c = 0; c < count; c++) | ||
241 | { | ||
242 | rd[c].expiration_time = GNUNET_TIME_relative_to_absolute ( | ||
243 | GNUNET_TIME_UNIT_HOURS).abs_value_us; | ||
244 | rd[c].record_type = TEST_RECORD_TYPE; | ||
245 | rd[c].data_size = 50; | ||
246 | rd[c].data = GNUNET_malloc (50); | ||
247 | rd[c].flags = 0; | ||
248 | memset ((char *) rd[c].data, 'a', 50); | ||
249 | } | ||
250 | return rd; | ||
251 | } | ||
252 | |||
253 | |||
254 | static void | ||
255 | fail_cb (void *cls) | ||
256 | { | ||
257 | GNUNET_assert (0); | ||
258 | } | ||
259 | |||
260 | |||
261 | static void | ||
262 | sync_cb (void *cls) | ||
263 | { | ||
264 | /* do nothing */ | ||
265 | } | ||
266 | |||
267 | |||
268 | static void | ||
269 | run (void *cls, | ||
270 | const struct GNUNET_CONFIGURATION_Handle *cfg, | ||
271 | struct GNUNET_TESTING_Peer *peer) | ||
272 | { | ||
273 | res = 1; | ||
274 | privkey.type = htonl (GNUNET_GNSRECORD_TYPE_PKEY); | ||
275 | GNUNET_CRYPTO_ecdsa_key_create (&privkey.ecdsa_key); | ||
276 | /* Start monitoring */ | ||
277 | zm = GNUNET_NAMESTORE_zone_monitor_start (cfg, | ||
278 | &privkey, | ||
279 | GNUNET_YES, | ||
280 | &fail_cb, | ||
281 | NULL, | ||
282 | &zone_proc, | ||
283 | NULL, | ||
284 | &sync_cb, | ||
285 | NULL); | ||
286 | if (NULL == zm) | ||
287 | { | ||
288 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
289 | "Failed to create zone monitor\n"); | ||
290 | GNUNET_break (0); | ||
291 | endbadly_task = GNUNET_SCHEDULER_add_now (&endbadly, NULL); | ||
292 | return; | ||
293 | } | ||
294 | |||
295 | endbadly_task = GNUNET_SCHEDULER_add_delayed (TIMEOUT, &endbadly, NULL); | ||
296 | /* Connect to namestore */ | ||
297 | nsh = GNUNET_NAMESTORE_connect (cfg); | ||
298 | if (NULL == nsh) | ||
299 | { | ||
300 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Connect to namestore\n"); | ||
301 | GNUNET_break (0); | ||
302 | endbadly_task = GNUNET_SCHEDULER_add_now (&endbadly, NULL); | ||
303 | return; | ||
304 | } | ||
305 | |||
306 | privkey2.type = htonl (GNUNET_GNSRECORD_TYPE_PKEY); | ||
307 | GNUNET_CRYPTO_ecdsa_key_create (&privkey2.ecdsa_key); | ||
308 | |||
309 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
310 | "Created record 3\n"); | ||
311 | /* name in different zone */ | ||
312 | GNUNET_asprintf (&s_name_3, "dummy3"); | ||
313 | s_rd_3 = create_record (1); | ||
314 | GNUNET_assert (NULL != (ns_ops[2] = | ||
315 | GNUNET_NAMESTORE_records_store (nsh, | ||
316 | &privkey2, | ||
317 | s_name_3, | ||
318 | 1, | ||
319 | s_rd_3, | ||
320 | &put_cont, | ||
321 | s_name_3))); | ||
322 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
323 | "Created record 1\n"); | ||
324 | GNUNET_asprintf (&s_name_1, "dummy1"); | ||
325 | s_rd_1 = create_record (1); | ||
326 | GNUNET_assert (NULL != (ns_ops[0] = | ||
327 | GNUNET_NAMESTORE_records_store (nsh, | ||
328 | &privkey, | ||
329 | s_name_1, | ||
330 | 1, | ||
331 | s_rd_1, | ||
332 | &put_cont, | ||
333 | s_name_1))); | ||
334 | |||
335 | |||
336 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Created record 2 \n"); | ||
337 | GNUNET_asprintf (&s_name_2, "dummy2"); | ||
338 | s_rd_2 = create_record (1); | ||
339 | GNUNET_assert (NULL != (ns_ops[1] = | ||
340 | GNUNET_NAMESTORE_records_store (nsh, | ||
341 | &privkey, | ||
342 | s_name_2, | ||
343 | 1, | ||
344 | s_rd_2, | ||
345 | &put_cont, | ||
346 | s_name_2))); | ||
347 | } | ||
348 | |||
349 | |||
350 | #include "test_common.c" | ||
351 | |||
352 | |||
353 | int | ||
354 | main (int argc, | ||
355 | char *argv[]) | ||
356 | { | ||
357 | const char *plugin_name; | ||
358 | char *cfg_name; | ||
359 | |||
360 | SETUP_CFG (plugin_name, cfg_name); | ||
361 | res = 1; | ||
362 | if (0 != | ||
363 | GNUNET_TESTING_peer_run ("test-namestore-api-monitoring", | ||
364 | cfg_name, | ||
365 | &run, | ||
366 | NULL)) | ||
367 | { | ||
368 | res = 1; | ||
369 | } | ||
370 | GNUNET_DISK_purge_cfg_dir (cfg_name, | ||
371 | "GNUNET_TEST_HOME"); | ||
372 | GNUNET_free (plugin_name); | ||
373 | GNUNET_free (cfg_name); | ||
374 | return res; | ||
375 | } | ||
376 | |||
377 | |||
378 | /* 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 fe17833c8..000000000 --- a/src/namestore/test_namestore_api_monitoring_existing.c +++ /dev/null | |||
@@ -1,393 +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 | |||
29 | #define TEST_RECORD_TYPE GNUNET_DNSPARSER_TYPE_TXT | ||
30 | |||
31 | |||
32 | #define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 10) | ||
33 | |||
34 | static const struct GNUNET_CONFIGURATION_Handle *cfg; | ||
35 | |||
36 | static struct GNUNET_NAMESTORE_Handle *nsh; | ||
37 | |||
38 | static struct GNUNET_SCHEDULER_Task *endbadly_task; | ||
39 | |||
40 | static struct GNUNET_CRYPTO_PrivateKey privkey; | ||
41 | |||
42 | static struct GNUNET_CRYPTO_PrivateKey privkey2; | ||
43 | |||
44 | static struct GNUNET_NAMESTORE_ZoneMonitor *zm; | ||
45 | |||
46 | static int res; | ||
47 | |||
48 | static const char *s_name_1; | ||
49 | |||
50 | static struct GNUNET_GNSRECORD_Data *s_rd_1; | ||
51 | |||
52 | static const char *s_name_2; | ||
53 | |||
54 | static struct GNUNET_GNSRECORD_Data *s_rd_2; | ||
55 | |||
56 | static const char *s_name_3; | ||
57 | |||
58 | static struct GNUNET_GNSRECORD_Data *s_rd_3; | ||
59 | |||
60 | struct GNUNET_NAMESTORE_QueueEntry *ns_ops[3]; | ||
61 | |||
62 | |||
63 | /** | ||
64 | * Re-establish the connection to the service. | ||
65 | * | ||
66 | * @param cls handle to use to re-connect. | ||
67 | */ | ||
68 | static void | ||
69 | endbadly (void *cls) | ||
70 | { | ||
71 | endbadly_task = NULL; | ||
72 | GNUNET_break (0); | ||
73 | GNUNET_SCHEDULER_shutdown (); | ||
74 | res = 1; | ||
75 | } | ||
76 | |||
77 | |||
78 | static void | ||
79 | end (void *cls) | ||
80 | { | ||
81 | if (NULL != zm) | ||
82 | { | ||
83 | GNUNET_NAMESTORE_zone_monitor_stop (zm); | ||
84 | zm = NULL; | ||
85 | } | ||
86 | if (NULL != ns_ops[0]) | ||
87 | { | ||
88 | GNUNET_NAMESTORE_cancel (ns_ops[0]); | ||
89 | ns_ops[0] = NULL; | ||
90 | } | ||
91 | if (NULL != ns_ops[1]) | ||
92 | { | ||
93 | GNUNET_NAMESTORE_cancel (ns_ops[1]); | ||
94 | ns_ops[1] = NULL; | ||
95 | } | ||
96 | if (NULL != ns_ops[2]) | ||
97 | { | ||
98 | GNUNET_NAMESTORE_cancel (ns_ops[2]); | ||
99 | ns_ops[2] = NULL; | ||
100 | } | ||
101 | if (NULL != endbadly_task) | ||
102 | { | ||
103 | GNUNET_SCHEDULER_cancel (endbadly_task); | ||
104 | endbadly_task = NULL; | ||
105 | } | ||
106 | if (NULL != nsh) | ||
107 | { | ||
108 | GNUNET_NAMESTORE_disconnect (nsh); | ||
109 | nsh = NULL; | ||
110 | } | ||
111 | if (NULL != s_rd_1) | ||
112 | { | ||
113 | GNUNET_free_nz ((void *) s_rd_1->data); | ||
114 | GNUNET_free (s_rd_1); | ||
115 | } | ||
116 | if (NULL != s_rd_2) | ||
117 | { | ||
118 | GNUNET_free_nz ((void *) s_rd_2->data); | ||
119 | GNUNET_free (s_rd_2); | ||
120 | } | ||
121 | if (NULL != s_rd_3) | ||
122 | { | ||
123 | GNUNET_free_nz ((void *) s_rd_3->data); | ||
124 | GNUNET_free (s_rd_3); | ||
125 | } | ||
126 | } | ||
127 | |||
128 | |||
129 | static void | ||
130 | zone_proc (void *cls, | ||
131 | const struct GNUNET_CRYPTO_PrivateKey *zone_key, | ||
132 | const char *name, | ||
133 | unsigned int rd_count, | ||
134 | const struct GNUNET_GNSRECORD_Data *rd) | ||
135 | { | ||
136 | static int returned_records; | ||
137 | static int fail = GNUNET_NO; | ||
138 | |||
139 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
140 | "Comparing results name %s\n", | ||
141 | name); | ||
142 | if (0 != GNUNET_memcmp (zone_key, | ||
143 | &privkey)) | ||
144 | { | ||
145 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
146 | "Monitoring returned wrong zone key\n"); | ||
147 | GNUNET_break (0); | ||
148 | GNUNET_SCHEDULER_shutdown (); | ||
149 | return; | ||
150 | } | ||
151 | |||
152 | if (0 == strcmp (name, | ||
153 | s_name_1)) | ||
154 | { | ||
155 | if (GNUNET_YES != | ||
156 | GNUNET_GNSRECORD_records_cmp (rd, | ||
157 | s_rd_1)) | ||
158 | { | ||
159 | GNUNET_break (0); | ||
160 | fail = GNUNET_YES; | ||
161 | } | ||
162 | } | ||
163 | else if (0 == strcmp (name, | ||
164 | s_name_2)) | ||
165 | { | ||
166 | if (GNUNET_YES != | ||
167 | GNUNET_GNSRECORD_records_cmp (rd, | ||
168 | 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 | GNUNET_SCHEDULER_shutdown (); | ||
187 | if (GNUNET_YES == fail) | ||
188 | { | ||
189 | GNUNET_break (0); | ||
190 | res = 1; | ||
191 | } | ||
192 | else | ||
193 | { | ||
194 | res = 0; | ||
195 | } | ||
196 | } | ||
197 | } | ||
198 | |||
199 | |||
200 | static void | ||
201 | fail_cb (void *cls) | ||
202 | { | ||
203 | GNUNET_assert (0); | ||
204 | } | ||
205 | |||
206 | |||
207 | static void | ||
208 | sync_cb (void *cls) | ||
209 | { | ||
210 | /* do nothing */ | ||
211 | } | ||
212 | |||
213 | |||
214 | static void | ||
215 | put_cont (void *cls, | ||
216 | enum GNUNET_ErrorCode ec) | ||
217 | { | ||
218 | static int c = 0; | ||
219 | const char *label = cls; | ||
220 | |||
221 | if (0 == strcmp (label, | ||
222 | s_name_1)) | ||
223 | ns_ops[0] = NULL; | ||
224 | else if (0 == strcmp (label, | ||
225 | s_name_2)) | ||
226 | ns_ops[1] = NULL; | ||
227 | else if (0 == strcmp (label, | ||
228 | s_name_3)) | ||
229 | ns_ops[2] = NULL; | ||
230 | |||
231 | if (GNUNET_EC_NONE == ec) | ||
232 | { | ||
233 | c++; | ||
234 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
235 | "Created record %u: `%s'\n", | ||
236 | c, | ||
237 | label); | ||
238 | } | ||
239 | else | ||
240 | { | ||
241 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
242 | "Failed to created records\n"); | ||
243 | GNUNET_break (0); | ||
244 | res = 1; | ||
245 | GNUNET_SCHEDULER_shutdown (); | ||
246 | return; | ||
247 | } | ||
248 | |||
249 | } | ||
250 | |||
251 | |||
252 | static struct GNUNET_GNSRECORD_Data * | ||
253 | create_record (unsigned int count) | ||
254 | { | ||
255 | struct GNUNET_GNSRECORD_Data *rd; | ||
256 | |||
257 | rd = GNUNET_new_array (count, | ||
258 | struct GNUNET_GNSRECORD_Data); | ||
259 | for (unsigned int c = 0; c < count; c++) | ||
260 | { | ||
261 | rd[c].expiration_time = GNUNET_TIME_relative_to_absolute ( | ||
262 | GNUNET_TIME_UNIT_HOURS).abs_value_us; | ||
263 | rd[c].record_type = TEST_RECORD_TYPE; | ||
264 | rd[c].data_size = 50; | ||
265 | rd[c].data = GNUNET_malloc (50); | ||
266 | rd[c].flags = 0; | ||
267 | memset ((char *) rd[c].data, | ||
268 | 'a', | ||
269 | 50); | ||
270 | } | ||
271 | return rd; | ||
272 | } | ||
273 | |||
274 | |||
275 | static void | ||
276 | run (void *cls, | ||
277 | const struct GNUNET_CONFIGURATION_Handle *mycfg, | ||
278 | struct GNUNET_TESTING_Peer *peer) | ||
279 | { | ||
280 | res = 1; | ||
281 | privkey.type = htonl (GNUNET_GNSRECORD_TYPE_PKEY); | ||
282 | privkey2.type = htonl (GNUNET_GNSRECORD_TYPE_PKEY); | ||
283 | GNUNET_CRYPTO_ecdsa_key_create (&privkey.ecdsa_key); | ||
284 | GNUNET_CRYPTO_ecdsa_key_create (&privkey2.ecdsa_key); | ||
285 | |||
286 | cfg = mycfg; | ||
287 | GNUNET_SCHEDULER_add_shutdown (&end, | ||
288 | NULL); | ||
289 | endbadly_task = GNUNET_SCHEDULER_add_delayed (TIMEOUT, | ||
290 | &endbadly, | ||
291 | NULL); | ||
292 | /* Connect to namestore */ | ||
293 | nsh = GNUNET_NAMESTORE_connect (cfg); | ||
294 | if (NULL == nsh) | ||
295 | { | ||
296 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
297 | "Connect to namestore failed\n"); | ||
298 | GNUNET_break (0); | ||
299 | endbadly_task = GNUNET_SCHEDULER_add_now (&endbadly, | ||
300 | NULL); | ||
301 | return; | ||
302 | } | ||
303 | /* Start monitoring */ | ||
304 | zm = GNUNET_NAMESTORE_zone_monitor_start (cfg, | ||
305 | &privkey, | ||
306 | GNUNET_YES, | ||
307 | &fail_cb, | ||
308 | NULL, | ||
309 | &zone_proc, | ||
310 | NULL, | ||
311 | &sync_cb, | ||
312 | NULL); | ||
313 | if (NULL == zm) | ||
314 | { | ||
315 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
316 | "Failed to create zone monitor\n"); | ||
317 | GNUNET_break (0); | ||
318 | res = 1; | ||
319 | GNUNET_SCHEDULER_shutdown (); | ||
320 | return; | ||
321 | } | ||
322 | |||
323 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
324 | "Created record 3\n"); | ||
325 | /* name in different zone */ | ||
326 | s_name_3 = "dummy3"; | ||
327 | s_rd_3 = create_record (1); | ||
328 | GNUNET_assert (NULL != (ns_ops[2] = | ||
329 | GNUNET_NAMESTORE_records_store (nsh, | ||
330 | &privkey2, | ||
331 | s_name_3, | ||
332 | 1, | ||
333 | s_rd_3, | ||
334 | &put_cont, | ||
335 | (void *) s_name_3))); | ||
336 | |||
337 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
338 | "Created record 1\n"); | ||
339 | s_name_1 = "dummy1"; | ||
340 | s_rd_1 = create_record (1); | ||
341 | GNUNET_assert (NULL != (ns_ops[0] = | ||
342 | GNUNET_NAMESTORE_records_store (nsh, | ||
343 | &privkey, | ||
344 | s_name_1, | ||
345 | 1, | ||
346 | s_rd_1, | ||
347 | &put_cont, | ||
348 | (void *) s_name_1))); | ||
349 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
350 | "Created record 2 \n"); | ||
351 | s_name_2 = "dummy2"; | ||
352 | s_rd_2 = create_record (1); | ||
353 | GNUNET_assert (NULL != (ns_ops[1] = | ||
354 | GNUNET_NAMESTORE_records_store (nsh, | ||
355 | &privkey, | ||
356 | s_name_2, | ||
357 | 1, | ||
358 | s_rd_2, | ||
359 | &put_cont, | ||
360 | (void *) s_name_2))); | ||
361 | } | ||
362 | |||
363 | |||
364 | #include "test_common.c" | ||
365 | |||
366 | |||
367 | int | ||
368 | main (int argc, | ||
369 | char *argv[]) | ||
370 | { | ||
371 | const char *plugin_name; | ||
372 | char *cfg_name; | ||
373 | |||
374 | SETUP_CFG (plugin_name, cfg_name); | ||
375 | res = 1; | ||
376 | if (0 != | ||
377 | GNUNET_TESTING_peer_run ("test-namestore-api-monitoring-existing", | ||
378 | cfg_name, | ||
379 | &run, | ||
380 | NULL)) | ||
381 | { | ||
382 | GNUNET_break (0); | ||
383 | res = 1; | ||
384 | } | ||
385 | GNUNET_DISK_purge_cfg_dir (cfg_name, | ||
386 | "GNUNET_TEST_HOME"); | ||
387 | GNUNET_free (plugin_name); | ||
388 | GNUNET_free (cfg_name); | ||
389 | return res; | ||
390 | } | ||
391 | |||
392 | |||
393 | /* 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 007168280..000000000 --- a/src/namestore/test_namestore_api_postgres.conf +++ /dev/null | |||
@@ -1,10 +0,0 @@ | |||
1 | @INLINE@ test_namestore_api.conf | ||
2 | |||
3 | [namestore] | ||
4 | DATABASE = postgres | ||
5 | |||
6 | |||
7 | [namestore-postgres] | ||
8 | CONFIG = connect_timeout=10 dbname=gnunetcheck | ||
9 | TEMPORARY_TABLE = NO | ||
10 | INIT_ON_CONNECT = YES | ||
diff --git a/src/namestore/test_namestore_api_remove.c b/src/namestore/test_namestore_api_remove.c deleted file mode 100644 index 1a4a7c867..000000000 --- a/src/namestore/test_namestore_api_remove.c +++ /dev/null | |||
@@ -1,219 +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 | |||
28 | #define TEST_RECORD_TYPE GNUNET_DNSPARSER_TYPE_TXT | ||
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 | |||
37 | static struct GNUNET_NAMESTORE_Handle *nsh; | ||
38 | |||
39 | static struct GNUNET_SCHEDULER_Task *endbadly_task; | ||
40 | |||
41 | static struct GNUNET_CRYPTO_PrivateKey privkey; | ||
42 | |||
43 | static struct GNUNET_CRYPTO_PublicKey pubkey; | ||
44 | |||
45 | static int res; | ||
46 | |||
47 | static int removed; | ||
48 | |||
49 | static struct GNUNET_NAMESTORE_QueueEntry *nsqe; | ||
50 | |||
51 | |||
52 | static void | ||
53 | cleanup () | ||
54 | { | ||
55 | if (NULL != nsh) | ||
56 | { | ||
57 | GNUNET_NAMESTORE_disconnect (nsh); | ||
58 | nsh = NULL; | ||
59 | } | ||
60 | GNUNET_SCHEDULER_shutdown (); | ||
61 | } | ||
62 | |||
63 | |||
64 | /** | ||
65 | * Re-establish the connection to the service. | ||
66 | * | ||
67 | * @param cls handle to use to re-connect. | ||
68 | */ | ||
69 | static void | ||
70 | endbadly (void *cls) | ||
71 | { | ||
72 | if (NULL != nsqe) | ||
73 | { | ||
74 | GNUNET_NAMESTORE_cancel (nsqe); | ||
75 | nsqe = NULL; | ||
76 | } | ||
77 | cleanup (); | ||
78 | res = 1; | ||
79 | } | ||
80 | |||
81 | |||
82 | static void | ||
83 | end (void *cls) | ||
84 | { | ||
85 | cleanup (); | ||
86 | res = 0; | ||
87 | } | ||
88 | |||
89 | |||
90 | static void | ||
91 | remove_cont (void *cls, | ||
92 | enum GNUNET_ErrorCode ec) | ||
93 | { | ||
94 | nsqe = NULL; | ||
95 | if (GNUNET_EC_NONE != ec) | ||
96 | { | ||
97 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
98 | _ ("Records could not be removed: `%s'\n"), | ||
99 | GNUNET_ErrorCode_get_hint (ec)); | ||
100 | if (NULL != endbadly_task) | ||
101 | GNUNET_SCHEDULER_cancel (endbadly_task); | ||
102 | endbadly_task = GNUNET_SCHEDULER_add_now (&endbadly, | ||
103 | NULL); | ||
104 | return; | ||
105 | } | ||
106 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, | ||
107 | "Records were removed, perform lookup\n"); | ||
108 | removed = GNUNET_YES; | ||
109 | if (NULL != endbadly_task) | ||
110 | GNUNET_SCHEDULER_cancel (endbadly_task); | ||
111 | GNUNET_SCHEDULER_add_now (&end, NULL); | ||
112 | } | ||
113 | |||
114 | |||
115 | static void | ||
116 | put_cont (void *cls, | ||
117 | enum GNUNET_ErrorCode ec) | ||
118 | { | ||
119 | const char *name = cls; | ||
120 | |||
121 | GNUNET_assert (NULL != cls); | ||
122 | nsqe = NULL; | ||
123 | if (GNUNET_EC_NONE != ec) | ||
124 | { | ||
125 | GNUNET_break (0); | ||
126 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
127 | "Namestore could not store record: `%s'\n", | ||
128 | GNUNET_ErrorCode_get_hint (ec)); | ||
129 | if (endbadly_task != NULL) | ||
130 | GNUNET_SCHEDULER_cancel (endbadly_task); | ||
131 | endbadly_task = GNUNET_SCHEDULER_add_now (&endbadly, NULL); | ||
132 | return; | ||
133 | } | ||
134 | |||
135 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
136 | "Name store added record for `%s': %s\n", | ||
137 | name, | ||
138 | (GNUNET_EC_NONE == ec) ? "SUCCESS" : "FAIL"); | ||
139 | nsqe = GNUNET_NAMESTORE_records_store (nsh, | ||
140 | &privkey, | ||
141 | name, | ||
142 | 0, NULL, | ||
143 | &remove_cont, (void *) name); | ||
144 | } | ||
145 | |||
146 | |||
147 | static void | ||
148 | run (void *cls, | ||
149 | const struct GNUNET_CONFIGURATION_Handle *cfg, | ||
150 | struct GNUNET_TESTING_Peer *peer) | ||
151 | { | ||
152 | struct GNUNET_GNSRECORD_Data rd; | ||
153 | const char *name = "dummy"; | ||
154 | |||
155 | endbadly_task = GNUNET_SCHEDULER_add_delayed (TIMEOUT, | ||
156 | &endbadly, | ||
157 | NULL); | ||
158 | privkey.type = htonl (GNUNET_GNSRECORD_TYPE_PKEY); | ||
159 | GNUNET_CRYPTO_ecdsa_key_create (&privkey.ecdsa_key); | ||
160 | GNUNET_CRYPTO_key_get_public (&privkey, | ||
161 | &pubkey); | ||
162 | |||
163 | removed = GNUNET_NO; | ||
164 | |||
165 | rd.expiration_time = GNUNET_TIME_UNIT_MINUTES.rel_value_us; | ||
166 | rd.record_type = TEST_RECORD_TYPE; | ||
167 | rd.data_size = TEST_RECORD_DATALEN; | ||
168 | rd.data = GNUNET_malloc (TEST_RECORD_DATALEN); | ||
169 | rd.flags = GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION; | ||
170 | memset ((char *) rd.data, | ||
171 | 'a', | ||
172 | TEST_RECORD_DATALEN); | ||
173 | |||
174 | nsh = GNUNET_NAMESTORE_connect (cfg); | ||
175 | GNUNET_break (NULL != nsh); | ||
176 | nsqe = GNUNET_NAMESTORE_records_store (nsh, | ||
177 | &privkey, | ||
178 | name, | ||
179 | 1, | ||
180 | &rd, | ||
181 | &put_cont, | ||
182 | (void *) name); | ||
183 | if (NULL == nsqe) | ||
184 | { | ||
185 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
186 | _ ("Namestore cannot store no block\n")); | ||
187 | } | ||
188 | GNUNET_free_nz ((void *) rd.data); | ||
189 | } | ||
190 | |||
191 | |||
192 | #include "test_common.c" | ||
193 | |||
194 | |||
195 | int | ||
196 | main (int argc, char *argv[]) | ||
197 | { | ||
198 | const char *plugin_name; | ||
199 | char *cfg_name; | ||
200 | |||
201 | SETUP_CFG (plugin_name, cfg_name); | ||
202 | res = 1; | ||
203 | if (0 != | ||
204 | GNUNET_TESTING_peer_run ("test-namestore-api-remove", | ||
205 | cfg_name, | ||
206 | &run, | ||
207 | NULL)) | ||
208 | { | ||
209 | res = 1; | ||
210 | } | ||
211 | GNUNET_DISK_purge_cfg_dir (cfg_name, | ||
212 | "GNUNET_TEST_HOME"); | ||
213 | GNUNET_free (plugin_name); | ||
214 | GNUNET_free (cfg_name); | ||
215 | return res; | ||
216 | } | ||
217 | |||
218 | |||
219 | /* 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 11a69bea1..000000000 --- a/src/namestore/test_namestore_api_remove_not_existing_record.c +++ /dev/null | |||
@@ -1,179 +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 | |||
37 | static struct GNUNET_NAMESTORE_Handle *nsh; | ||
38 | |||
39 | static struct GNUNET_SCHEDULER_Task *endbadly_task; | ||
40 | |||
41 | static struct GNUNET_CRYPTO_PrivateKey privkey; | ||
42 | |||
43 | static struct GNUNET_CRYPTO_PublicKey pubkey; | ||
44 | |||
45 | static int res; | ||
46 | |||
47 | static struct GNUNET_NAMESTORE_QueueEntry *nsqe; | ||
48 | |||
49 | |||
50 | static void | ||
51 | cleanup (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 | */ | ||
67 | static void | ||
68 | endbadly (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 | |||
80 | static void | ||
81 | end (void *cls) | ||
82 | { | ||
83 | cleanup (); | ||
84 | res = 0; | ||
85 | } | ||
86 | |||
87 | |||
88 | static void | ||
89 | put_cont (void *cls, | ||
90 | enum GNUNET_ErrorCode ec) | ||
91 | { | ||
92 | GNUNET_assert (NULL != cls); | ||
93 | nsqe = NULL; | ||
94 | if (endbadly_task != NULL) | ||
95 | { | ||
96 | GNUNET_SCHEDULER_cancel (endbadly_task); | ||
97 | endbadly_task = NULL; | ||
98 | } | ||
99 | switch (ec) | ||
100 | { | ||
101 | case GNUNET_EC_NAMESTORE_RECORD_NOT_FOUND: | ||
102 | /* We expect that the record is not found */ | ||
103 | GNUNET_SCHEDULER_add_now (&end, NULL); | ||
104 | break; | ||
105 | |||
106 | case GNUNET_EC_NONE: | ||
107 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
108 | "Namestore could remove non-existing record: `%s'\n", | ||
109 | GNUNET_ErrorCode_get_hint (ec)); | ||
110 | GNUNET_SCHEDULER_add_now (&endbadly, NULL); | ||
111 | break; | ||
112 | |||
113 | default: | ||
114 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
115 | "Namestore failed: `%s'\n", | ||
116 | GNUNET_ErrorCode_get_hint (ec)); | ||
117 | GNUNET_SCHEDULER_add_now (&endbadly, NULL); | ||
118 | break; | ||
119 | } | ||
120 | } | ||
121 | |||
122 | |||
123 | static void | ||
124 | run (void *cls, | ||
125 | const struct GNUNET_CONFIGURATION_Handle *cfg, | ||
126 | struct GNUNET_TESTING_Peer *peer) | ||
127 | { | ||
128 | const char *name = "dummy"; | ||
129 | |||
130 | endbadly_task = GNUNET_SCHEDULER_add_delayed (TIMEOUT, | ||
131 | &endbadly, | ||
132 | NULL); | ||
133 | privkey.type = htonl (GNUNET_GNSRECORD_TYPE_PKEY); | ||
134 | GNUNET_CRYPTO_ecdsa_key_create (&privkey.ecdsa_key); | ||
135 | GNUNET_CRYPTO_key_get_public (&privkey, &pubkey); | ||
136 | |||
137 | nsh = GNUNET_NAMESTORE_connect (cfg); | ||
138 | GNUNET_break (NULL != nsh); | ||
139 | nsqe = GNUNET_NAMESTORE_records_store (nsh, | ||
140 | &privkey, | ||
141 | name, | ||
142 | 0, NULL, | ||
143 | &put_cont, (void *) name); | ||
144 | if (NULL == nsqe) | ||
145 | { | ||
146 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
147 | _ ("Namestore cannot store no block\n")); | ||
148 | } | ||
149 | } | ||
150 | |||
151 | |||
152 | #include "test_common.c" | ||
153 | |||
154 | |||
155 | int | ||
156 | main (int argc, char *argv[]) | ||
157 | { | ||
158 | const char *plugin_name; | ||
159 | char *cfg_name; | ||
160 | |||
161 | SETUP_CFG (plugin_name, cfg_name); | ||
162 | res = 1; | ||
163 | if (0 != | ||
164 | GNUNET_TESTING_peer_run ("test-namestore-api-remove-non-existing-record", | ||
165 | cfg_name, | ||
166 | &run, | ||
167 | NULL)) | ||
168 | { | ||
169 | res = 1; | ||
170 | } | ||
171 | GNUNET_DISK_purge_cfg_dir (cfg_name, | ||
172 | "GNUNET_TEST_HOME"); | ||
173 | GNUNET_free (plugin_name); | ||
174 | GNUNET_free (cfg_name); | ||
175 | return res; | ||
176 | } | ||
177 | |||
178 | |||
179 | /* 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 342356247..000000000 --- a/src/namestore/test_namestore_api_sqlite.conf +++ /dev/null | |||
@@ -1,9 +0,0 @@ | |||
1 | @INLINE@ test_namestore_api.conf | ||
2 | |||
3 | [namestore] | ||
4 | DATABASE = sqlite | ||
5 | # PREFIX = valgrind --leak-check=full --track-origins=yes --log-file=/tmp/v_log | ||
6 | |||
7 | [namestore-sqlite] | ||
8 | FILENAME = $GNUNET_TEST_HOME/namestore/sqlite_test.db | ||
9 | INIT_ON_CONNECT = YES | ||
diff --git a/src/namestore/test_namestore_api_store.c b/src/namestore/test_namestore_api_store.c deleted file mode 100644 index 22b92fbe5..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 | |||
28 | #define TEST_RECORD_TYPE GNUNET_DNSPARSER_TYPE_TXT | ||
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 | |||
37 | static struct GNUNET_NAMESTORE_Handle *nsh; | ||
38 | |||
39 | static struct GNUNET_SCHEDULER_Task *endbadly_task; | ||
40 | |||
41 | static struct GNUNET_CRYPTO_PrivateKey privkey; | ||
42 | |||
43 | static struct GNUNET_CRYPTO_PublicKey pubkey; | ||
44 | |||
45 | static int res; | ||
46 | |||
47 | static struct GNUNET_NAMESTORE_QueueEntry *nsqe; | ||
48 | |||
49 | |||
50 | static void | ||
51 | cleanup () | ||
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 | */ | ||
67 | static void | ||
68 | endbadly (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 | |||
80 | static void | ||
81 | end (void *cls) | ||
82 | { | ||
83 | cleanup (); | ||
84 | res = 0; | ||
85 | } | ||
86 | |||
87 | |||
88 | static void | ||
89 | put_cont (void *cls, enum GNUNET_ErrorCode ec) | ||
90 | { | ||
91 | const char *name = cls; | ||
92 | |||
93 | nsqe = NULL; | ||
94 | GNUNET_assert (NULL != cls); | ||
95 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
96 | "Name store added record for `%s': %s\n", | ||
97 | name, | ||
98 | (GNUNET_EC_NONE == ec) ? "SUCCESS" : "FAIL"); | ||
99 | GNUNET_SCHEDULER_cancel (endbadly_task); | ||
100 | endbadly_task = NULL; | ||
101 | GNUNET_SCHEDULER_add_now (&end, NULL); | ||
102 | } | ||
103 | |||
104 | |||
105 | static void | ||
106 | run (void *cls, | ||
107 | const struct GNUNET_CONFIGURATION_Handle *cfg, | ||
108 | struct GNUNET_TESTING_Peer *peer) | ||
109 | { | ||
110 | struct GNUNET_GNSRECORD_Data rd; | ||
111 | const char *name = "dummy.dummy.gnunet"; | ||
112 | |||
113 | endbadly_task = GNUNET_SCHEDULER_add_delayed (TIMEOUT, | ||
114 | &endbadly, NULL); | ||
115 | privkey.type = htonl (GNUNET_GNSRECORD_TYPE_PKEY); | ||
116 | GNUNET_CRYPTO_ecdsa_key_create (&privkey.ecdsa_key); | ||
117 | GNUNET_CRYPTO_key_get_public (&privkey, &pubkey); | ||
118 | |||
119 | |||
120 | rd.expiration_time = GNUNET_TIME_absolute_get ().abs_value_us; | ||
121 | rd.record_type = TEST_RECORD_TYPE; | ||
122 | rd.data_size = TEST_RECORD_DATALEN; | ||
123 | rd.data = GNUNET_malloc (TEST_RECORD_DATALEN); | ||
124 | rd.flags = 0; | ||
125 | memset ((char *) rd.data, 'a', TEST_RECORD_DATALEN); | ||
126 | |||
127 | nsh = GNUNET_NAMESTORE_connect (cfg); | ||
128 | GNUNET_break (NULL != nsh); | ||
129 | nsqe = GNUNET_NAMESTORE_records_store (nsh, | ||
130 | &privkey, | ||
131 | name, | ||
132 | 1, | ||
133 | &rd, | ||
134 | &put_cont, | ||
135 | (void *) name); | ||
136 | if (NULL == nsqe) | ||
137 | { | ||
138 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
139 | _ ("Namestore cannot store no block\n")); | ||
140 | } | ||
141 | GNUNET_free_nz ((void *) rd.data); | ||
142 | } | ||
143 | |||
144 | |||
145 | #include "test_common.c" | ||
146 | |||
147 | |||
148 | int | ||
149 | main (int argc, char *argv[]) | ||
150 | { | ||
151 | const char *plugin_name; | ||
152 | char *cfg_name; | ||
153 | |||
154 | SETUP_CFG (plugin_name, cfg_name); | ||
155 | res = 1; | ||
156 | if (0 != | ||
157 | GNUNET_TESTING_peer_run ("test-namestore-api", | ||
158 | cfg_name, | ||
159 | &run, | ||
160 | NULL)) | ||
161 | { | ||
162 | res = 1; | ||
163 | } | ||
164 | GNUNET_DISK_purge_cfg_dir (cfg_name, | ||
165 | "GNUNET_TEST_HOME"); | ||
166 | GNUNET_free (plugin_name); | ||
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 86495e261..000000000 --- a/src/namestore/test_namestore_api_store_update.c +++ /dev/null | |||
@@ -1,269 +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_namestore_service.h" | ||
28 | #include "gnunet_testing_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 TEST_RECORD_DATALEN2 234 | ||
37 | |||
38 | #define TEST_RECORD_DATA2 'b' | ||
39 | |||
40 | #define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 100) | ||
41 | |||
42 | |||
43 | static struct GNUNET_NAMESTORE_Handle *nsh; | ||
44 | |||
45 | static struct GNUNET_SCHEDULER_Task *endbadly_task; | ||
46 | |||
47 | static struct GNUNET_CRYPTO_PrivateKey privkey; | ||
48 | |||
49 | static struct GNUNET_CRYPTO_PublicKey pubkey; | ||
50 | |||
51 | static int res; | ||
52 | |||
53 | static int update_performed; | ||
54 | |||
55 | static struct GNUNET_NAMESTORE_QueueEntry *nsqe; | ||
56 | |||
57 | static const char *name = "dummy"; | ||
58 | |||
59 | |||
60 | /** | ||
61 | * Terminate test with error. | ||
62 | * | ||
63 | * @param cls handle to use to re-connect. | ||
64 | */ | ||
65 | static void | ||
66 | endbadly (void *cls) | ||
67 | { | ||
68 | GNUNET_break (0); | ||
69 | endbadly_task = NULL; | ||
70 | GNUNET_SCHEDULER_shutdown (); | ||
71 | res = 1; | ||
72 | } | ||
73 | |||
74 | |||
75 | static void | ||
76 | end (void *cls) | ||
77 | { | ||
78 | if (NULL != endbadly_task) | ||
79 | { | ||
80 | GNUNET_SCHEDULER_cancel (endbadly_task); | ||
81 | endbadly_task = NULL; | ||
82 | } | ||
83 | if (NULL != nsqe) | ||
84 | { | ||
85 | GNUNET_NAMESTORE_cancel (nsqe); | ||
86 | nsqe = NULL; | ||
87 | } | ||
88 | if (NULL != nsh) | ||
89 | { | ||
90 | GNUNET_NAMESTORE_disconnect (nsh); | ||
91 | nsh = NULL; | ||
92 | } | ||
93 | } | ||
94 | |||
95 | |||
96 | static void | ||
97 | put_cont (void *cls, | ||
98 | enum GNUNET_ErrorCode ec); | ||
99 | |||
100 | |||
101 | static void | ||
102 | lookup_success (void *cls, | ||
103 | const struct GNUNET_CRYPTO_PrivateKey *zone, | ||
104 | const char* label, | ||
105 | unsigned int rd_count, | ||
106 | const struct GNUNET_GNSRECORD_Data *rd) | ||
107 | { | ||
108 | struct GNUNET_GNSRECORD_Data rd_new; | ||
109 | |||
110 | GNUNET_assert (1 == rd_count); | ||
111 | GNUNET_assert (NULL != rd); | ||
112 | nsqe = NULL; | ||
113 | if (GNUNET_NO == update_performed) | ||
114 | { | ||
115 | char rd_cmp_data[TEST_RECORD_DATALEN]; | ||
116 | |||
117 | memset (rd_cmp_data, | ||
118 | TEST_RECORD_DATA, | ||
119 | TEST_RECORD_DATALEN); | ||
120 | GNUNET_assert (TEST_RECORD_TYPE == rd[0].record_type); | ||
121 | GNUNET_assert (TEST_RECORD_DATALEN == rd[0].data_size); | ||
122 | GNUNET_assert (0 == memcmp (&rd_cmp_data, | ||
123 | rd[0].data, | ||
124 | TEST_RECORD_DATALEN)); | ||
125 | |||
126 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
127 | "Block was decrypted successfully, updating record \n"); | ||
128 | |||
129 | rd_new.flags = GNUNET_GNSRECORD_RF_NONE; | ||
130 | rd_new.expiration_time = GNUNET_TIME_absolute_get ().abs_value_us | ||
131 | + 1000000000; | ||
132 | rd_new.record_type = TEST_RECORD_TYPE; | ||
133 | rd_new.data_size = TEST_RECORD_DATALEN2; | ||
134 | rd_new.data = GNUNET_malloc (TEST_RECORD_DATALEN2); | ||
135 | memset ((char *) rd_new.data, | ||
136 | TEST_RECORD_DATA2, | ||
137 | TEST_RECORD_DATALEN2); | ||
138 | |||
139 | nsqe = GNUNET_NAMESTORE_records_store (nsh, | ||
140 | &privkey, | ||
141 | name, | ||
142 | 1, | ||
143 | &rd_new, | ||
144 | &put_cont, | ||
145 | (void *) name); | ||
146 | GNUNET_free (rd_new.data); | ||
147 | update_performed = GNUNET_YES; | ||
148 | } | ||
149 | else | ||
150 | { | ||
151 | char rd_cmp_data[TEST_RECORD_DATALEN2]; | ||
152 | |||
153 | memset (rd_cmp_data, | ||
154 | TEST_RECORD_DATA2, | ||
155 | TEST_RECORD_DATALEN2); | ||
156 | GNUNET_assert (TEST_RECORD_TYPE == rd[0].record_type); | ||
157 | GNUNET_assert (TEST_RECORD_DATALEN2 == rd[0].data_size); | ||
158 | GNUNET_assert (0 == memcmp (&rd_cmp_data, | ||
159 | rd[0].data, | ||
160 | TEST_RECORD_DATALEN2)); | ||
161 | GNUNET_SCHEDULER_shutdown (); | ||
162 | res = 0; | ||
163 | } | ||
164 | } | ||
165 | |||
166 | |||
167 | static void | ||
168 | put_cont (void *cls, | ||
169 | enum GNUNET_ErrorCode ec) | ||
170 | { | ||
171 | const char *name = cls; | ||
172 | struct GNUNET_HashCode derived_hash; | ||
173 | |||
174 | nsqe = NULL; | ||
175 | GNUNET_assert (NULL != cls); | ||
176 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
177 | "Name store added record for `%s': %s\n", | ||
178 | name, | ||
179 | (GNUNET_EC_NONE == ec) ? "SUCCESS" : "FAIL"); | ||
180 | /* Create derived hash */ | ||
181 | GNUNET_GNSRECORD_query_from_private_key (&privkey, | ||
182 | name, | ||
183 | &derived_hash); | ||
184 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
185 | "Looking in namestore for `%s'\n", | ||
186 | GNUNET_h2s (&derived_hash)); | ||
187 | nsqe = GNUNET_NAMESTORE_records_lookup (nsh, | ||
188 | &privkey, | ||
189 | name, | ||
190 | &endbadly, | ||
191 | (void *) name, | ||
192 | & lookup_success, | ||
193 | (void *) name); | ||
194 | } | ||
195 | |||
196 | |||
197 | static void | ||
198 | run (void *cls, | ||
199 | const struct GNUNET_CONFIGURATION_Handle *cfg, | ||
200 | struct GNUNET_TESTING_Peer *peer) | ||
201 | { | ||
202 | struct GNUNET_GNSRECORD_Data rd; | ||
203 | |||
204 | update_performed = GNUNET_NO; | ||
205 | GNUNET_SCHEDULER_add_shutdown (&end, | ||
206 | NULL); | ||
207 | endbadly_task = GNUNET_SCHEDULER_add_delayed (TIMEOUT, | ||
208 | &endbadly, | ||
209 | NULL); | ||
210 | memset (&privkey, 0, sizeof (privkey)); | ||
211 | privkey.type = htonl (GNUNET_GNSRECORD_TYPE_PKEY); | ||
212 | GNUNET_CRYPTO_ecdsa_key_create (&privkey.ecdsa_key); | ||
213 | GNUNET_CRYPTO_key_get_public (&privkey, &pubkey); | ||
214 | rd.flags = GNUNET_GNSRECORD_RF_NONE; | ||
215 | rd.expiration_time = GNUNET_TIME_absolute_get ().abs_value_us + 1000000000; | ||
216 | rd.record_type = TEST_RECORD_TYPE; | ||
217 | rd.data_size = TEST_RECORD_DATALEN; | ||
218 | rd.data = GNUNET_malloc (TEST_RECORD_DATALEN); | ||
219 | memset ((char *) rd.data, | ||
220 | TEST_RECORD_DATA, | ||
221 | TEST_RECORD_DATALEN); | ||
222 | |||
223 | nsh = GNUNET_NAMESTORE_connect (cfg); | ||
224 | GNUNET_break (NULL != nsh); | ||
225 | nsqe = GNUNET_NAMESTORE_records_store (nsh, | ||
226 | &privkey, | ||
227 | name, | ||
228 | 1, | ||
229 | &rd, | ||
230 | &put_cont, | ||
231 | (void *) name); | ||
232 | if (NULL == nsqe) | ||
233 | { | ||
234 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
235 | _ ("Namestore cannot store no block\n")); | ||
236 | } | ||
237 | GNUNET_free_nz ((void *) rd.data); | ||
238 | } | ||
239 | |||
240 | |||
241 | #include "test_common.c" | ||
242 | |||
243 | |||
244 | int | ||
245 | main (int argc, | ||
246 | char *argv[]) | ||
247 | { | ||
248 | const char *plugin_name; | ||
249 | char *cfg_name; | ||
250 | |||
251 | SETUP_CFG (plugin_name, cfg_name); | ||
252 | res = 1; | ||
253 | if (0 != | ||
254 | GNUNET_TESTING_peer_run ("test--store-update", | ||
255 | cfg_name, | ||
256 | &run, | ||
257 | NULL)) | ||
258 | { | ||
259 | res = 1; | ||
260 | } | ||
261 | GNUNET_DISK_purge_cfg_dir (cfg_name, | ||
262 | "GNUNET_TEST_HOME"); | ||
263 | GNUNET_free (plugin_name); | ||
264 | GNUNET_free (cfg_name); | ||
265 | return res; | ||
266 | } | ||
267 | |||
268 | |||
269 | /* end of test_namestore_api_store_update.c */ | ||
diff --git a/src/namestore/test_namestore_api_tx_rollback.c b/src/namestore/test_namestore_api_tx_rollback.c deleted file mode 100644 index 4a701f60e..000000000 --- a/src/namestore/test_namestore_api_tx_rollback.c +++ /dev/null | |||
@@ -1,264 +0,0 @@ | |||
1 | /* | ||
2 | This file is part of GNUnet. | ||
3 | Copyright (C) 2022 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_tx_rollback.c | ||
22 | * @brief testcase for namestore_api_tx_rollback.c to: rollback changes in TX | ||
23 | */ | ||
24 | #include "platform.h" | ||
25 | #include "gnunet_namestore_service.h" | ||
26 | #include "gnunet_testing_lib.h" | ||
27 | |||
28 | #define TEST_RECORD_TYPE GNUNET_DNSPARSER_TYPE_TXT | ||
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 | |||
37 | static struct GNUNET_NAMESTORE_Handle *nsh; | ||
38 | |||
39 | static struct GNUNET_SCHEDULER_Task *endbadly_task; | ||
40 | |||
41 | static struct GNUNET_CRYPTO_PrivateKey privkey; | ||
42 | |||
43 | static struct GNUNET_CRYPTO_PublicKey pubkey; | ||
44 | |||
45 | static int res; | ||
46 | |||
47 | static int removed; | ||
48 | |||
49 | static struct GNUNET_NAMESTORE_QueueEntry *nsqe; | ||
50 | |||
51 | |||
52 | static void | ||
53 | cleanup () | ||
54 | { | ||
55 | if (NULL != nsh) | ||
56 | { | ||
57 | GNUNET_NAMESTORE_disconnect (nsh); | ||
58 | nsh = NULL; | ||
59 | } | ||
60 | GNUNET_SCHEDULER_shutdown (); | ||
61 | } | ||
62 | |||
63 | |||
64 | /** | ||
65 | * Re-establish the connection to the service. | ||
66 | * | ||
67 | * @param cls handle to use to re-connect. | ||
68 | */ | ||
69 | static void | ||
70 | endbadly (void *cls) | ||
71 | { | ||
72 | if (NULL != nsqe) | ||
73 | { | ||
74 | GNUNET_NAMESTORE_cancel (nsqe); | ||
75 | nsqe = NULL; | ||
76 | } | ||
77 | cleanup (); | ||
78 | res = 1; | ||
79 | } | ||
80 | |||
81 | |||
82 | static void | ||
83 | end (void *cls) | ||
84 | { | ||
85 | cleanup (); | ||
86 | res = 0; | ||
87 | } | ||
88 | |||
89 | static void | ||
90 | lookup_it (void *cls, | ||
91 | const struct GNUNET_CRYPTO_PrivateKey *zone, | ||
92 | const char *label, | ||
93 | unsigned int rd_count, | ||
94 | const struct GNUNET_GNSRECORD_Data *rd) | ||
95 | { | ||
96 | GNUNET_assert (0 == rd_count); | ||
97 | GNUNET_SCHEDULER_add_now (&end, NULL); | ||
98 | } | ||
99 | |||
100 | static void | ||
101 | fail_cb (void *cls) | ||
102 | { | ||
103 | GNUNET_assert (0); | ||
104 | } | ||
105 | |||
106 | static void | ||
107 | remove_cont (void *cls, | ||
108 | enum GNUNET_ErrorCode ec) | ||
109 | { | ||
110 | nsqe = NULL; | ||
111 | if (GNUNET_EC_NONE != ec) | ||
112 | { | ||
113 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
114 | _ ("Unable to roll back: `%s'\n"), | ||
115 | GNUNET_ErrorCode_get_hint (ec)); | ||
116 | if (NULL != endbadly_task) | ||
117 | GNUNET_SCHEDULER_cancel (endbadly_task); | ||
118 | endbadly_task = GNUNET_SCHEDULER_add_now (&endbadly, | ||
119 | NULL); | ||
120 | return; | ||
121 | } | ||
122 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, | ||
123 | "Rolled back, perform lookup\n"); | ||
124 | removed = GNUNET_YES; | ||
125 | if (NULL != endbadly_task) | ||
126 | GNUNET_SCHEDULER_cancel (endbadly_task); | ||
127 | /* FIXME not actually doing lookup here */ | ||
128 | nsqe = GNUNET_NAMESTORE_records_lookup (nsh, | ||
129 | &privkey, | ||
130 | (char*) cls, | ||
131 | &fail_cb, | ||
132 | NULL, | ||
133 | &lookup_it, | ||
134 | NULL); | ||
135 | } | ||
136 | |||
137 | |||
138 | static void | ||
139 | put_cont (void *cls, | ||
140 | enum GNUNET_ErrorCode ec) | ||
141 | { | ||
142 | const char *name = cls; | ||
143 | |||
144 | GNUNET_assert (NULL != cls); | ||
145 | nsqe = NULL; | ||
146 | if (GNUNET_EC_NONE != ec) | ||
147 | { | ||
148 | GNUNET_break (0); | ||
149 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
150 | "Namestore could not store record: `%s'\n", | ||
151 | GNUNET_ErrorCode_get_hint (ec)); | ||
152 | if (endbadly_task != NULL) | ||
153 | GNUNET_SCHEDULER_cancel (endbadly_task); | ||
154 | endbadly_task = GNUNET_SCHEDULER_add_now (&endbadly, NULL); | ||
155 | return; | ||
156 | } | ||
157 | |||
158 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
159 | "Name store added record for `%s': %s\n", | ||
160 | name, | ||
161 | (GNUNET_EC_NONE == ec) ? "SUCCESS" : "FAIL"); | ||
162 | nsqe = GNUNET_NAMESTORE_transaction_rollback (nsh, remove_cont, | ||
163 | (void *) name); | ||
164 | } | ||
165 | |||
166 | static void | ||
167 | begin_cont (void *cls, | ||
168 | enum GNUNET_ErrorCode ec) | ||
169 | { | ||
170 | struct GNUNET_GNSRECORD_Data rd; | ||
171 | const char *name = cls; | ||
172 | |||
173 | GNUNET_assert (GNUNET_EC_NONE == ec); | ||
174 | privkey.type = htonl (GNUNET_GNSRECORD_TYPE_PKEY); | ||
175 | GNUNET_CRYPTO_ecdsa_key_create (&privkey.ecdsa_key); | ||
176 | GNUNET_CRYPTO_key_get_public (&privkey, | ||
177 | &pubkey); | ||
178 | |||
179 | removed = GNUNET_NO; | ||
180 | |||
181 | rd.expiration_time = GNUNET_TIME_absolute_get ().abs_value_us; | ||
182 | rd.record_type = TEST_RECORD_TYPE; | ||
183 | rd.data_size = TEST_RECORD_DATALEN; | ||
184 | rd.data = GNUNET_malloc (TEST_RECORD_DATALEN); | ||
185 | rd.flags = 0; | ||
186 | memset ((char *) rd.data, | ||
187 | 'a', | ||
188 | TEST_RECORD_DATALEN); | ||
189 | nsqe = GNUNET_NAMESTORE_records_store (nsh, | ||
190 | &privkey, | ||
191 | name, | ||
192 | 1, | ||
193 | &rd, | ||
194 | &put_cont, | ||
195 | (void *) name); | ||
196 | GNUNET_assert (NULL != nsqe); | ||
197 | GNUNET_free_nz ((void *) rd.data); | ||
198 | } | ||
199 | |||
200 | static void | ||
201 | run (void *cls, | ||
202 | const struct GNUNET_CONFIGURATION_Handle *cfg, | ||
203 | struct GNUNET_TESTING_Peer *peer) | ||
204 | { | ||
205 | const char *name = "dummy"; | ||
206 | |||
207 | endbadly_task = GNUNET_SCHEDULER_add_delayed (TIMEOUT, | ||
208 | &endbadly, | ||
209 | NULL); | ||
210 | nsh = GNUNET_NAMESTORE_connect (cfg); | ||
211 | GNUNET_break (NULL != nsh); | ||
212 | nsqe = GNUNET_NAMESTORE_transaction_begin (nsh, begin_cont, (void *) name); | ||
213 | /*nsqe = GNUNET_NAMESTORE_transaction_commit (nsh, commit_cont); | ||
214 | nsqe = GNUNET_NAMESTORE_transaction_rollback (nsh, rollback_cont); Must also happen on disconnect | ||
215 | nsqe = GNUNET_NAMESTORE_records_edit (nsh, | ||
216 | &privkey, | ||
217 | name, | ||
218 | 1, | ||
219 | &rd, | ||
220 | &edit_cont, | ||
221 | (void *) name); | ||
222 | nsqe = GNUNET_NAMESTORE_records_insert_bulk (nsh, | ||
223 | count, | ||
224 | &rd, | ||
225 | & | ||
226 | nsqe = GNUNET_NAMESTORE_records_store (nsh, | ||
227 | &privkey, | ||
228 | name, | ||
229 | 1, | ||
230 | &rd, | ||
231 | &put_cont, | ||
232 | (void *) name);*/ | ||
233 | GNUNET_assert (NULL != nsqe); | ||
234 | } | ||
235 | |||
236 | |||
237 | #include "test_common.c" | ||
238 | |||
239 | |||
240 | int | ||
241 | main (int argc, char *argv[]) | ||
242 | { | ||
243 | const char *plugin_name; | ||
244 | char *cfg_name; | ||
245 | |||
246 | SETUP_CFG (plugin_name, cfg_name); | ||
247 | res = 1; | ||
248 | if (0 != | ||
249 | GNUNET_TESTING_peer_run ("test-namestore-api-remove", | ||
250 | cfg_name, | ||
251 | &run, | ||
252 | NULL)) | ||
253 | { | ||
254 | res = 1; | ||
255 | } | ||
256 | GNUNET_DISK_purge_cfg_dir (cfg_name, | ||
257 | "GNUNET_TEST_HOME"); | ||
258 | GNUNET_free (plugin_name); | ||
259 | GNUNET_free (cfg_name); | ||
260 | return res; | ||
261 | } | ||
262 | |||
263 | |||
264 | /* end of test_namestore_api_remove.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 fb69fffcc..000000000 --- a/src/namestore/test_namestore_api_zone_iteration.c +++ /dev/null | |||
@@ -1,464 +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 | |||
29 | #define TEST_RECORD_TYPE GNUNET_DNSPARSER_TYPE_TXT | ||
30 | |||
31 | |||
32 | #define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 100) | ||
33 | |||
34 | |||
35 | static struct GNUNET_NAMESTORE_Handle *nsh; | ||
36 | |||
37 | static struct GNUNET_SCHEDULER_Task *endbadly_task; | ||
38 | |||
39 | static struct GNUNET_CRYPTO_PrivateKey privkey; | ||
40 | |||
41 | static struct GNUNET_CRYPTO_PrivateKey privkey2; | ||
42 | |||
43 | static struct GNUNET_NAMESTORE_ZoneIterator *zi; | ||
44 | |||
45 | static int res; | ||
46 | |||
47 | static int returned_records; | ||
48 | |||
49 | static char *s_name_1; | ||
50 | |||
51 | static struct GNUNET_GNSRECORD_Data *s_rd_1; | ||
52 | |||
53 | static char *s_name_2; | ||
54 | |||
55 | static struct GNUNET_GNSRECORD_Data *s_rd_2; | ||
56 | |||
57 | static char *s_name_3; | ||
58 | |||
59 | static struct GNUNET_GNSRECORD_Data *s_rd_3; | ||
60 | |||
61 | |||
62 | /** | ||
63 | * Re-establish the connection to the service. | ||
64 | * | ||
65 | * @param cls handle to use to re-connect. | ||
66 | * @param tc scheduler context | ||
67 | */ | ||
68 | static void | ||
69 | endbadly (void *cls) | ||
70 | { | ||
71 | endbadly_task = NULL; | ||
72 | GNUNET_SCHEDULER_shutdown (); | ||
73 | res = 1; | ||
74 | } | ||
75 | |||
76 | |||
77 | static void | ||
78 | end (void *cls) | ||
79 | { | ||
80 | if (NULL != zi) | ||
81 | { | ||
82 | GNUNET_NAMESTORE_zone_iteration_stop (zi); | ||
83 | zi = NULL; | ||
84 | } | ||
85 | if (NULL != endbadly_task) | ||
86 | { | ||
87 | GNUNET_SCHEDULER_cancel (endbadly_task); | ||
88 | endbadly_task = NULL; | ||
89 | } | ||
90 | GNUNET_free (s_name_1); | ||
91 | GNUNET_free (s_name_2); | ||
92 | GNUNET_free (s_name_3); | ||
93 | if (NULL != s_rd_1) | ||
94 | { | ||
95 | GNUNET_free_nz ((void *) s_rd_1->data); | ||
96 | GNUNET_free (s_rd_1); | ||
97 | } | ||
98 | if (NULL != s_rd_2) | ||
99 | { | ||
100 | GNUNET_free_nz ((void *) s_rd_2->data); | ||
101 | GNUNET_free (s_rd_2); | ||
102 | } | ||
103 | if (NULL != s_rd_3) | ||
104 | { | ||
105 | GNUNET_free_nz ((void *) s_rd_3->data); | ||
106 | GNUNET_free (s_rd_3); | ||
107 | } | ||
108 | if (NULL != nsh) | ||
109 | { | ||
110 | GNUNET_NAMESTORE_disconnect (nsh); | ||
111 | nsh = NULL; | ||
112 | } | ||
113 | } | ||
114 | |||
115 | |||
116 | static void | ||
117 | zone_end (void *cls) | ||
118 | { | ||
119 | GNUNET_break (3 == returned_records); | ||
120 | if (3 == returned_records) | ||
121 | { | ||
122 | res = 0; /* Last iteraterator callback, we are done */ | ||
123 | zi = NULL; | ||
124 | } | ||
125 | else | ||
126 | res = 1; | ||
127 | |||
128 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
129 | "Received last result, iteration done after receing %u results\n", | ||
130 | returned_records); | ||
131 | GNUNET_SCHEDULER_shutdown (); | ||
132 | } | ||
133 | |||
134 | |||
135 | static void | ||
136 | fail_cb (void *cls) | ||
137 | { | ||
138 | GNUNET_assert (0); | ||
139 | } | ||
140 | |||
141 | |||
142 | static void | ||
143 | zone_proc (void *cls, | ||
144 | const struct GNUNET_CRYPTO_PrivateKey *zone, | ||
145 | const char *label, | ||
146 | unsigned int rd_count, | ||
147 | const struct GNUNET_GNSRECORD_Data *rd) | ||
148 | { | ||
149 | int failed = GNUNET_NO; | ||
150 | |||
151 | GNUNET_assert (NULL != zone); | ||
152 | if (0 == GNUNET_memcmp (zone, | ||
153 | &privkey)) | ||
154 | { | ||
155 | if (0 == strcmp (label, s_name_1)) | ||
156 | { | ||
157 | if (rd_count == 1) | ||
158 | { | ||
159 | if (GNUNET_YES != GNUNET_GNSRECORD_records_cmp (rd, s_rd_1)) | ||
160 | { | ||
161 | failed = GNUNET_YES; | ||
162 | GNUNET_break (0); | ||
163 | } | ||
164 | } | ||
165 | else | ||
166 | { | ||
167 | failed = GNUNET_YES; | ||
168 | GNUNET_break (0); | ||
169 | } | ||
170 | } | ||
171 | else if (0 == strcmp (label, s_name_2)) | ||
172 | { | ||
173 | if (rd_count == 1) | ||
174 | { | ||
175 | if (GNUNET_YES != GNUNET_GNSRECORD_records_cmp (rd, s_rd_2)) | ||
176 | { | ||
177 | failed = GNUNET_YES; | ||
178 | GNUNET_break (0); | ||
179 | } | ||
180 | } | ||
181 | else | ||
182 | { | ||
183 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
184 | "Received invalid record count\n"); | ||
185 | failed = GNUNET_YES; | ||
186 | GNUNET_break (0); | ||
187 | } | ||
188 | } | ||
189 | else | ||
190 | { | ||
191 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
192 | "Comparing result failed: got name `%s' for first zone\n", | ||
193 | label); | ||
194 | failed = GNUNET_YES; | ||
195 | GNUNET_break (0); | ||
196 | } | ||
197 | } | ||
198 | else if (0 == GNUNET_memcmp (zone, | ||
199 | &privkey2)) | ||
200 | { | ||
201 | if (0 == strcmp (label, s_name_3)) | ||
202 | { | ||
203 | if (rd_count == 1) | ||
204 | { | ||
205 | if (GNUNET_YES != GNUNET_GNSRECORD_records_cmp (rd, s_rd_3)) | ||
206 | { | ||
207 | failed = GNUNET_YES; | ||
208 | GNUNET_break (0); | ||
209 | } | ||
210 | } | ||
211 | else | ||
212 | { | ||
213 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
214 | "Received invalid record count\n"); | ||
215 | failed = GNUNET_YES; | ||
216 | GNUNET_break (0); | ||
217 | } | ||
218 | } | ||
219 | else | ||
220 | { | ||
221 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
222 | "Comparing result failed: got name `%s' for first zone\n", | ||
223 | label); | ||
224 | failed = GNUNET_YES; | ||
225 | GNUNET_break (0); | ||
226 | } | ||
227 | } | ||
228 | else | ||
229 | { | ||
230 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
231 | "Received invalid zone\n"); | ||
232 | failed = GNUNET_YES; | ||
233 | GNUNET_break (0); | ||
234 | } | ||
235 | |||
236 | if (failed == GNUNET_NO) | ||
237 | { | ||
238 | returned_records++; | ||
239 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
240 | "Telling namestore to send the next result\n"); | ||
241 | GNUNET_NAMESTORE_zone_iterator_next (zi, | ||
242 | 1); | ||
243 | } | ||
244 | else | ||
245 | { | ||
246 | GNUNET_break (0); | ||
247 | GNUNET_SCHEDULER_shutdown (); | ||
248 | res = 1; | ||
249 | } | ||
250 | } | ||
251 | |||
252 | |||
253 | static void | ||
254 | put_cont (void *cls, | ||
255 | enum GNUNET_ErrorCode ec) | ||
256 | { | ||
257 | static int c = 0; | ||
258 | |||
259 | if (GNUNET_EC_NONE == ec) | ||
260 | { | ||
261 | c++; | ||
262 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
263 | "Created record %u \n", | ||
264 | c); | ||
265 | } | ||
266 | else | ||
267 | { | ||
268 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
269 | "Failed to created records: `%s'\n", | ||
270 | GNUNET_ErrorCode_get_hint (ec)); | ||
271 | GNUNET_break (0); | ||
272 | GNUNET_SCHEDULER_shutdown (); | ||
273 | res = 1; | ||
274 | return; | ||
275 | } | ||
276 | |||
277 | if (c == 3) | ||
278 | { | ||
279 | res = 1; | ||
280 | returned_records = 0; | ||
281 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
282 | "All records created, starting iteration over all zones \n"); | ||
283 | zi = GNUNET_NAMESTORE_zone_iteration_start (nsh, | ||
284 | NULL, | ||
285 | &fail_cb, | ||
286 | NULL, | ||
287 | &zone_proc, | ||
288 | NULL, | ||
289 | &zone_end, | ||
290 | NULL); | ||
291 | if (zi == NULL) | ||
292 | { | ||
293 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
294 | "Failed to create zone iterator\n"); | ||
295 | GNUNET_break (0); | ||
296 | GNUNET_SCHEDULER_shutdown (); | ||
297 | res = 1; | ||
298 | return; | ||
299 | } | ||
300 | } | ||
301 | } | ||
302 | |||
303 | |||
304 | static struct GNUNET_GNSRECORD_Data * | ||
305 | create_record (unsigned int count) | ||
306 | { | ||
307 | struct GNUNET_GNSRECORD_Data *rd; | ||
308 | |||
309 | rd = GNUNET_new_array (count, | ||
310 | struct GNUNET_GNSRECORD_Data); | ||
311 | for (unsigned int c = 0; c < count; c++) | ||
312 | { | ||
313 | rd[c].expiration_time = GNUNET_TIME_relative_to_absolute ( | ||
314 | GNUNET_TIME_UNIT_HOURS).abs_value_us; | ||
315 | rd[c].record_type = TEST_RECORD_TYPE; | ||
316 | rd[c].data_size = 50; | ||
317 | rd[c].data = GNUNET_malloc (50); | ||
318 | rd[c].flags = 0; | ||
319 | memset ((char *) rd[c].data, 'a', 50); | ||
320 | } | ||
321 | return rd; | ||
322 | } | ||
323 | |||
324 | |||
325 | /** | ||
326 | * Callback called from the zone iterator when we iterate over | ||
327 | * the empty zone. Check that we got no records and then | ||
328 | * start the actual tests by filling the zone. | ||
329 | */ | ||
330 | static void | ||
331 | empty_zone_proc (void *cls, | ||
332 | const struct GNUNET_CRYPTO_PrivateKey *zone, | ||
333 | const char *label, | ||
334 | unsigned int rd_count, | ||
335 | const struct GNUNET_GNSRECORD_Data *rd) | ||
336 | { | ||
337 | GNUNET_assert (nsh == cls); | ||
338 | if (NULL != zone) | ||
339 | { | ||
340 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
341 | _ ("Expected empty zone but received zone private key\n")); | ||
342 | GNUNET_break (0); | ||
343 | GNUNET_SCHEDULER_shutdown (); | ||
344 | res = 1; | ||
345 | return; | ||
346 | } | ||
347 | if ((NULL != label) || (NULL != rd) || (0 != rd_count)) | ||
348 | { | ||
349 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
350 | _ ("Expected no zone content but received data\n")); | ||
351 | GNUNET_break (0); | ||
352 | GNUNET_SCHEDULER_shutdown (); | ||
353 | res = 1; | ||
354 | return; | ||
355 | } | ||
356 | GNUNET_assert (0); | ||
357 | } | ||
358 | |||
359 | |||
360 | static void | ||
361 | empty_zone_end (void *cls) | ||
362 | { | ||
363 | zi = NULL; | ||
364 | privkey.type = htonl (GNUNET_GNSRECORD_TYPE_PKEY); | ||
365 | privkey2.type = htonl (GNUNET_GNSRECORD_TYPE_PKEY); | ||
366 | GNUNET_CRYPTO_ecdsa_key_create (&privkey.ecdsa_key); | ||
367 | GNUNET_CRYPTO_ecdsa_key_create (&privkey2.ecdsa_key); | ||
368 | |||
369 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Created record 1\n"); | ||
370 | |||
371 | GNUNET_asprintf (&s_name_1, "dummy1"); | ||
372 | s_rd_1 = create_record (1); | ||
373 | GNUNET_NAMESTORE_records_store (nsh, | ||
374 | &privkey, | ||
375 | s_name_1, | ||
376 | 1, s_rd_1, | ||
377 | &put_cont, | ||
378 | NULL); | ||
379 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
380 | "Created record 2 \n"); | ||
381 | GNUNET_asprintf (&s_name_2, "dummy2"); | ||
382 | s_rd_2 = create_record (1); | ||
383 | GNUNET_NAMESTORE_records_store (nsh, | ||
384 | &privkey, | ||
385 | s_name_2, | ||
386 | 1, s_rd_2, | ||
387 | &put_cont, | ||
388 | NULL); | ||
389 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
390 | "Created record 3\n"); | ||
391 | /* name in different zone */ | ||
392 | GNUNET_asprintf (&s_name_3, "dummy3"); | ||
393 | s_rd_3 = create_record (1); | ||
394 | GNUNET_NAMESTORE_records_store (nsh, | ||
395 | &privkey2, | ||
396 | s_name_3, | ||
397 | 1, | ||
398 | s_rd_3, | ||
399 | &put_cont, | ||
400 | NULL); | ||
401 | } | ||
402 | |||
403 | |||
404 | static void | ||
405 | run (void *cls, | ||
406 | const struct GNUNET_CONFIGURATION_Handle *cfg, | ||
407 | struct GNUNET_TESTING_Peer *peer) | ||
408 | { | ||
409 | endbadly_task = GNUNET_SCHEDULER_add_delayed (TIMEOUT, | ||
410 | &endbadly, | ||
411 | NULL); | ||
412 | GNUNET_SCHEDULER_add_shutdown (&end, | ||
413 | NULL); | ||
414 | |||
415 | nsh = GNUNET_NAMESTORE_connect (cfg); | ||
416 | GNUNET_break (NULL != nsh); | ||
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 | NULL); | ||
426 | if (NULL == zi) | ||
427 | { | ||
428 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
429 | "Failed to create zone iterator\n"); | ||
430 | GNUNET_break (0); | ||
431 | res = 1; | ||
432 | GNUNET_SCHEDULER_shutdown (); | ||
433 | } | ||
434 | } | ||
435 | |||
436 | |||
437 | #include "test_common.c" | ||
438 | |||
439 | |||
440 | int | ||
441 | main (int argc, char *argv[]) | ||
442 | { | ||
443 | const char *plugin_name; | ||
444 | char *cfg_name; | ||
445 | |||
446 | SETUP_CFG (plugin_name, cfg_name); | ||
447 | res = 1; | ||
448 | if (0 != | ||
449 | GNUNET_TESTING_peer_run ("test-namestore-api-zone-iteration", | ||
450 | cfg_name, | ||
451 | &run, | ||
452 | NULL)) | ||
453 | { | ||
454 | res = 1; | ||
455 | } | ||
456 | GNUNET_DISK_purge_cfg_dir (cfg_name, | ||
457 | "GNUNET_TEST_HOME"); | ||
458 | GNUNET_free (plugin_name); | ||
459 | GNUNET_free (cfg_name); | ||
460 | return res; | ||
461 | } | ||
462 | |||
463 | |||
464 | /* 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 c494051d0..000000000 --- a/src/namestore/test_namestore_api_zone_iteration_nick.c +++ /dev/null | |||
@@ -1,460 +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 | |||
30 | #define TEST_RECORD_TYPE GNUNET_DNSPARSER_TYPE_TXT | ||
31 | |||
32 | #define ZONE_NICK_1 "nick1" | ||
33 | #define ZONE_NICK_2 "nick2" | ||
34 | |||
35 | #define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 100) | ||
36 | |||
37 | |||
38 | static struct GNUNET_NAMESTORE_Handle *nsh; | ||
39 | |||
40 | static struct GNUNET_CRYPTO_PrivateKey privkey; | ||
41 | |||
42 | static struct GNUNET_CRYPTO_PrivateKey privkey2; | ||
43 | |||
44 | static struct GNUNET_NAMESTORE_ZoneIterator *zi; | ||
45 | |||
46 | static int res; | ||
47 | |||
48 | static int returned_records; | ||
49 | |||
50 | static char *s_name_1; | ||
51 | |||
52 | static struct GNUNET_GNSRECORD_Data *s_rd_1; | ||
53 | |||
54 | static char *s_name_2; | ||
55 | |||
56 | static struct GNUNET_GNSRECORD_Data *s_rd_2; | ||
57 | |||
58 | static char *s_name_3; | ||
59 | |||
60 | static struct GNUNET_GNSRECORD_Data *s_rd_3; | ||
61 | |||
62 | static struct GNUNET_NAMESTORE_QueueEntry *nsqe; | ||
63 | |||
64 | |||
65 | /** | ||
66 | * Re-establish the connection to the service. | ||
67 | * | ||
68 | * @param cls handle to use to re-connect. | ||
69 | * @param tc scheduler context | ||
70 | */ | ||
71 | static void | ||
72 | end (void *cls) | ||
73 | { | ||
74 | if (NULL != zi) | ||
75 | { | ||
76 | GNUNET_NAMESTORE_zone_iteration_stop (zi); | ||
77 | zi = NULL; | ||
78 | } | ||
79 | if (nsh != NULL) | ||
80 | { | ||
81 | GNUNET_NAMESTORE_disconnect (nsh); | ||
82 | nsh = NULL; | ||
83 | } | ||
84 | GNUNET_free (s_name_1); | ||
85 | GNUNET_free (s_name_2); | ||
86 | GNUNET_free (s_name_3); | ||
87 | |||
88 | if (s_rd_1 != NULL) | ||
89 | { | ||
90 | GNUNET_free_nz ((void *) s_rd_1->data); | ||
91 | GNUNET_free (s_rd_1); | ||
92 | } | ||
93 | if (s_rd_2 != NULL) | ||
94 | { | ||
95 | GNUNET_free_nz ((void *) s_rd_2->data); | ||
96 | GNUNET_free (s_rd_2); | ||
97 | } | ||
98 | if (s_rd_3 != NULL) | ||
99 | { | ||
100 | GNUNET_free_nz ((void *) s_rd_3->data); | ||
101 | GNUNET_free (s_rd_3); | ||
102 | } | ||
103 | } | ||
104 | |||
105 | |||
106 | static int | ||
107 | check_zone_1 (const char *label, unsigned int rd_count, | ||
108 | const struct GNUNET_GNSRECORD_Data *rd) | ||
109 | { | ||
110 | for (unsigned int c = 0; c < rd_count; c++) | ||
111 | { | ||
112 | if ((rd[c].record_type == GNUNET_GNSRECORD_TYPE_NICK) && | ||
113 | (0 != strcmp (rd[c].data, ZONE_NICK_1))) | ||
114 | { | ||
115 | GNUNET_break (0); | ||
116 | return GNUNET_YES; | ||
117 | } | ||
118 | } | ||
119 | return GNUNET_NO; | ||
120 | } | ||
121 | |||
122 | |||
123 | static int | ||
124 | check_zone_2 (const char *label, | ||
125 | unsigned int rd_count, | ||
126 | const struct GNUNET_GNSRECORD_Data *rd) | ||
127 | { | ||
128 | for (unsigned int c = 0; c < rd_count; c++) | ||
129 | { | ||
130 | if ((rd[c].record_type == GNUNET_GNSRECORD_TYPE_NICK) && | ||
131 | (0 != strcmp (rd[c].data, ZONE_NICK_2))) | ||
132 | { | ||
133 | GNUNET_break (0); | ||
134 | return GNUNET_YES; | ||
135 | } | ||
136 | } | ||
137 | return GNUNET_NO; | ||
138 | } | ||
139 | |||
140 | |||
141 | static void | ||
142 | zone_proc_end (void *cls) | ||
143 | { | ||
144 | zi = NULL; | ||
145 | res = 0; | ||
146 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
147 | "Received last result, iteration done after receing %u results\n", | ||
148 | returned_records); | ||
149 | GNUNET_SCHEDULER_shutdown (); | ||
150 | } | ||
151 | |||
152 | |||
153 | static void | ||
154 | zone_proc (void *cls, | ||
155 | const struct GNUNET_CRYPTO_PrivateKey *zone, | ||
156 | const char *label, | ||
157 | unsigned int rd_count, | ||
158 | const struct GNUNET_GNSRECORD_Data *rd) | ||
159 | { | ||
160 | int failed = GNUNET_NO; | ||
161 | |||
162 | GNUNET_assert (NULL != zone); | ||
163 | if (0 == GNUNET_memcmp (zone, &privkey)) | ||
164 | { | ||
165 | failed = check_zone_1 (label, rd_count, rd); | ||
166 | if (GNUNET_YES == failed) | ||
167 | GNUNET_break (0); | ||
168 | } | ||
169 | else if (0 == GNUNET_memcmp (zone, &privkey2)) | ||
170 | { | ||
171 | failed = check_zone_2 (label, rd_count, rd); | ||
172 | if (GNUNET_YES == failed) | ||
173 | GNUNET_break (0); | ||
174 | } | ||
175 | else | ||
176 | { | ||
177 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
178 | "Received invalid zone\n"); | ||
179 | failed = GNUNET_YES; | ||
180 | GNUNET_break (0); | ||
181 | } | ||
182 | |||
183 | if (failed == GNUNET_NO) | ||
184 | { | ||
185 | returned_records++; | ||
186 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
187 | "Telling namestore to send the next result\n"); | ||
188 | GNUNET_NAMESTORE_zone_iterator_next (zi, | ||
189 | 1); | ||
190 | } | ||
191 | else | ||
192 | { | ||
193 | GNUNET_break (0); | ||
194 | res = 1; | ||
195 | GNUNET_SCHEDULER_shutdown (); | ||
196 | } | ||
197 | } | ||
198 | |||
199 | |||
200 | static void | ||
201 | fail_cb (void *cls) | ||
202 | { | ||
203 | GNUNET_assert (0); | ||
204 | } | ||
205 | |||
206 | |||
207 | static void | ||
208 | put_cont (void *cls, | ||
209 | enum GNUNET_ErrorCode ec) | ||
210 | { | ||
211 | static int c = 0; | ||
212 | |||
213 | if (GNUNET_EC_NONE == ec) | ||
214 | { | ||
215 | c++; | ||
216 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Created record %u \n", c); | ||
217 | } | ||
218 | else | ||
219 | { | ||
220 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Failed to created records: `%s'\n", | ||
221 | GNUNET_ErrorCode_get_hint (ec)); | ||
222 | GNUNET_break (0); | ||
223 | GNUNET_SCHEDULER_shutdown (); | ||
224 | return; | ||
225 | } | ||
226 | |||
227 | if (c == 3) | ||
228 | { | ||
229 | res = 1; | ||
230 | returned_records = 0; | ||
231 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
232 | "All records created, starting iteration over all zones \n"); | ||
233 | zi = GNUNET_NAMESTORE_zone_iteration_start (nsh, | ||
234 | NULL, | ||
235 | &fail_cb, | ||
236 | NULL, | ||
237 | &zone_proc, | ||
238 | NULL, | ||
239 | &zone_proc_end, | ||
240 | NULL); | ||
241 | if (zi == NULL) | ||
242 | { | ||
243 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Failed to create zone iterator\n"); | ||
244 | GNUNET_break (0); | ||
245 | GNUNET_SCHEDULER_shutdown (); | ||
246 | return; | ||
247 | } | ||
248 | } | ||
249 | } | ||
250 | |||
251 | |||
252 | static struct GNUNET_GNSRECORD_Data * | ||
253 | create_record (unsigned int count) | ||
254 | { | ||
255 | struct GNUNET_GNSRECORD_Data *rd; | ||
256 | |||
257 | rd = GNUNET_new_array (count, | ||
258 | struct GNUNET_GNSRECORD_Data); | ||
259 | for (unsigned int c = 0; c < count; c++) | ||
260 | { | ||
261 | rd[c].expiration_time = GNUNET_TIME_relative_to_absolute ( | ||
262 | GNUNET_TIME_UNIT_HOURS).abs_value_us; | ||
263 | rd[c].record_type = TEST_RECORD_TYPE; | ||
264 | rd[c].data_size = 50; | ||
265 | rd[c].data = GNUNET_malloc (50); | ||
266 | rd[c].flags = 0; | ||
267 | memset ((char *) rd[c].data, 'a', 50); | ||
268 | } | ||
269 | return rd; | ||
270 | } | ||
271 | |||
272 | |||
273 | static void | ||
274 | nick_2_cont (void *cls, | ||
275 | enum GNUNET_ErrorCode ec) | ||
276 | { | ||
277 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
278 | "Nick added : %s\n", | ||
279 | (GNUNET_EC_NONE == ec) ? "SUCCESS" : "FAIL"); | ||
280 | |||
281 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Created record 1\n"); | ||
282 | |||
283 | GNUNET_asprintf (&s_name_1, "dummy1"); | ||
284 | s_rd_1 = create_record (1); | ||
285 | GNUNET_NAMESTORE_records_store (nsh, &privkey, s_name_1, | ||
286 | 1, s_rd_1, | ||
287 | &put_cont, NULL); | ||
288 | |||
289 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
290 | "Created record 2 \n"); | ||
291 | GNUNET_asprintf (&s_name_2, "dummy2"); | ||
292 | s_rd_2 = create_record (1); | ||
293 | GNUNET_NAMESTORE_records_store (nsh, &privkey, s_name_2, | ||
294 | 1, s_rd_2, &put_cont, NULL); | ||
295 | |||
296 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
297 | "Created record 3\n"); | ||
298 | |||
299 | /* name in different zone */ | ||
300 | GNUNET_asprintf (&s_name_3, "dummy3"); | ||
301 | s_rd_3 = create_record (1); | ||
302 | GNUNET_NAMESTORE_records_store (nsh, &privkey2, s_name_3, | ||
303 | 1, s_rd_3, | ||
304 | &put_cont, NULL); | ||
305 | } | ||
306 | |||
307 | |||
308 | static void | ||
309 | nick_1_cont (void *cls, enum GNUNET_ErrorCode ec) | ||
310 | { | ||
311 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
312 | "Nick 1 added : %s\n", | ||
313 | (GNUNET_EC_NONE == ec) ? "SUCCESS" : "FAIL"); | ||
314 | struct GNUNET_GNSRECORD_Data rd; | ||
315 | |||
316 | memset (&rd, 0, sizeof(rd)); | ||
317 | rd.data = ZONE_NICK_2; | ||
318 | rd.data_size = strlen (ZONE_NICK_2) + 1; | ||
319 | rd.record_type = GNUNET_GNSRECORD_TYPE_NICK; | ||
320 | rd.expiration_time = GNUNET_TIME_UNIT_FOREVER_ABS.abs_value_us; | ||
321 | rd.flags |= GNUNET_GNSRECORD_RF_PRIVATE; | ||
322 | nsqe = GNUNET_NAMESTORE_records_store (nsh, | ||
323 | &privkey2, | ||
324 | GNUNET_GNS_EMPTY_LABEL_AT, | ||
325 | 1, | ||
326 | &rd, | ||
327 | &nick_2_cont, | ||
328 | &privkey2); | ||
329 | |||
330 | if (NULL == nsqe) | ||
331 | { | ||
332 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
333 | _ ("Namestore cannot store no block\n")); | ||
334 | } | ||
335 | } | ||
336 | |||
337 | |||
338 | /** | ||
339 | * Callback called from the zone iterator when we iterate over | ||
340 | * the empty zone. Check that we got no records and then | ||
341 | * start the actual tests by filling the zone. | ||
342 | */ | ||
343 | static void | ||
344 | empty_zone_proc (void *cls, | ||
345 | const struct GNUNET_CRYPTO_PrivateKey *zone, | ||
346 | const char *label, | ||
347 | unsigned int rd_count, | ||
348 | const struct GNUNET_GNSRECORD_Data *rd) | ||
349 | { | ||
350 | GNUNET_assert (nsh == cls); | ||
351 | |||
352 | if (NULL != zone) | ||
353 | { | ||
354 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
355 | _ ("Expected empty zone but received zone private key\n")); | ||
356 | GNUNET_break (0); | ||
357 | GNUNET_SCHEDULER_shutdown (); | ||
358 | return; | ||
359 | } | ||
360 | if ((NULL != label) || (NULL != rd) || (0 != rd_count)) | ||
361 | { | ||
362 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
363 | _ ("Expected no zone content but received data\n")); | ||
364 | GNUNET_break (0); | ||
365 | GNUNET_SCHEDULER_shutdown (); | ||
366 | return; | ||
367 | } | ||
368 | GNUNET_assert (0); | ||
369 | } | ||
370 | |||
371 | |||
372 | static void | ||
373 | empty_zone_end (void *cls) | ||
374 | { | ||
375 | GNUNET_assert (nsh == cls); | ||
376 | struct GNUNET_GNSRECORD_Data rd; | ||
377 | |||
378 | zi = NULL; | ||
379 | privkey.type = htonl (GNUNET_GNSRECORD_TYPE_PKEY); | ||
380 | privkey2.type = htonl (GNUNET_GNSRECORD_TYPE_PKEY); | ||
381 | GNUNET_CRYPTO_ecdsa_key_create (&privkey.ecdsa_key); | ||
382 | GNUNET_CRYPTO_ecdsa_key_create (&privkey2.ecdsa_key); | ||
383 | |||
384 | memset (&rd, 0, sizeof(rd)); | ||
385 | rd.data = ZONE_NICK_1; | ||
386 | rd.data_size = strlen (ZONE_NICK_1) + 1; | ||
387 | rd.record_type = GNUNET_GNSRECORD_TYPE_NICK; | ||
388 | rd.expiration_time = GNUNET_TIME_UNIT_FOREVER_ABS.abs_value_us; | ||
389 | rd.flags |= GNUNET_GNSRECORD_RF_PRIVATE; | ||
390 | nsqe = GNUNET_NAMESTORE_records_store (nsh, | ||
391 | &privkey, | ||
392 | GNUNET_GNS_EMPTY_LABEL_AT, | ||
393 | 1, | ||
394 | &rd, | ||
395 | &nick_1_cont, | ||
396 | NULL); | ||
397 | if (NULL == nsqe) | ||
398 | { | ||
399 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
400 | _ ("Namestore cannot store no block\n")); | ||
401 | } | ||
402 | } | ||
403 | |||
404 | |||
405 | static void | ||
406 | run (void *cls, | ||
407 | const struct GNUNET_CONFIGURATION_Handle *cfg, | ||
408 | struct GNUNET_TESTING_Peer *peer) | ||
409 | { | ||
410 | nsh = GNUNET_NAMESTORE_connect (cfg); | ||
411 | GNUNET_break (NULL != nsh); | ||
412 | GNUNET_SCHEDULER_add_shutdown (&end, | ||
413 | NULL); | ||
414 | /* first, iterate over empty namestore */ | ||
415 | zi = GNUNET_NAMESTORE_zone_iteration_start (nsh, | ||
416 | NULL, | ||
417 | &fail_cb, | ||
418 | NULL, | ||
419 | &empty_zone_proc, | ||
420 | nsh, | ||
421 | &empty_zone_end, | ||
422 | nsh); | ||
423 | if (NULL == zi) | ||
424 | { | ||
425 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
426 | "Failed to create zone iterator\n"); | ||
427 | GNUNET_break (0); | ||
428 | GNUNET_SCHEDULER_shutdown (); | ||
429 | } | ||
430 | } | ||
431 | |||
432 | |||
433 | #include "test_common.c" | ||
434 | |||
435 | |||
436 | int | ||
437 | main (int argc, char *argv[]) | ||
438 | { | ||
439 | const char *plugin_name; | ||
440 | char *cfg_name; | ||
441 | |||
442 | SETUP_CFG (plugin_name, cfg_name); | ||
443 | res = 1; | ||
444 | if (0 != | ||
445 | GNUNET_TESTING_peer_run ("test-namestore-api-zone-iteration-nick", | ||
446 | cfg_name, | ||
447 | &run, | ||
448 | NULL)) | ||
449 | { | ||
450 | res = 1; | ||
451 | } | ||
452 | GNUNET_DISK_purge_cfg_dir (cfg_name, | ||
453 | "GNUNET_TEST_HOME"); | ||
454 | GNUNET_free (plugin_name); | ||
455 | GNUNET_free (cfg_name); | ||
456 | return res; | ||
457 | } | ||
458 | |||
459 | |||
460 | /* 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 02587706c..000000000 --- a/src/namestore/test_namestore_api_zone_iteration_specific_zone.c +++ /dev/null | |||
@@ -1,447 +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 | |||
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 | |||
36 | static struct GNUNET_NAMESTORE_Handle *nsh; | ||
37 | |||
38 | static struct GNUNET_SCHEDULER_Task *endbadly_task; | ||
39 | |||
40 | static struct GNUNET_CRYPTO_PrivateKey privkey; | ||
41 | |||
42 | static struct GNUNET_CRYPTO_PrivateKey privkey2; | ||
43 | |||
44 | static struct GNUNET_NAMESTORE_ZoneIterator *zi; | ||
45 | |||
46 | static int res; | ||
47 | |||
48 | static int returned_records; | ||
49 | |||
50 | static char *s_name_1; | ||
51 | |||
52 | static struct GNUNET_GNSRECORD_Data *s_rd_1; | ||
53 | |||
54 | static char *s_name_2; | ||
55 | |||
56 | static struct GNUNET_GNSRECORD_Data *s_rd_2; | ||
57 | |||
58 | static char *s_name_3; | ||
59 | |||
60 | static struct GNUNET_GNSRECORD_Data *s_rd_3; | ||
61 | |||
62 | |||
63 | /** | ||
64 | * Handle timeout. | ||
65 | * | ||
66 | * @param cls handle to use to re-connect. | ||
67 | */ | ||
68 | static void | ||
69 | endbadly (void *cls) | ||
70 | { | ||
71 | endbadly_task = NULL; | ||
72 | GNUNET_SCHEDULER_shutdown (); | ||
73 | res = 1; | ||
74 | } | ||
75 | |||
76 | |||
77 | static void | ||
78 | end (void *cls) | ||
79 | { | ||
80 | if (NULL != zi) | ||
81 | { | ||
82 | GNUNET_NAMESTORE_zone_iteration_stop (zi); | ||
83 | zi = NULL; | ||
84 | } | ||
85 | if (NULL != endbadly_task) | ||
86 | { | ||
87 | GNUNET_SCHEDULER_cancel (endbadly_task); | ||
88 | endbadly_task = NULL; | ||
89 | } | ||
90 | GNUNET_free (s_name_1); | ||
91 | GNUNET_free (s_name_2); | ||
92 | GNUNET_free (s_name_3); | ||
93 | if (s_rd_1 != NULL) | ||
94 | { | ||
95 | GNUNET_free_nz ((void *) s_rd_1->data); | ||
96 | GNUNET_free (s_rd_1); | ||
97 | } | ||
98 | if (s_rd_2 != NULL) | ||
99 | { | ||
100 | GNUNET_free_nz ((void *) s_rd_2->data); | ||
101 | GNUNET_free (s_rd_2); | ||
102 | } | ||
103 | if (s_rd_3 != NULL) | ||
104 | { | ||
105 | GNUNET_free_nz ((void *) s_rd_3->data); | ||
106 | GNUNET_free (s_rd_3); | ||
107 | } | ||
108 | if (nsh != NULL) | ||
109 | { | ||
110 | GNUNET_NAMESTORE_disconnect (nsh); | ||
111 | nsh = NULL; | ||
112 | } | ||
113 | } | ||
114 | |||
115 | |||
116 | static void | ||
117 | fail_cb (void *cls) | ||
118 | { | ||
119 | GNUNET_assert (0); | ||
120 | zi = NULL; | ||
121 | } | ||
122 | |||
123 | |||
124 | static void | ||
125 | zone_proc (void *cls, | ||
126 | const struct GNUNET_CRYPTO_PrivateKey *zone, | ||
127 | const char *label, | ||
128 | unsigned int rd_count, | ||
129 | const struct GNUNET_GNSRECORD_Data *rd) | ||
130 | { | ||
131 | int failed = GNUNET_NO; | ||
132 | |||
133 | GNUNET_assert (NULL != zone); | ||
134 | if (0 == GNUNET_memcmp (zone, | ||
135 | &privkey)) | ||
136 | { | ||
137 | if (0 == strcmp (label, s_name_1)) | ||
138 | { | ||
139 | if (rd_count == 1) | ||
140 | { | ||
141 | if (GNUNET_YES != GNUNET_GNSRECORD_records_cmp (rd, s_rd_1)) | ||
142 | { | ||
143 | failed = GNUNET_YES; | ||
144 | GNUNET_break (0); | ||
145 | } | ||
146 | } | ||
147 | else | ||
148 | { | ||
149 | failed = GNUNET_YES; | ||
150 | GNUNET_break (0); | ||
151 | } | ||
152 | } | ||
153 | else if (0 == strcmp (label, s_name_2)) | ||
154 | { | ||
155 | if (rd_count == 1) | ||
156 | { | ||
157 | if (GNUNET_YES != GNUNET_GNSRECORD_records_cmp (rd, s_rd_2)) | ||
158 | { | ||
159 | failed = GNUNET_YES; | ||
160 | GNUNET_break (0); | ||
161 | } | ||
162 | } | ||
163 | else | ||
164 | { | ||
165 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
166 | "Received invalid record count\n"); | ||
167 | failed = GNUNET_YES; | ||
168 | GNUNET_break (0); | ||
169 | } | ||
170 | } | ||
171 | else | ||
172 | { | ||
173 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
174 | "Comparing result failed: got name `%s' for first zone\n", | ||
175 | label); | ||
176 | failed = GNUNET_YES; | ||
177 | GNUNET_break (0); | ||
178 | } | ||
179 | } | ||
180 | else if (0 == GNUNET_memcmp (zone, &privkey2)) | ||
181 | { | ||
182 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
183 | "Received data for not requested zone\n"); | ||
184 | failed = GNUNET_YES; | ||
185 | GNUNET_break (0); | ||
186 | } | ||
187 | else | ||
188 | { | ||
189 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
190 | "Received invalid zone\n"); | ||
191 | failed = GNUNET_YES; | ||
192 | GNUNET_break (0); | ||
193 | } | ||
194 | if (failed == GNUNET_NO) | ||
195 | { | ||
196 | returned_records++; | ||
197 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
198 | "Telling namestore to send the next result\n"); | ||
199 | GNUNET_NAMESTORE_zone_iterator_next (zi, | ||
200 | 1); | ||
201 | } | ||
202 | else | ||
203 | { | ||
204 | GNUNET_break (0); | ||
205 | res = 2; | ||
206 | GNUNET_SCHEDULER_shutdown (); | ||
207 | } | ||
208 | } | ||
209 | |||
210 | |||
211 | static void | ||
212 | zone_proc_end (void *cls) | ||
213 | { | ||
214 | zi = NULL; | ||
215 | GNUNET_break (2 == returned_records); | ||
216 | if (2 == returned_records) | ||
217 | { | ||
218 | res = 0; /* Last iteraterator callback, we are done */ | ||
219 | } | ||
220 | else | ||
221 | { | ||
222 | res = 1; | ||
223 | } | ||
224 | |||
225 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
226 | "Received last result, iteration done after receing %u results\n", | ||
227 | returned_records); | ||
228 | GNUNET_SCHEDULER_shutdown (); | ||
229 | } | ||
230 | |||
231 | |||
232 | static void | ||
233 | put_cont (void *cls, | ||
234 | enum GNUNET_ErrorCode ec) | ||
235 | { | ||
236 | static int c = 0; | ||
237 | |||
238 | if (GNUNET_EC_NONE == ec) | ||
239 | { | ||
240 | c++; | ||
241 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
242 | "Created record %u \n", c); | ||
243 | } | ||
244 | else | ||
245 | { | ||
246 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
247 | "Failed to created records: `%s'\n", | ||
248 | GNUNET_ErrorCode_get_hint (ec)); | ||
249 | GNUNET_break (0); | ||
250 | res = 2; | ||
251 | GNUNET_SCHEDULER_shutdown (); | ||
252 | return; | ||
253 | } | ||
254 | |||
255 | if (c == 3) | ||
256 | { | ||
257 | res = 1; | ||
258 | returned_records = 0; | ||
259 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
260 | "All records created, starting iteration over all zones \n"); | ||
261 | zi = GNUNET_NAMESTORE_zone_iteration_start (nsh, | ||
262 | &privkey, | ||
263 | &fail_cb, | ||
264 | NULL, | ||
265 | &zone_proc, | ||
266 | NULL, | ||
267 | &zone_proc_end, | ||
268 | NULL); | ||
269 | if (zi == NULL) | ||
270 | { | ||
271 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
272 | "Failed to create zone iterator\n"); | ||
273 | GNUNET_break (0); | ||
274 | res = 2; | ||
275 | GNUNET_SCHEDULER_shutdown (); | ||
276 | return; | ||
277 | } | ||
278 | } | ||
279 | } | ||
280 | |||
281 | |||
282 | static struct GNUNET_GNSRECORD_Data * | ||
283 | create_record (unsigned int count) | ||
284 | { | ||
285 | struct GNUNET_GNSRECORD_Data *rd; | ||
286 | |||
287 | rd = GNUNET_new_array (count, | ||
288 | struct GNUNET_GNSRECORD_Data); | ||
289 | for (unsigned int c = 0; c < count; c++) | ||
290 | { | ||
291 | rd[c].expiration_time = GNUNET_TIME_relative_to_absolute ( | ||
292 | GNUNET_TIME_UNIT_HOURS).abs_value_us; | ||
293 | rd[c].record_type = TEST_RECORD_TYPE; | ||
294 | rd[c].data_size = 50; | ||
295 | rd[c].data = GNUNET_malloc (50); | ||
296 | rd[c].flags = 0; | ||
297 | memset ((char *) rd[c].data, 'a', 50); | ||
298 | } | ||
299 | return rd; | ||
300 | } | ||
301 | |||
302 | |||
303 | /** | ||
304 | * Callback called from the zone iterator when we iterate over | ||
305 | * the empty zone. Check that we got no records and then | ||
306 | * start the actual tests by filling the zone. | ||
307 | */ | ||
308 | static void | ||
309 | empty_zone_proc (void *cls, | ||
310 | const struct GNUNET_CRYPTO_PrivateKey *zone, | ||
311 | const char *label, | ||
312 | unsigned int rd_count, | ||
313 | const struct GNUNET_GNSRECORD_Data *rd) | ||
314 | { | ||
315 | GNUNET_assert (nsh == cls); | ||
316 | if (NULL != zone) | ||
317 | { | ||
318 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
319 | _ ("Expected empty zone but received zone private key\n")); | ||
320 | GNUNET_break (0); | ||
321 | res = 2; | ||
322 | GNUNET_SCHEDULER_shutdown (); | ||
323 | return; | ||
324 | } | ||
325 | if ((NULL != label) || (NULL != rd) || (0 != rd_count)) | ||
326 | { | ||
327 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
328 | _ ("Expected no zone content but received data\n")); | ||
329 | GNUNET_break (0); | ||
330 | res = 2; | ||
331 | GNUNET_SCHEDULER_shutdown (); | ||
332 | return; | ||
333 | } | ||
334 | GNUNET_assert (0); | ||
335 | } | ||
336 | |||
337 | |||
338 | static void | ||
339 | empty_zone_proc_end (void *cls) | ||
340 | { | ||
341 | zi = NULL; | ||
342 | privkey.type = htonl (GNUNET_GNSRECORD_TYPE_PKEY); | ||
343 | privkey2.type = htonl (GNUNET_GNSRECORD_TYPE_PKEY); | ||
344 | GNUNET_CRYPTO_ecdsa_key_create (&privkey.ecdsa_key); | ||
345 | GNUNET_CRYPTO_ecdsa_key_create (&privkey2.ecdsa_key); | ||
346 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
347 | "Created record 1\n"); | ||
348 | GNUNET_asprintf (&s_name_1, | ||
349 | "dummy1"); | ||
350 | s_rd_1 = create_record (1); | ||
351 | GNUNET_NAMESTORE_records_store (nsh, | ||
352 | &privkey, | ||
353 | s_name_1, | ||
354 | 1, | ||
355 | s_rd_1, | ||
356 | &put_cont, | ||
357 | NULL); | ||
358 | |||
359 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
360 | "Created record 2 \n"); | ||
361 | GNUNET_asprintf (&s_name_2, | ||
362 | "dummy2"); | ||
363 | s_rd_2 = create_record (1); | ||
364 | GNUNET_NAMESTORE_records_store (nsh, | ||
365 | &privkey, | ||
366 | s_name_2, | ||
367 | 1, | ||
368 | s_rd_2, | ||
369 | &put_cont, | ||
370 | NULL); | ||
371 | |||
372 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
373 | "Created record 3\n"); | ||
374 | |||
375 | /* name in different zone */ | ||
376 | GNUNET_asprintf (&s_name_3, | ||
377 | "dummy3"); | ||
378 | s_rd_3 = create_record (1); | ||
379 | GNUNET_NAMESTORE_records_store (nsh, | ||
380 | &privkey2, | ||
381 | s_name_3, | ||
382 | 1, s_rd_3, | ||
383 | &put_cont, | ||
384 | NULL); | ||
385 | } | ||
386 | |||
387 | |||
388 | static void | ||
389 | run (void *cls, | ||
390 | const struct GNUNET_CONFIGURATION_Handle *cfg, | ||
391 | struct GNUNET_TESTING_Peer *peer) | ||
392 | { | ||
393 | GNUNET_SCHEDULER_add_shutdown (&end, | ||
394 | NULL); | ||
395 | endbadly_task = GNUNET_SCHEDULER_add_delayed (TIMEOUT, | ||
396 | &endbadly, | ||
397 | NULL); | ||
398 | nsh = GNUNET_NAMESTORE_connect (cfg); | ||
399 | GNUNET_break (NULL != nsh); | ||
400 | /* first, iterate over empty namestore */ | ||
401 | zi = GNUNET_NAMESTORE_zone_iteration_start (nsh, | ||
402 | NULL, | ||
403 | &fail_cb, | ||
404 | NULL, | ||
405 | &empty_zone_proc, | ||
406 | nsh, | ||
407 | &empty_zone_proc_end, | ||
408 | nsh); | ||
409 | if (NULL == zi) | ||
410 | { | ||
411 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
412 | "Failed to create zone iterator\n"); | ||
413 | GNUNET_break (0); | ||
414 | GNUNET_SCHEDULER_shutdown (); | ||
415 | } | ||
416 | } | ||
417 | |||
418 | |||
419 | #include "test_common.c" | ||
420 | |||
421 | |||
422 | int | ||
423 | main (int argc, char *argv[]) | ||
424 | { | ||
425 | const char *plugin_name; | ||
426 | char *cfg_name; | ||
427 | |||
428 | SETUP_CFG (plugin_name, cfg_name); | ||
429 | res = 1; | ||
430 | if (0 != | ||
431 | GNUNET_TESTING_peer_run ( | ||
432 | "test-namestore-api-zone-iteration-specific-zone", | ||
433 | cfg_name, | ||
434 | &run, | ||
435 | NULL)) | ||
436 | { | ||
437 | res = 1; | ||
438 | } | ||
439 | GNUNET_DISK_purge_cfg_dir (cfg_name, | ||
440 | "GNUNET_TEST_HOME"); | ||
441 | GNUNET_free (plugin_name); | ||
442 | GNUNET_free (cfg_name); | ||
443 | return res; | ||
444 | } | ||
445 | |||
446 | |||
447 | /* 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 b6b0787ef..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 | |||
29 | #define TEST_RECORD_TYPE GNUNET_DNSPARSER_TYPE_TXT | ||
30 | |||
31 | #define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 100) | ||
32 | #define WAIT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 2) | ||
33 | |||
34 | static struct GNUNET_NAMESTORE_Handle *nsh; | ||
35 | |||
36 | static struct GNUNET_CRYPTO_PrivateKey privkey; | ||
37 | |||
38 | static struct GNUNET_CRYPTO_PrivateKey privkey2; | ||
39 | |||
40 | static struct GNUNET_NAMESTORE_ZoneIterator *zi; | ||
41 | |||
42 | static int res; | ||
43 | |||
44 | static int returned_records; | ||
45 | |||
46 | static char *s_name_1; | ||
47 | |||
48 | static struct GNUNET_GNSRECORD_Data *s_rd_1; | ||
49 | |||
50 | static char *s_name_2; | ||
51 | |||
52 | static struct GNUNET_GNSRECORD_Data *s_rd_2; | ||
53 | |||
54 | static char *s_name_3; | ||
55 | |||
56 | static struct GNUNET_GNSRECORD_Data *s_rd_3; | ||
57 | |||
58 | |||
59 | /** | ||
60 | * Re-establish the connection to the service. | ||
61 | * | ||
62 | * @param cls handle to use to re-connect. | ||
63 | */ | ||
64 | static void | ||
65 | end (void *cls) | ||
66 | { | ||
67 | if (NULL != zi) | ||
68 | { | ||
69 | GNUNET_NAMESTORE_zone_iteration_stop (zi); | ||
70 | zi = NULL; | ||
71 | } | ||
72 | if (nsh != NULL) | ||
73 | { | ||
74 | GNUNET_NAMESTORE_disconnect (nsh); | ||
75 | nsh = NULL; | ||
76 | } | ||
77 | GNUNET_free (s_name_1); | ||
78 | GNUNET_free (s_name_2); | ||
79 | GNUNET_free (s_name_3); | ||
80 | if (s_rd_1 != NULL) | ||
81 | { | ||
82 | GNUNET_free_nz ((void *) s_rd_1->data); | ||
83 | GNUNET_free (s_rd_1); | ||
84 | } | ||
85 | if (s_rd_2 != NULL) | ||
86 | { | ||
87 | GNUNET_free_nz ((void *) s_rd_2->data); | ||
88 | GNUNET_free (s_rd_2); | ||
89 | } | ||
90 | if (s_rd_3 != NULL) | ||
91 | { | ||
92 | GNUNET_free_nz ((void *) s_rd_3->data); | ||
93 | GNUNET_free (s_rd_3); | ||
94 | } | ||
95 | } | ||
96 | |||
97 | |||
98 | static void | ||
99 | delayed_end (void *cls) | ||
100 | { | ||
101 | GNUNET_SCHEDULER_shutdown (); | ||
102 | } | ||
103 | |||
104 | |||
105 | static void | ||
106 | fail_cb (void *cls) | ||
107 | { | ||
108 | GNUNET_assert (0); | ||
109 | } | ||
110 | |||
111 | |||
112 | static void | ||
113 | zone_proc (void *cls, | ||
114 | const struct GNUNET_CRYPTO_PrivateKey *zone, | ||
115 | const char *label, | ||
116 | unsigned int rd_count, | ||
117 | const struct GNUNET_GNSRECORD_Data *rd) | ||
118 | { | ||
119 | int failed = GNUNET_NO; | ||
120 | |||
121 | GNUNET_assert (NULL != zone); | ||
122 | if (0 == GNUNET_memcmp (zone, &privkey)) | ||
123 | { | ||
124 | if (0 == strcmp (label, s_name_1)) | ||
125 | { | ||
126 | if (rd_count == 1) | ||
127 | { | ||
128 | if (GNUNET_YES != GNUNET_GNSRECORD_records_cmp (rd, s_rd_1)) | ||
129 | { | ||
130 | failed = GNUNET_YES; | ||
131 | GNUNET_break (0); | ||
132 | } | ||
133 | } | ||
134 | else | ||
135 | { | ||
136 | failed = GNUNET_YES; | ||
137 | GNUNET_break (0); | ||
138 | } | ||
139 | } | ||
140 | else if (0 == strcmp (label, s_name_2)) | ||
141 | { | ||
142 | if (rd_count == 1) | ||
143 | { | ||
144 | if (GNUNET_YES != GNUNET_GNSRECORD_records_cmp (rd, s_rd_2)) | ||
145 | { | ||
146 | failed = GNUNET_YES; | ||
147 | GNUNET_break (0); | ||
148 | } | ||
149 | } | ||
150 | else | ||
151 | { | ||
152 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
153 | "Received invalid record count\n"); | ||
154 | failed = GNUNET_YES; | ||
155 | GNUNET_break (0); | ||
156 | } | ||
157 | } | ||
158 | else | ||
159 | { | ||
160 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
161 | "Comparing result failed: got name `%s' for first zone\n", | ||
162 | label); | ||
163 | failed = GNUNET_YES; | ||
164 | GNUNET_break (0); | ||
165 | } | ||
166 | } | ||
167 | else if (0 == GNUNET_memcmp (zone, &privkey2)) | ||
168 | { | ||
169 | if (0 == strcmp (label, s_name_3)) | ||
170 | { | ||
171 | if (rd_count == 1) | ||
172 | { | ||
173 | if (GNUNET_YES != GNUNET_GNSRECORD_records_cmp (rd, s_rd_3)) | ||
174 | { | ||
175 | failed = GNUNET_YES; | ||
176 | GNUNET_break (0); | ||
177 | } | ||
178 | } | ||
179 | else | ||
180 | { | ||
181 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
182 | "Received invalid record count\n"); | ||
183 | failed = GNUNET_YES; | ||
184 | GNUNET_break (0); | ||
185 | } | ||
186 | } | ||
187 | else | ||
188 | { | ||
189 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
190 | "Comparing result failed: got name `%s' for first zone\n", | ||
191 | label); | ||
192 | failed = GNUNET_YES; | ||
193 | GNUNET_break (0); | ||
194 | } | ||
195 | } | ||
196 | else | ||
197 | { | ||
198 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
199 | "Received invalid zone\n"); | ||
200 | failed = GNUNET_YES; | ||
201 | GNUNET_break (0); | ||
202 | } | ||
203 | if (failed == GNUNET_NO) | ||
204 | { | ||
205 | if (1 == returned_records) | ||
206 | { | ||
207 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
208 | "Telling namestore to stop zone iteration\n"); | ||
209 | GNUNET_NAMESTORE_zone_iteration_stop (zi); | ||
210 | zi = NULL; | ||
211 | res = 0; | ||
212 | GNUNET_SCHEDULER_add_delayed (WAIT, | ||
213 | &delayed_end, | ||
214 | NULL); | ||
215 | return; | ||
216 | } | ||
217 | returned_records++; | ||
218 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
219 | "Telling namestore to send the next result\n"); | ||
220 | GNUNET_NAMESTORE_zone_iterator_next (zi, | ||
221 | 1); | ||
222 | } | ||
223 | else | ||
224 | { | ||
225 | GNUNET_break (0); | ||
226 | GNUNET_SCHEDULER_shutdown (); | ||
227 | } | ||
228 | } | ||
229 | |||
230 | |||
231 | static void | ||
232 | zone_proc_end (void *cls) | ||
233 | { | ||
234 | GNUNET_break (1 <= returned_records); | ||
235 | if (1 >= returned_records) | ||
236 | res = 1; /* Last iteraterator callback, we are done */ | ||
237 | else | ||
238 | res = 0; | ||
239 | zi = NULL; | ||
240 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
241 | "Received last result, iteration done after receing %u results\n", | ||
242 | returned_records); | ||
243 | GNUNET_SCHEDULER_add_now (&end, NULL); | ||
244 | } | ||
245 | |||
246 | |||
247 | static void | ||
248 | put_cont (void *cls, enum GNUNET_ErrorCode ec) | ||
249 | { | ||
250 | static int c = 0; | ||
251 | |||
252 | if (GNUNET_EC_NONE == ec) | ||
253 | { | ||
254 | c++; | ||
255 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Created record %u \n", c); | ||
256 | } | ||
257 | else | ||
258 | { | ||
259 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Failed to created records: `%s'\n", | ||
260 | GNUNET_ErrorCode_get_hint (ec)); | ||
261 | GNUNET_break (0); | ||
262 | GNUNET_SCHEDULER_shutdown (); | ||
263 | return; | ||
264 | } | ||
265 | |||
266 | if (c == 3) | ||
267 | { | ||
268 | res = 1; | ||
269 | returned_records = 0; | ||
270 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
271 | "All records created, starting iteration over all zones \n"); | ||
272 | zi = GNUNET_NAMESTORE_zone_iteration_start (nsh, | ||
273 | NULL, | ||
274 | &fail_cb, | ||
275 | NULL, | ||
276 | &zone_proc, | ||
277 | NULL, | ||
278 | &zone_proc_end, | ||
279 | NULL); | ||
280 | if (zi == NULL) | ||
281 | { | ||
282 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
283 | "Failed to create zone iterator\n"); | ||
284 | GNUNET_break (0); | ||
285 | GNUNET_SCHEDULER_shutdown (); | ||
286 | return; | ||
287 | } | ||
288 | } | ||
289 | } | ||
290 | |||
291 | |||
292 | static struct GNUNET_GNSRECORD_Data * | ||
293 | create_record (unsigned int count) | ||
294 | { | ||
295 | struct GNUNET_GNSRECORD_Data *rd; | ||
296 | |||
297 | rd = GNUNET_new_array (count, | ||
298 | struct GNUNET_GNSRECORD_Data); | ||
299 | for (unsigned int c = 0; c < count; c++) | ||
300 | { | ||
301 | rd[c].expiration_time = GNUNET_TIME_relative_to_absolute ( | ||
302 | GNUNET_TIME_UNIT_HOURS).abs_value_us; | ||
303 | rd[c].record_type = TEST_RECORD_TYPE; | ||
304 | rd[c].data_size = 50; | ||
305 | rd[c].data = GNUNET_malloc (50); | ||
306 | rd[c].flags = 0; | ||
307 | memset ((char *) rd[c].data, 'a', 50); | ||
308 | } | ||
309 | return rd; | ||
310 | } | ||
311 | |||
312 | |||
313 | /** | ||
314 | * Callback called from the zone iterator when we iterate over | ||
315 | * the empty zone. Check that we got no records and then | ||
316 | * start the actual tests by filling the zone. | ||
317 | */ | ||
318 | static void | ||
319 | empty_zone_proc (void *cls, | ||
320 | const struct GNUNET_CRYPTO_PrivateKey *zone, | ||
321 | const char *label, | ||
322 | unsigned int rd_count, | ||
323 | const struct GNUNET_GNSRECORD_Data *rd) | ||
324 | { | ||
325 | GNUNET_assert (nsh == cls); | ||
326 | if (NULL != zone) | ||
327 | { | ||
328 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
329 | _ ("Expected empty zone but received zone private key\n")); | ||
330 | GNUNET_break (0); | ||
331 | GNUNET_SCHEDULER_shutdown (); | ||
332 | return; | ||
333 | } | ||
334 | if ((NULL != label) || (NULL != rd) || (0 != rd_count)) | ||
335 | { | ||
336 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
337 | _ ("Expected no zone content but received data\n")); | ||
338 | GNUNET_break (0); | ||
339 | GNUNET_SCHEDULER_shutdown (); | ||
340 | return; | ||
341 | } | ||
342 | GNUNET_assert (0); | ||
343 | } | ||
344 | |||
345 | |||
346 | static void | ||
347 | empty_zone_proc_end (void *cls) | ||
348 | { | ||
349 | GNUNET_assert (nsh == cls); | ||
350 | zi = NULL; | ||
351 | privkey.type = htonl (GNUNET_GNSRECORD_TYPE_PKEY); | ||
352 | privkey2.type = htonl (GNUNET_GNSRECORD_TYPE_PKEY); | ||
353 | GNUNET_CRYPTO_ecdsa_key_create (&privkey.ecdsa_key); | ||
354 | GNUNET_CRYPTO_ecdsa_key_create (&privkey2.ecdsa_key); | ||
355 | |||
356 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
357 | "Created record 1\n"); | ||
358 | |||
359 | GNUNET_asprintf (&s_name_1, | ||
360 | "dummy1"); | ||
361 | s_rd_1 = create_record (1); | ||
362 | GNUNET_NAMESTORE_records_store (nsh, | ||
363 | &privkey, s_name_1, | ||
364 | 1, s_rd_1, &put_cont, NULL); | ||
365 | |||
366 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
367 | "Created record 2 \n"); | ||
368 | GNUNET_asprintf (&s_name_2, | ||
369 | "dummy2"); | ||
370 | s_rd_2 = create_record (1); | ||
371 | GNUNET_NAMESTORE_records_store (nsh, | ||
372 | &privkey, | ||
373 | s_name_2, | ||
374 | 1, | ||
375 | s_rd_2, | ||
376 | &put_cont, NULL); | ||
377 | |||
378 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
379 | "Created record 3\n"); | ||
380 | |||
381 | /* name in different zone */ | ||
382 | GNUNET_asprintf (&s_name_3, "dummy3"); | ||
383 | s_rd_3 = create_record (1); | ||
384 | GNUNET_NAMESTORE_records_store (nsh, | ||
385 | &privkey2, | ||
386 | s_name_3, | ||
387 | 1, | ||
388 | s_rd_3, | ||
389 | &put_cont, NULL); | ||
390 | } | ||
391 | |||
392 | |||
393 | static void | ||
394 | run (void *cls, | ||
395 | const struct GNUNET_CONFIGURATION_Handle *cfg, | ||
396 | struct GNUNET_TESTING_Peer *peer) | ||
397 | { | ||
398 | nsh = GNUNET_NAMESTORE_connect (cfg); | ||
399 | GNUNET_break (NULL != nsh); | ||
400 | GNUNET_SCHEDULER_add_shutdown (&end, | ||
401 | NULL); | ||
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 | |||
424 | int | ||
425 | main (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 ("test-namestore-api-zone-iteration-stop", | ||
434 | cfg_name, | ||
435 | &run, | ||
436 | NULL)) | ||
437 | { | ||
438 | res = 1; | ||
439 | } | ||
440 | GNUNET_DISK_purge_cfg_dir (cfg_name, | ||
441 | "GNUNET_TEST_HOME"); | ||
442 | GNUNET_free (plugin_name); | ||
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 c70eef53a..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 | |||
29 | #define TEST_RECORD_TYPE GNUNET_DNSPARSER_TYPE_TXT | ||
30 | |||
31 | #define RECORDS 5 | ||
32 | |||
33 | #define TEST_RECORD_DATALEN 123 | ||
34 | |||
35 | #define TEST_RECORD_DATA 'a' | ||
36 | |||
37 | #define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 100) | ||
38 | |||
39 | |||
40 | static struct GNUNET_NAMESTORE_Handle *nsh; | ||
41 | |||
42 | static struct GNUNET_SCHEDULER_Task *endbadly_task; | ||
43 | |||
44 | static struct GNUNET_CRYPTO_PrivateKey privkey; | ||
45 | |||
46 | static struct GNUNET_CRYPTO_PublicKey pubkey; | ||
47 | |||
48 | static struct GNUNET_CRYPTO_PublicKey s_zone_value; | ||
49 | |||
50 | static char *s_name; | ||
51 | |||
52 | static int res; | ||
53 | |||
54 | static struct GNUNET_NAMESTORE_QueueEntry *qe; | ||
55 | |||
56 | |||
57 | /** | ||
58 | * Re-establish the connection to the service. | ||
59 | * | ||
60 | * @param cls handle to use to re-connect. | ||
61 | */ | ||
62 | static void | ||
63 | endbadly (void *cls) | ||
64 | { | ||
65 | (void) cls; | ||
66 | GNUNET_SCHEDULER_shutdown (); | ||
67 | res = 1; | ||
68 | } | ||
69 | |||
70 | |||
71 | static void | ||
72 | end (void *cls) | ||
73 | { | ||
74 | if (NULL != qe) | ||
75 | { | ||
76 | GNUNET_NAMESTORE_cancel (qe); | ||
77 | qe = NULL; | ||
78 | } | ||
79 | if (NULL != endbadly_task) | ||
80 | { | ||
81 | GNUNET_SCHEDULER_cancel (endbadly_task); | ||
82 | endbadly_task = NULL; | ||
83 | } | ||
84 | if (NULL != nsh) | ||
85 | { | ||
86 | GNUNET_NAMESTORE_disconnect (nsh); | ||
87 | nsh = NULL; | ||
88 | } | ||
89 | } | ||
90 | |||
91 | |||
92 | static void | ||
93 | zone_to_name_proc (void *cls, | ||
94 | const struct GNUNET_CRYPTO_PrivateKey *zone_key, | ||
95 | const char *n, | ||
96 | unsigned int rd_count, | ||
97 | const struct GNUNET_GNSRECORD_Data *rd) | ||
98 | { | ||
99 | int fail = GNUNET_NO; | ||
100 | |||
101 | qe = NULL; | ||
102 | if ((NULL == zone_key) && | ||
103 | (NULL == n) && | ||
104 | (0 == rd_count) && | ||
105 | (NULL == rd)) | ||
106 | { | ||
107 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
108 | "No result found\n"); | ||
109 | res = 1; | ||
110 | } | ||
111 | else | ||
112 | { | ||
113 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
114 | "Result found: `%s'\n", | ||
115 | n); | ||
116 | if ((NULL == n) || | ||
117 | (0 != strcmp (n, | ||
118 | s_name))) | ||
119 | { | ||
120 | fail = GNUNET_YES; | ||
121 | GNUNET_break (0); | ||
122 | } | ||
123 | if (1 != rd_count) | ||
124 | { | ||
125 | fail = GNUNET_YES; | ||
126 | GNUNET_break (0); | ||
127 | } | ||
128 | if ((NULL == zone_key) || | ||
129 | (0 != GNUNET_memcmp (zone_key, | ||
130 | &privkey))) | ||
131 | { | ||
132 | fail = GNUNET_YES; | ||
133 | GNUNET_break (0); | ||
134 | } | ||
135 | if (fail == GNUNET_NO) | ||
136 | res = 0; | ||
137 | else | ||
138 | res = 1; | ||
139 | } | ||
140 | GNUNET_SCHEDULER_add_now (&end, | ||
141 | NULL); | ||
142 | } | ||
143 | |||
144 | |||
145 | static void | ||
146 | error_cb (void *cls) | ||
147 | { | ||
148 | (void) cls; | ||
149 | qe = NULL; | ||
150 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
151 | "Not found!\n"); | ||
152 | GNUNET_SCHEDULER_shutdown (); | ||
153 | res = 2; | ||
154 | } | ||
155 | |||
156 | |||
157 | static void | ||
158 | put_cont (void *cls, | ||
159 | enum GNUNET_ErrorCode ec) | ||
160 | { | ||
161 | char *name = cls; | ||
162 | |||
163 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
164 | "Name store added record for `%s': %s\n", | ||
165 | name, | ||
166 | (GNUNET_EC_NONE == ec) ? | ||
167 | "SUCCESS" : GNUNET_ErrorCode_get_hint (ec)); | ||
168 | if (GNUNET_EC_NONE == ec) | ||
169 | { | ||
170 | res = 0; | ||
171 | |||
172 | qe = GNUNET_NAMESTORE_zone_to_name (nsh, | ||
173 | &privkey, | ||
174 | &s_zone_value, | ||
175 | &error_cb, | ||
176 | NULL, | ||
177 | &zone_to_name_proc, | ||
178 | NULL); | ||
179 | } | ||
180 | else | ||
181 | { | ||
182 | res = 1; | ||
183 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
184 | "Failed to put records for name `%s'\n", | ||
185 | name); | ||
186 | GNUNET_SCHEDULER_add_now (&end, | ||
187 | NULL); | ||
188 | } | ||
189 | } | ||
190 | |||
191 | |||
192 | static void | ||
193 | run (void *cls, | ||
194 | const struct GNUNET_CONFIGURATION_Handle *cfg, | ||
195 | struct GNUNET_TESTING_Peer *peer) | ||
196 | { | ||
197 | (void) cls; | ||
198 | (void) peer; | ||
199 | endbadly_task = GNUNET_SCHEDULER_add_delayed (TIMEOUT, | ||
200 | &endbadly, | ||
201 | NULL); | ||
202 | GNUNET_SCHEDULER_add_shutdown (&end, | ||
203 | NULL); | ||
204 | GNUNET_asprintf (&s_name, "dummy"); | ||
205 | privkey.type = htonl (GNUNET_GNSRECORD_TYPE_PKEY); | ||
206 | GNUNET_CRYPTO_ecdsa_key_create (&privkey.ecdsa_key); | ||
207 | /* get public key */ | ||
208 | GNUNET_CRYPTO_key_get_public (&privkey, | ||
209 | &pubkey); | ||
210 | |||
211 | GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_WEAK, | ||
212 | &s_zone_value, | ||
213 | sizeof(s_zone_value)); | ||
214 | s_zone_value.type = htonl (GNUNET_GNSRECORD_TYPE_PKEY); | ||
215 | { | ||
216 | struct GNUNET_GNSRECORD_Data rd; | ||
217 | |||
218 | rd.expiration_time = GNUNET_TIME_UNIT_HOURS.rel_value_us; | ||
219 | rd.record_type = GNUNET_GNSRECORD_TYPE_PKEY; | ||
220 | rd.data_size = sizeof (s_zone_value.ecdsa_key); | ||
221 | rd.data = &s_zone_value.ecdsa_key; | ||
222 | rd.flags = GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION; | ||
223 | |||
224 | nsh = GNUNET_NAMESTORE_connect (cfg); | ||
225 | GNUNET_break (NULL != nsh); | ||
226 | GNUNET_NAMESTORE_records_store (nsh, | ||
227 | &privkey, | ||
228 | s_name, | ||
229 | 1, | ||
230 | &rd, | ||
231 | &put_cont, | ||
232 | s_name); | ||
233 | } | ||
234 | } | ||
235 | |||
236 | |||
237 | #include "test_common.c" | ||
238 | |||
239 | |||
240 | int | ||
241 | main (int argc, | ||
242 | char *argv[]) | ||
243 | { | ||
244 | const char *plugin_name; | ||
245 | char *cfg_name; | ||
246 | |||
247 | (void) argc; | ||
248 | SETUP_CFG (plugin_name, cfg_name); | ||
249 | res = 1; | ||
250 | if (0 != | ||
251 | GNUNET_TESTING_peer_run ("test-namestore-api-zone-to-name", | ||
252 | cfg_name, | ||
253 | &run, | ||
254 | NULL)) | ||
255 | { | ||
256 | res = 1; | ||
257 | } | ||
258 | GNUNET_DISK_purge_cfg_dir (cfg_name, | ||
259 | "GNUNET_TEST_HOME"); | ||
260 | GNUNET_free (plugin_name); | ||
261 | GNUNET_free (cfg_name); | ||
262 | return res; | ||
263 | } | ||
264 | |||
265 | |||
266 | /* end of test_namestore_api_zone_to_name.c */ | ||
diff --git a/src/namestore/test_namestore_delete.sh b/src/namestore/test_namestore_delete.sh deleted file mode 100755 index b861a4bc0..000000000 --- a/src/namestore/test_namestore_delete.sh +++ /dev/null | |||
@@ -1,68 +0,0 @@ | |||
1 | #!/bin/bash | ||
2 | CONFIGURATION="test_namestore_api.conf" | ||
3 | trap "gnunet-arm -e -c $CONFIGURATION" SIGINT | ||
4 | |||
5 | LOCATION=$(which gnunet-config) | ||
6 | if [ -z $LOCATION ] | ||
7 | then | ||
8 | LOCATION="gnunet-config" | ||
9 | fi | ||
10 | $LOCATION --version 1> /dev/null | ||
11 | if test $? != 0 | ||
12 | then | ||
13 | echo "GNUnet command line tools cannot be found, check environmental variables PATH and GNUNET_PREFIX" | ||
14 | exit 77 | ||
15 | fi | ||
16 | |||
17 | rm -rf `$LOCATION -c $CONFIGURATION -s PATHS -o GNUNET_HOME` | ||
18 | TEST_DOMAIN_PLUS="www.gnu" | ||
19 | TEST_DOMAIN_DNS="www3.gnu" | ||
20 | TEST_IP_PLUS="127.0.0.1" | ||
21 | TEST_IP_DNS="131.159.74.67" | ||
22 | TEST_RECORD_CNAME_SERVER="server" | ||
23 | TEST_RECORD_CNAME_PLUS="server.+" | ||
24 | TEST_RECORD_CNAME_DNS="gnunet.org" | ||
25 | TEST_RECORD_NAME_SERVER="server" | ||
26 | TEST_RECORD_NAME_PLUS="www" | ||
27 | TEST_RECORD_NAME_DNS="www3" | ||
28 | which timeout &> /dev/null && DO_TIMEOUT="timeout 5" | ||
29 | |||
30 | function start_peer | ||
31 | { | ||
32 | gnunet-arm -s -c $CONFIGURATION | ||
33 | gnunet-identity -C testego -c $CONFIGURATION | ||
34 | } | ||
35 | |||
36 | function stop_peer | ||
37 | { | ||
38 | gnunet-identity -D testego -c $CONFIGURATION | ||
39 | gnunet-arm -e -c $CONFIGURATION | ||
40 | } | ||
41 | |||
42 | |||
43 | start_peer | ||
44 | # Create a public record | ||
45 | gnunet-namestore -p -z testego -a -n $TEST_RECORD_NAME_DNS -t A -V $TEST_IP_PLUS -e never -c $CONFIGURATION | ||
46 | # Delete record | ||
47 | gnunet-namestore -p -z testego -d -n $TEST_RECORD_NAME_DNS -t A -V $TEST_IP_PLUS -e never -c $CONFIGURATION | ||
48 | # List all records | ||
49 | OUTPUT=`gnunet-namestore -p -z testego -D` | ||
50 | FOUND_IP=false | ||
51 | FOUND_NAME=false | ||
52 | for 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 | ||
61 | stop_peer | ||
62 | |||
63 | |||
64 | if [ $FOUND_IP = true ] | ||
65 | then | ||
66 | echo "FAIL: Delete name in namestore: IP returned" | ||
67 | exit 1 | ||
68 | fi | ||
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 | ||
2 | CONFIGURATION="test_namestore_api.conf" | ||
3 | trap "gnunet-arm -e -c $CONFIGURATION" SIGINT | ||
4 | |||
5 | LOCATION=$(which gnunet-config) | ||
6 | if [ -z $LOCATION ] | ||
7 | then | ||
8 | LOCATION="gnunet-config" | ||
9 | fi | ||
10 | $LOCATION --version 1> /dev/null | ||
11 | if test $? != 0 | ||
12 | then | ||
13 | echo "GNUnet command line tools cannot be found, check environmental variables PATH and GNUNET_PREFIX" | ||
14 | exit 77 | ||
15 | fi | ||
16 | |||
17 | rm -rf `$LOCATION -c $CONFIGURATION -s PATHS -o GNUNET_HOME` | ||
18 | TEST_IP_PLUS="127.0.0.1" | ||
19 | TEST_RECORD_NAME_DNS="www3" | ||
20 | which timeout &> /dev/null && DO_TIMEOUT="timeout 5" | ||
21 | |||
22 | # start peer | ||
23 | gnunet-arm -s -c $CONFIGURATION | ||
24 | gnunet-identity -C testego -c $CONFIGURATION | ||
25 | |||
26 | # Create a public record | ||
27 | gnunet-namestore -p -z testego -a -n $TEST_RECORD_NAME_DNS -t A -V $TEST_IP_PLUS -e never -c $CONFIGURATION | ||
28 | NAMESTORE_RES=$? | ||
29 | # Lookup specific name | ||
30 | OUTPUT=`gnunet-namestore -p -z testego -n $TEST_RECORD_NAME_DNS -D` | ||
31 | |||
32 | |||
33 | FOUND_IP=false | ||
34 | FOUND_NAME=false | ||
35 | for 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 | ||
45 | done | ||
46 | # stop peer | ||
47 | gnunet-identity -D testego -c $CONFIGURATION | ||
48 | gnunet-arm -e -c $CONFIGURATION | ||
49 | |||
50 | |||
51 | if [ $FOUND_NAME = true -a $FOUND_IP = true ] | ||
52 | then | ||
53 | echo "PASS: Lookup name in namestore" | ||
54 | exit 0 | ||
55 | elif [ $FOUND_NAME = false ] | ||
56 | then | ||
57 | echo "FAIL: Lookup name in namestore: name not returned" | ||
58 | exit 1 | ||
59 | elif [ $FOUND_IP = false ] | ||
60 | then | ||
61 | echo "FAIL: Lookup name in namestore: IP not returned" | ||
62 | exit 1 | ||
63 | fi | ||
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 | ||
2 | CONFIGURATION="test_namestore_api.conf" | ||
3 | trap "gnunet-arm -e -c $CONFIGURATION" SIGINT | ||
4 | |||
5 | LOCATION=$(which gnunet-config) | ||
6 | if [ -z $LOCATION ] | ||
7 | then | ||
8 | LOCATION="gnunet-config" | ||
9 | fi | ||
10 | $LOCATION --version 1> /dev/null | ||
11 | if test $? != 0 | ||
12 | then | ||
13 | echo "GNUnet command line tools cannot be found, check environmental variables PATH and GNUNET_PREFIX" | ||
14 | exit 77 | ||
15 | fi | ||
16 | |||
17 | rm -rf `$LOCATION -c $CONFIGURATION -s PATHS -o GNUNET_HOME` | ||
18 | TEST_DOMAIN_PLUS="www.gnu" | ||
19 | TEST_DOMAIN_DNS="www3.gnu" | ||
20 | TEST_IP_PLUS="127.0.0.1" | ||
21 | TEST_IP_DNS="131.159.74.67" | ||
22 | TEST_RECORD_CNAME_SERVER="server" | ||
23 | TEST_RECORD_CNAME_PLUS="server.+" | ||
24 | TEST_RECORD_CNAME_DNS="gnunet.org" | ||
25 | TEST_RECORD_NAME_SERVER="server" | ||
26 | TEST_RECORD_NAME_PLUS="www" | ||
27 | TEST_RECORD_NAME_DNS="www3" | ||
28 | which timeout &> /dev/null && DO_TIMEOUT="timeout 5" | ||
29 | |||
30 | function start_peer | ||
31 | { | ||
32 | gnunet-arm -s -c $CONFIGURATION | ||
33 | gnunet-identity -C testego -c $CONFIGURATION | ||
34 | } | ||
35 | |||
36 | function stop_peer | ||
37 | { | ||
38 | gnunet-identity -D testego -c $CONFIGURATION | ||
39 | gnunet-arm -e -c $CONFIGURATION | ||
40 | } | ||
41 | |||
42 | |||
43 | start_peer | ||
44 | # Create a public record | ||
45 | gnunet-namestore -p -z testego -a -n $TEST_RECORD_NAME_DNS -t A -V $TEST_IP_PLUS -e never -c $CONFIGURATION | ||
46 | NAMESTORE_RES=$? | ||
47 | stop_peer | ||
48 | |||
49 | if [ $NAMESTORE_RES = 0 ] | ||
50 | then | ||
51 | echo "PASS: Creating name in namestore" | ||
52 | else | ||
53 | echo "FAIL: Creating name in namestore failed with $NAMESTORE_RES." | ||
54 | exit 1 | ||
55 | fi | ||
diff --git a/src/namestore/test_namestore_put_multiple.sh b/src/namestore/test_namestore_put_multiple.sh deleted file mode 100755 index 4c7340440..000000000 --- a/src/namestore/test_namestore_put_multiple.sh +++ /dev/null | |||
@@ -1,112 +0,0 @@ | |||
1 | #!/bin/bash | ||
2 | |||
3 | # Check for required packages | ||
4 | if ! [ -x "$(command -v gnunet-namestore)" ]; then | ||
5 | echo 'bind/named is not installed' >&2 | ||
6 | exit 1 | ||
7 | fi | ||
8 | |||
9 | # Check if gnunet is running | ||
10 | gnunet-arm -I 2&>1 /dev/null | ||
11 | ret=$? | ||
12 | if [ 0 -ne $ret ]; then | ||
13 | echo 'gnunet services are not running' | ||
14 | exit 1 | ||
15 | fi | ||
16 | |||
17 | ## GNUNET part | ||
18 | # Check if identity exists and deletes and readds it to get rid of entries in zone | ||
19 | gnunet-identity -d | grep randomtestingid 2>&1 /dev/null | ||
20 | ret=$? | ||
21 | |||
22 | if [ 0 -ne $ret ]; then | ||
23 | gnunet-identity -D randomtestingid | ||
24 | gnunet-identity -C randomtestingid | ||
25 | fi | ||
26 | |||
27 | function get_record_type { | ||
28 | arr=$1 | ||
29 | typ=$(echo -n "${arr[0]}" | cut -d' ' -f1) | ||
30 | echo "$typ" | ||
31 | } | ||
32 | |||
33 | function get_value { | ||
34 | arr=$1 | ||
35 | val=$(echo -n "${arr[0]}" | cut -d' ' -f4-) | ||
36 | echo "$val" | ||
37 | } | ||
38 | |||
39 | function testing { | ||
40 | label=$1 | ||
41 | records=$2 | ||
42 | recordstring="" | ||
43 | typ=$(get_record_type "${records[@]}") | ||
44 | for i in "${records[@]}" | ||
45 | do | ||
46 | recordstring+="$i"$'\n' | ||
47 | done | ||
48 | echo "$recordstring" | ||
49 | gnunet-namestore -a -S <<EOF | ||
50 | $label.randomtestingid: | ||
51 | $recordstring | ||
52 | EOF | ||
53 | ret=$? | ||
54 | if [ 0 -ne $ret ]; then | ||
55 | echo "failed to add record $label: $recordstring" | ||
56 | fi | ||
57 | gnunet-gns -t "$typ" -u foo2.randomtestingid 2>&1 /dev/null | ||
58 | if [ 0 -ne $ret ]; then | ||
59 | echo "record $label could not be found" | ||
60 | fi | ||
61 | } | ||
62 | |||
63 | # TEST CASES | ||
64 | # 1 | ||
65 | echo "Testing adding of single A record with -R" | ||
66 | declare -a arr=('A 1200 [r] 127.0.0.1') | ||
67 | testing test1 "${arr[@]}" | ||
68 | # 2 | ||
69 | echo "Testing adding of multiple A records with -R" | ||
70 | declare -a arr=('A 1200 [r] 127.0.0.1' 'A 2400 [r] 127.0.0.2') | ||
71 | testing test2 "${arr[@]}" | ||
72 | # 3 | ||
73 | echo "Testing adding of multiple different records with -R" | ||
74 | declare -a arr=('A 1200 [r] 127.0.0.1' 'AAAA 2400 [r] 2002::') | ||
75 | testing test3 "${arr[@]}" | ||
76 | # 4 | ||
77 | echo "Testing adding of single GNS2DNS record with -R" | ||
78 | declare -a arr=('GNS2DNS 86400 [r] gnu.org@127.0.0.1') | ||
79 | testing test4 "${arr[@]}" | ||
80 | # 5 | ||
81 | echo "Testing adding of single GNS2DNS shadow record with -R" | ||
82 | declare -a arr=('GNS2DNS 86409 [rs] gnu.org@127.0.0.250') | ||
83 | testing test5 "${arr[@]}" | ||
84 | # 6 | ||
85 | echo "Testing adding of multiple GNS2DNS record with -R" | ||
86 | declare -a arr=('GNS2DNS 1 [r] gnunet.org@127.0.0.1' 'GNS2DNS 3600 [s] gnunet.org@127.0.0.2') | ||
87 | testing test6 "${arr[@]}" | ||
88 | val=$(gnunet-gns -t GNS2DNS -u test6.randomtestingid) | ||
89 | if [[ $val == *"127.0.0.1"* ]]; then | ||
90 | echo "shadow!" | ||
91 | fi | ||
92 | echo "Sleeping to let record expire" | ||
93 | sleep 5 | ||
94 | val=$(gnunet-gns -t GNS2DNS -u test6.randomtestingid) | ||
95 | if [[ $val == *"127.0.0.2"* ]]; then | ||
96 | echo "no shadow!" | ||
97 | fi | ||
98 | # 7 | ||
99 | echo "Testing adding MX record with -R" | ||
100 | declare -a arr=('MX 3600 [r] 10,mail') | ||
101 | testing test7 "${arr[@]}" | ||
102 | # 8 | ||
103 | echo "Testing adding TXT record with -R" | ||
104 | declare -a arr=('TXT 3600 [r] Pretty_Unicorns') | ||
105 | testing test8 "${arr[@]}" | ||
106 | # 8 | ||
107 | #echo "Testing adding TXT record with -R" | ||
108 | #declare -a arr=('SRV 3600 [r] _autodiscover_old._tcp.bfh.ch.') | ||
109 | #testing test8 "${arr[@]}" | ||
110 | |||
111 | # CLEANUP | ||
112 | gnunet-identity -D randomtestingid | ||
diff --git a/src/namestore/test_namestore_put_stdin.sh b/src/namestore/test_namestore_put_stdin.sh deleted file mode 100755 index deb7bc4cb..000000000 --- a/src/namestore/test_namestore_put_stdin.sh +++ /dev/null | |||
@@ -1,68 +0,0 @@ | |||
1 | #!/bin/bash | ||
2 | CONFIGURATION="test_namestore_api.conf" | ||
3 | trap "gnunet-arm -e -c $CONFIGURATION" SIGINT | ||
4 | |||
5 | LOCATION=$(which gnunet-config) | ||
6 | if [ -z $LOCATION ] | ||
7 | then | ||
8 | LOCATION="gnunet-config" | ||
9 | fi | ||
10 | $LOCATION --version 1> /dev/null | ||
11 | if test $? != 0 | ||
12 | then | ||
13 | echo "GNUnet command line tools cannot be found, check environmental variables PATH and GNUNET_PREFIX" | ||
14 | exit 77 | ||
15 | fi | ||
16 | |||
17 | rm -rf `$LOCATION -c $CONFIGURATION -s PATHS -o GNUNET_HOME` | ||
18 | TEST_RECORD_NAME="www3" | ||
19 | TEST_RECORD_NAME2="www" | ||
20 | TEST_IP="8.7.6.5" | ||
21 | TEST_IP2="1.2.3.4" | ||
22 | |||
23 | which timeout &> /dev/null && DO_TIMEOUT="timeout 5" | ||
24 | |||
25 | function start_peer | ||
26 | { | ||
27 | gnunet-arm -s -c $CONFIGURATION | ||
28 | gnunet-identity -C testego -c $CONFIGURATION | ||
29 | gnunet-identity -C testego2 -c $CONFIGURATION | ||
30 | } | ||
31 | |||
32 | function stop_peer | ||
33 | { | ||
34 | gnunet-identity -D testego -c $CONFIGURATION | ||
35 | gnunet-identity -D testego2 -c $CONFIGURATION | ||
36 | gnunet-arm -e -c $CONFIGURATION | ||
37 | } | ||
38 | |||
39 | |||
40 | start_peer | ||
41 | # Create a public record | ||
42 | EGOKEY=`gnunet-identity -d | grep testego2 | cut -d' ' -f3` | ||
43 | gnunet-namestore -a -c $CONFIGURATION -S <<EOF | ||
44 | $TEST_RECORD_NAME.testego: | ||
45 | A 3600000000 [pr] $TEST_IP | ||
46 | TXT 21438201833 [r] $TEST_IP2 | ||
47 | |||
48 | TXT 21438201833 [r] aslkdj asdlkjaslkd 232! | ||
49 | |||
50 | $TEST_RECORD_NAME2.testego: | ||
51 | AAAA 324241223 [prS] ::dead:beef | ||
52 | A 111324241223000000 [pC] 1.1.1.1 | ||
53 | |||
54 | www7.$EGOKEY: | ||
55 | A 3600000000 [pr] $TEST_IP | ||
56 | |||
57 | EOF | ||
58 | NAMESTORE_RES=$? | ||
59 | gnunet-namestore -D -r -c $CONFIGURATION | ||
60 | stop_peer | ||
61 | |||
62 | if [ $NAMESTORE_RES = 0 ] | ||
63 | then | ||
64 | echo "PASS: Creating name in namestore" | ||
65 | else | ||
66 | echo "FAIL: Creating name in namestore failed with $NAMESTORE_RES." | ||
67 | exit 1 | ||
68 | fi | ||
diff --git a/src/namestore/test_namestore_zonefile_import.sh b/src/namestore/test_namestore_zonefile_import.sh deleted file mode 100755 index d6345257f..000000000 --- a/src/namestore/test_namestore_zonefile_import.sh +++ /dev/null | |||
@@ -1,33 +0,0 @@ | |||
1 | #!/bin/sh | ||
2 | # This file is in the public domain. | ||
3 | trap "gnunet-arm -e -c test_namestore_api.conf" INT | ||
4 | |||
5 | LOCATION=$(which gnunet-config) | ||
6 | if [ -z $LOCATION ] | ||
7 | then | ||
8 | LOCATION="gnunet-config" | ||
9 | fi | ||
10 | $LOCATION --version 1> /dev/null | ||
11 | if test $? != 0 | ||
12 | then | ||
13 | echo "GNUnet command line tools cannot be found, check environmental variables PATH and GNUNET_PREFIX" | ||
14 | exit 77 | ||
15 | fi | ||
16 | |||
17 | rm -rf `gnunet-config -c test_namestore_api.conf -f -s paths -o GNUNET_TEST_HOME` | ||
18 | which timeout > /dev/null 2>&1 && DO_TIMEOUT="timeout 5" | ||
19 | |||
20 | MY_EGO="myego" | ||
21 | gnunet-arm -s -c test_namestore_api.conf | ||
22 | gnunet-identity -C $MY_EGO -c test_namestore_api.conf | ||
23 | gnunet-namestore-zonefile -c test_namestore_api.conf < example_zonefile | ||
24 | res=$? | ||
25 | gnunet-identity -D $MY_EGO -c test_namestore_api.conf | ||
26 | gnunet-arm -e -c test_namestore_api.conf | ||
27 | |||
28 | if [ $res != 0 ]; then | ||
29 | echo "FAIL: Zone import failed." | ||
30 | exit 1 | ||
31 | fi | ||
32 | |||
33 | |||
diff --git a/src/namestore/test_plugin_namestore.c b/src/namestore/test_plugin_namestore.c deleted file mode 100644 index 388b23f57..000000000 --- a/src/namestore/test_plugin_namestore.c +++ /dev/null | |||
@@ -1,218 +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 | |||
30 | #define TEST_RECORD_TYPE GNUNET_DNSPARSER_TYPE_TXT | ||
31 | |||
32 | static int ok; | ||
33 | |||
34 | /** | ||
35 | * Name of plugin under test. | ||
36 | */ | ||
37 | static const char *plugin_name; | ||
38 | |||
39 | |||
40 | /** | ||
41 | * Function called when the service shuts down. Unloads our namestore | ||
42 | * plugin. | ||
43 | * | ||
44 | * @param api api to unload | ||
45 | */ | ||
46 | static void | ||
47 | unload_plugin (struct GNUNET_NAMESTORE_PluginFunctions *api) | ||
48 | { | ||
49 | char *libname; | ||
50 | |||
51 | GNUNET_asprintf (&libname, "libgnunet_plugin_namestore_%s", plugin_name); | ||
52 | GNUNET_break (NULL == GNUNET_PLUGIN_unload (libname, api)); | ||
53 | GNUNET_free (libname); | ||
54 | } | ||
55 | |||
56 | |||
57 | /** | ||
58 | * Load the namestore plugin. | ||
59 | * | ||
60 | * @param cfg configuration to pass | ||
61 | * @return NULL on error | ||
62 | */ | ||
63 | static struct GNUNET_NAMESTORE_PluginFunctions * | ||
64 | load_plugin (const struct GNUNET_CONFIGURATION_Handle *cfg) | ||
65 | { | ||
66 | struct GNUNET_NAMESTORE_PluginFunctions *ret; | ||
67 | char *libname; | ||
68 | |||
69 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, | ||
70 | "Loading `%s' namestore plugin\n", | ||
71 | plugin_name); | ||
72 | GNUNET_asprintf (&libname, | ||
73 | "libgnunet_plugin_namestore_%s", | ||
74 | plugin_name); | ||
75 | if (NULL == (ret = GNUNET_PLUGIN_load (libname, (void *) cfg))) | ||
76 | { | ||
77 | fprintf (stderr, | ||
78 | "Failed to load plugin `%s'!\n", | ||
79 | plugin_name); | ||
80 | GNUNET_free (libname); | ||
81 | return NULL; | ||
82 | } | ||
83 | GNUNET_free (libname); | ||
84 | if (GNUNET_OK != ret->drop_tables (ret->cls)) | ||
85 | { | ||
86 | GNUNET_break (0); | ||
87 | return NULL; | ||
88 | } | ||
89 | if (GNUNET_OK != ret->create_tables (ret->cls)) | ||
90 | { | ||
91 | GNUNET_break (0); | ||
92 | return NULL; | ||
93 | } | ||
94 | return ret; | ||
95 | } | ||
96 | |||
97 | |||
98 | static void | ||
99 | test_record (void *cls, | ||
100 | uint64_t seq, | ||
101 | const struct GNUNET_CRYPTO_PrivateKey *private_key, | ||
102 | const char *label, | ||
103 | unsigned int rd_count, | ||
104 | const struct GNUNET_GNSRECORD_Data *rd) | ||
105 | { | ||
106 | int *idp = cls; | ||
107 | int id = *idp; | ||
108 | struct GNUNET_CRYPTO_PrivateKey tzone_private_key; | ||
109 | char tname[64]; | ||
110 | unsigned int trd_count = 1 + (id % 1024); | ||
111 | |||
112 | GNUNET_snprintf (tname, sizeof(tname), "a%u", (unsigned int) id); | ||
113 | GNUNET_assert (trd_count == rd_count); | ||
114 | for (unsigned int i = 0; i < trd_count; i++) | ||
115 | { | ||
116 | GNUNET_assert (rd[i].data_size == id % 10); | ||
117 | GNUNET_assert (0 == memcmp ("Hello World", rd[i].data, id % 10)); | ||
118 | GNUNET_assert (rd[i].record_type == TEST_RECORD_TYPE); | ||
119 | GNUNET_assert (rd[i].flags == 0); | ||
120 | } | ||
121 | memset (&tzone_private_key, (id % 241), sizeof(tzone_private_key)); | ||
122 | GNUNET_assert (0 == strcmp (label, tname)); | ||
123 | GNUNET_assert (0 == GNUNET_memcmp (&tzone_private_key, private_key)); | ||
124 | } | ||
125 | |||
126 | |||
127 | static void | ||
128 | get_record (struct GNUNET_NAMESTORE_PluginFunctions *nsp, int id) | ||
129 | { | ||
130 | GNUNET_assert ( | ||
131 | GNUNET_OK == | ||
132 | nsp->iterate_records (nsp->cls, NULL, 0, 1, &test_record, &id)); | ||
133 | } | ||
134 | |||
135 | |||
136 | static void | ||
137 | put_record (struct GNUNET_NAMESTORE_PluginFunctions *nsp, int id) | ||
138 | { | ||
139 | struct GNUNET_CRYPTO_PrivateKey zone_private_key; | ||
140 | char label[64]; | ||
141 | unsigned int rd_count = 1 + (id % 1024); | ||
142 | struct GNUNET_GNSRECORD_Data rd[GNUNET_NZL (rd_count)]; | ||
143 | struct GNUNET_CRYPTO_EcdsaSignature signature; | ||
144 | |||
145 | GNUNET_snprintf (label, sizeof(label), "a%u", (unsigned int) id); | ||
146 | for (unsigned int i = 0; i < rd_count; i++) | ||
147 | { | ||
148 | rd[i].data = "Hello World"; | ||
149 | rd[i].data_size = id % 10; | ||
150 | rd[i].expiration_time = | ||
151 | GNUNET_TIME_relative_to_absolute (GNUNET_TIME_UNIT_MINUTES).abs_value_us; | ||
152 | rd[i].record_type = TEST_RECORD_TYPE; | ||
153 | rd[i].flags = 0; | ||
154 | } | ||
155 | memset (&zone_private_key, (id % 241), sizeof(zone_private_key)); | ||
156 | memset (&signature, (id % 243), sizeof(signature)); | ||
157 | GNUNET_assert ( | ||
158 | GNUNET_OK == | ||
159 | nsp->store_records (nsp->cls, &zone_private_key, label, rd_count, rd)); | ||
160 | } | ||
161 | |||
162 | |||
163 | static void | ||
164 | run (void *cls, | ||
165 | char *const *args, | ||
166 | const char *cfgfile, | ||
167 | const struct GNUNET_CONFIGURATION_Handle *cfg) | ||
168 | { | ||
169 | struct GNUNET_NAMESTORE_PluginFunctions *nsp; | ||
170 | |||
171 | ok = 0; | ||
172 | nsp = load_plugin (cfg); | ||
173 | if (NULL == nsp) | ||
174 | { | ||
175 | fprintf ( | ||
176 | stderr, | ||
177 | "%s", | ||
178 | "Failed to initialize namestore. Database likely not setup, skipping test.\n"); | ||
179 | return; | ||
180 | } | ||
181 | put_record (nsp, 1); | ||
182 | get_record (nsp, 1); | ||
183 | #ifndef DARWIN // #5582 | ||
184 | unload_plugin (nsp); | ||
185 | #endif | ||
186 | } | ||
187 | |||
188 | |||
189 | int | ||
190 | main (int argc, char *argv[]) | ||
191 | { | ||
192 | char cfg_name[PATH_MAX]; | ||
193 | char *const xargv[] = { "test-plugin-namestore", "-c", cfg_name, NULL }; | ||
194 | struct GNUNET_GETOPT_CommandLineOption options[] = | ||
195 | { GNUNET_GETOPT_OPTION_END }; | ||
196 | |||
197 | GNUNET_log_setup ("test-plugin-namestore", "WARNING", NULL); | ||
198 | plugin_name = GNUNET_STRINGS_get_suffix_from_binary_name (argv[0]); | ||
199 | GNUNET_snprintf (cfg_name, | ||
200 | sizeof(cfg_name), | ||
201 | "test_plugin_namestore_%s.conf", | ||
202 | plugin_name); | ||
203 | GNUNET_DISK_purge_cfg_dir (cfg_name, "GNUNET_TMP"); | ||
204 | GNUNET_PROGRAM_run ((sizeof(xargv) / sizeof(char *)) - 1, | ||
205 | xargv, | ||
206 | "test-plugin-namestore", | ||
207 | "nohelp", | ||
208 | options, | ||
209 | &run, | ||
210 | NULL); | ||
211 | GNUNET_DISK_purge_cfg_dir (cfg_name, "GNUNET_TMP"); | ||
212 | if (ok != 0) | ||
213 | fprintf (stderr, "Missed some testcases: %d\n", ok); | ||
214 | return ok; | ||
215 | } | ||
216 | |||
217 | |||
218 | /* end of test_plugin_namestore.c */ | ||
diff --git a/src/namestore/test_plugin_namestore_postgres.conf b/src/namestore/test_plugin_namestore_postgres.conf deleted file mode 100644 index 140d54623..000000000 --- a/src/namestore/test_plugin_namestore_postgres.conf +++ /dev/null | |||
@@ -1,4 +0,0 @@ | |||
1 | [namestore-postgres] | ||
2 | CONFIG = connect_timeout=10 dbname=gnunetcheck | ||
3 | INIT_ON_CONNECT = YES | ||
4 | #TEMPORARY_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 365198db2..000000000 --- a/src/namestore/test_plugin_namestore_sqlite.conf +++ /dev/null | |||
@@ -1,3 +0,0 @@ | |||
1 | [namestore-sqlite] | ||
2 | FILENAME = $GNUNET_TMP/gnunet-test-plugin-namestore-sqlite/sqlite.db | ||
3 | INIT_ON_CONNECT = YES | ||
diff --git a/src/namestore/test_plugin_rest_namestore.sh b/src/namestore/test_plugin_rest_namestore.sh deleted file mode 100755 index 4f117db8b..000000000 --- a/src/namestore/test_plugin_rest_namestore.sh +++ /dev/null | |||
@@ -1,131 +0,0 @@ | |||
1 | #!/bin/sh | ||
2 | trap "gnunet-arm -e -c test_gns_lookup.conf" SIGINT | ||
3 | |||
4 | LOCATION=$(which gnunet-config) | ||
5 | if [ -z $LOCATION ] | ||
6 | then | ||
7 | LOCATION="gnunet-config" | ||
8 | fi | ||
9 | $LOCATION --version 1> /dev/null | ||
10 | if test $? != 0 | ||
11 | then | ||
12 | echo "GNUnet command line tools cannot be found, check environmental variables PATH and GNUNET_PREFIX" | ||
13 | exit 77 | ||
14 | fi | ||
15 | |||
16 | rm -rf `gnunet-config -c test_namestore_api.conf -f -s paths -o GNUNET_TEST_HOME` | ||
17 | |||
18 | namestore_link="http://localhost:7776/namestore" | ||
19 | wrong_link="http://localhost:7776/namestoreandmore" | ||
20 | |||
21 | curl_get () { | ||
22 | #$1 is link | ||
23 | #$2 is grep | ||
24 | resp=$(curl -v "$1" 2>&1) | ||
25 | cache="$(echo $resp | grep "$2")" | ||
26 | #echo $cache | ||
27 | if [ "" = "$cache" ] | ||
28 | then | ||
29 | echo "Error in get response: $resp, expected $2" | ||
30 | gnunet-arm -e -c test_namestore_api.conf | ||
31 | exit 1 | ||
32 | fi | ||
33 | } | ||
34 | |||
35 | curl_post () { | ||
36 | #$1 is link | ||
37 | #$2 is data | ||
38 | #$3 is grep | ||
39 | resp=$(curl -v -X "POST" "$1" --data "$2" 2>&1) | ||
40 | cache="$(echo $resp | grep "$3")" | ||
41 | #echo $cache | ||
42 | if [ "" = "$cache" ] | ||
43 | then | ||
44 | echo "Error in post response: $resp ($2), expected $3" | ||
45 | gnunet-arm -e -c test_namestore_api.conf | ||
46 | exit 1 | ||
47 | fi | ||
48 | } | ||
49 | |||
50 | curl_delete () { | ||
51 | #$1 is link | ||
52 | #$2 is grep | ||
53 | resp=$(curl -v -X "DELETE" "$1" 2>&1) | ||
54 | cache="$(echo $resp | grep "$2")" | ||
55 | #echo $cache | ||
56 | if [ "" = "$cache" ] | ||
57 | then | ||
58 | echo "Error in delete response: $resp, expected $2" | ||
59 | gnunet-arm -e -c test_namestore_api.conf | ||
60 | exit 1 | ||
61 | fi | ||
62 | } | ||
63 | |||
64 | # curl_put () { | ||
65 | # #$1 is link | ||
66 | # #$2 is data | ||
67 | # #$3 is grep | ||
68 | # cache="$(curl -v -X "PUT" "$1" --data "$2" 2>&1 | grep "$3")" | ||
69 | # #echo $cache | ||
70 | # if [ "" == "$cache" ] | ||
71 | # then | ||
72 | # exit 1 | ||
73 | # fi | ||
74 | # } | ||
75 | |||
76 | #Test subsystem default identity | ||
77 | |||
78 | TEST_ID="test" | ||
79 | gnunet-arm -s -c test_namestore_api.conf | ||
80 | #Test GET | ||
81 | gnunet-identity -C $TEST_ID -c test_namestore_api.conf | ||
82 | test="$(gnunet-namestore -D -z $TEST_ID -c test_namestore_api.conf)" | ||
83 | name=$TEST_ID | ||
84 | public="$(gnunet-identity -d -c test_namestore_api.conf | grep $TEST_ID | awk 'NR==1{print $3}')" | ||
85 | echo "$name $public" | ||
86 | gnunet-namestore -z $name -p -a -n "test_entry" -e "1d" -V "000G006WVZ8HQ5YTVFNX09HK0VJVVQ9ZCBYDSCH3ERT04N5ZRBKEB82EP8" -t "PKEY" -c test_namestore_api.conf | ||
87 | sleep 1 | ||
88 | gnunet-arm -i rest -c test_namestore_api.conf | ||
89 | sleep 1 | ||
90 | curl_get "${namestore_link}/$name" "HTTP/1.1 200 OK" | ||
91 | curl_get "${namestore_link}/$public" "error" | ||
92 | gnunet-namestore -z $name -d -n "test_entry" -c test_namestore_api.conf | ||
93 | |||
94 | #Test POST with NAME | ||
95 | curl_post "${namestore_link}/$name" '{"data": [{"value":"000G006WVZ8HQ5YTVFNX09HK0VJVVQ9ZCBYDSCH3ERT04N5ZRBKEB82EP8", "record_type":"PKEY", "relative_expiration": 86400000000, "is_relative_expiration": false, "is_supplemental": false, "is_shadow": false, "is_private": false}],"record_name":"test_entry"}' "HTTP/1.1 204 No Content" | ||
96 | gnunet-namestore -z $name -d -n "test_entry" -c test_namestore_api.conf > /dev/null 2>&1 | ||
97 | |||
98 | # invalid values | ||
99 | curl_post "${namestore_link}/$name" '{"data": [{"value":"HVX38H2CB7WJM0WCPWT9CFX6GASMYJVR65RN75SJSSKAYVYXHMRGxxx", "record_type":"PKEY", "relative_expiration": 86400000000, "is_relative_expiration": false, "is_supplemental": false, "is_shadow": false, "is_private": false}],"record_name":"test_entry"}' "error" | ||
100 | gnunet-namestore -z $name -d -n "test_entry" -c test_namestore_api.conf > /dev/null 2>&1 | ||
101 | |||
102 | |||
103 | curl_post "${namestore_link}/$name" '{"data": [{"value":"", "record_type":"PKEY", "relative_expiration": 86400000000,"flag":0,"record_name"}]:"test_entry"}' "error" | ||
104 | gnunet-namestore -z $name -d -n "test_entry" -c test_namestore_api.conf > /dev/null 2>&1 | ||
105 | |||
106 | curl_post "${namestore_link}/$name" '{"data": [{"record_type":"PKEY", "relative_expiration": 86400000000,"flag":0}],"record_name":"test_entry"}' "error" | ||
107 | gnunet-namestore -z $name -d -n "test_entry" -c test_namestore_api.conf > /dev/null 2>&1 | ||
108 | |||
109 | #expirations | ||
110 | curl_post "${namestore_link}/$name" '{"data": [{"value":"000G006WVZ8HQ5YTVFNX09HK0VJVVQ9ZCBYDSCH3ERT04N5ZRBKEB82EP8", "record_type":"PKEY", "relative_expiration":0, "is_relative_expiration": true, "is_supplemental": false, "is_shadow": false, "is_private": false}],"record_name":"test_entry"}' "HTTP/1.1 204" | ||
111 | gnunet-namestore -z $name -d -n "test_entry" -c test_namestore_api.conf > /dev/null 2>&1 | ||
112 | |||
113 | curl_post "${namestore_link}/$name" '{"data": [{"value":"000G006WVZ8HQ5YTVFNX09HK0VJVVQ9ZCBYDSCH3ERT04N5ZRBKEB82EP8", "record_type":"PKEY", "relative_expiration":864000000000000, "is_relative_expiration": true, "is_supplemental": false, "is_shadow": false, "is_private": false}],"record_name":"test_entry"}' "HTTP/1.1 204" | ||
114 | gnunet-namestore -z $name -d -n "test_entry" -c test_namestore_api.conf > /dev/null 2>&1 | ||
115 | |||
116 | curl_post "${namestore_link}/$name" '{"data": [{"value":"000G006WVZ8HQ5YTVFNX09HK0VJVVQ9ZCBYDSCH3ERT04N5ZRBKEB82EP8", "record_type":"PKEY", "expiration_time_missing":"1d", "is_relative_expiration": false, "is_supplemental": false, "is_shadow": false, "is_private": false}],"record_name":"test_entry"}' "error" | ||
117 | gnunet-namestore -z $name -d -n "test_entry" -c test_namestore_api.conf > /dev/null 2>&1 | ||
118 | |||
119 | #record_name | ||
120 | curl_post "${namestore_link}/$name" '{"data": [{"value":"000G006WVZ8HQ5YTVFNX09HK0VJVVQ9ZCBYDSCH3ERT04N5ZRBKEB82EP8", "record_type":"PKEY", "relative_expiration":86400000000, "is_relative_expiration": false, "is_supplemental": false, "is_shadow": false, "is_private": false}],"record_name":""}' "error" | ||
121 | gnunet-namestore -z $name -d -n "test_entry" -c test_namestore_api.conf > /dev/null 2>&1 | ||
122 | curl_post "${namestore_link}/$name" '{"data": [{"value":"000G006WVZ8HQ5YTVFNX09HK0VJVVQ9ZCBYDSCH3ERT04N5ZRBKEB82EP8", "record_type":"PKEY", "relative_expiration":"1d", "is_relative_expiration": false, "is_supplemental": false, "is_shadow": false, "is_private": false}],"record_name_missing":"test_entry"}' "error" | ||
123 | gnunet-namestore -z $name -d -n "test_entry" -c test_namestore_api.conf > /dev/null 2>&1 | ||
124 | |||
125 | #Test DELETE | ||
126 | gnunet-namestore -z $name -p -a -n "test_entry" -e "1d" -V "000G006WVZ8HQ5YTVFNX09HK0VJVVQ9ZCBYDSCH3ERT04N5ZRBKEB82EP8" -t "PKEY" -c test_namestore_api.conf | ||
127 | curl_delete "${namestore_link}/$name/test_entry" "HTTP/1.1 204" | ||
128 | |||
129 | gnunet-arm -e -c test_namestore_api.conf | ||
130 | exit 0; | ||
131 | |||