diff options
Diffstat (limited to 'src/namestore')
49 files changed, 0 insertions, 19840 deletions
diff --git a/src/namestore/.gitignore b/src/namestore/.gitignore deleted file mode 100644 index f159cdaff..000000000 --- a/src/namestore/.gitignore +++ /dev/null | |||
@@ -1,88 +0,0 @@ | |||
1 | gnunet-service-namestore | ||
2 | gnunet-namestore | ||
3 | gnunet-namestore-fcfsd | ||
4 | test_namestore_api_lookup_nick.nc | ||
5 | test_namestore_api_lookup_private.nc | ||
6 | test_namestore_api_lookup_public.nc | ||
7 | test_namestore_api_lookup_shadow.nc | ||
8 | test_namestore_api_lookup_shadow_filter.nc | ||
9 | test_namestore_api_monitoring.nc | ||
10 | test_namestore_api_monitoring_existing.nc | ||
11 | test_namestore_api_remove.nc | ||
12 | test_namestore_api_remove_not_existing_record.nc | ||
13 | test_namestore_api_store.nc | ||
14 | test_namestore_api_store_update.nc | ||
15 | test_namestore_api_zone_iteration.nc | ||
16 | test_namestore_api_zone_iteration_nick.nc | ||
17 | test_namestore_api_zone_iteration_specific_zone.nc | ||
18 | test_namestore_api_zone_iteration_stop.nc | ||
19 | test_plugin_namestore_postgres | ||
20 | test_plugin_namestore_sqlite | ||
21 | test_plugin_namestore_flat | ||
22 | gnunet-zoneimport | ||
23 | test_namestore_api_lookup_nick_flat | ||
24 | test_namestore_api_lookup_nick_postgres | ||
25 | test_namestore_api_lookup_nick_sqlite | ||
26 | test_namestore_api_lookup_private_flat | ||
27 | test_namestore_api_lookup_private_postgres | ||
28 | test_namestore_api_lookup_private_sqlite | ||
29 | test_namestore_api_lookup_public_flat | ||
30 | test_namestore_api_lookup_public_postgres | ||
31 | test_namestore_api_lookup_public_sqlite | ||
32 | test_namestore_api_lookup_shadow_filter_flat | ||
33 | test_namestore_api_lookup_shadow_filter_postgres | ||
34 | test_namestore_api_lookup_shadow_filter_sqlite | ||
35 | test_namestore_api_lookup_shadow_flat | ||
36 | test_namestore_api_lookup_shadow_postgres | ||
37 | test_namestore_api_lookup_shadow_sqlite | ||
38 | test_namestore_api_monitoring_existing_flat | ||
39 | test_namestore_api_monitoring_existing_postgres | ||
40 | test_namestore_api_monitoring_existing_sqlite | ||
41 | test_namestore_api_monitoring_flat | ||
42 | test_namestore_api_monitoring_postgres | ||
43 | test_namestore_api_monitoring_sqlite | ||
44 | test_namestore_api_remove_flat | ||
45 | test_namestore_api_remove_not_existing_record_flat | ||
46 | test_namestore_api_remove_not_existing_record_postgres | ||
47 | test_namestore_api_remove_not_existing_record_sqlite | ||
48 | test_namestore_api_remove_postgres | ||
49 | test_namestore_api_remove_sqlite | ||
50 | test_namestore_api_store_flat | ||
51 | test_namestore_api_store_postgres | ||
52 | test_namestore_api_store_sqlite | ||
53 | test_namestore_api_store_update_flat | ||
54 | test_namestore_api_store_update_postgres | ||
55 | test_namestore_api_store_update_sqlite | ||
56 | test_namestore_api_zone_iteration_flat | ||
57 | test_namestore_api_zone_iteration_nick_flat | ||
58 | test_namestore_api_zone_iteration_nick_postgres | ||
59 | test_namestore_api_zone_iteration_nick_sqlite | ||
60 | test_namestore_api_zone_iteration_postgres | ||
61 | test_namestore_api_zone_iteration_specific_zone_flat | ||
62 | test_namestore_api_zone_iteration_specific_zone_postgres | ||
63 | test_namestore_api_zone_iteration_specific_zone_sqlite | ||
64 | test_namestore_api_zone_iteration_sqlite | ||
65 | test_namestore_api_zone_iteration_stop_flat | ||
66 | test_namestore_api_zone_iteration_stop_postgres | ||
67 | test_namestore_api_zone_iteration_stop_sqlite | ||
68 | test_namestore_api_zone_to_name_flat | ||
69 | test_namestore_api_zone_to_name_postgres | ||
70 | test_namestore_api_zone_to_name_sqlite | ||
71 | test_namestore_api_lookup_nick_flat | ||
72 | test_namestore_api_lookup_private_flat | ||
73 | test_namestore_api_lookup_public_flat | ||
74 | test_namestore_api_lookup_shadow_filter_flat | ||
75 | test_namestore_api_lookup_shadow_flat | ||
76 | test_namestore_api_monitoring_existing_flat | ||
77 | test_namestore_api_monitoring_flat | ||
78 | test_namestore_api_remove_flat | ||
79 | test_namestore_api_remove_not_existing_record_flat | ||
80 | test_namestore_api_store_flat | ||
81 | test_namestore_api_store_update_flat | ||
82 | test_namestore_api_zone_iteration_flat | ||
83 | test_namestore_api_zone_iteration_nick_flat | ||
84 | test_namestore_api_zone_iteration_specific_zone_flat | ||
85 | test_namestore_api_zone_iteration_stop_flat | ||
86 | test_namestore_api_zone_to_name_flat | ||
87 | test_plugin_namestore_flat | ||
88 | perf_namestore_api_zone_iteration_flat | ||
diff --git a/src/namestore/Makefile.am b/src/namestore/Makefile.am deleted file mode 100644 index 18e6a196b..000000000 --- a/src/namestore/Makefile.am +++ /dev/null | |||
@@ -1,755 +0,0 @@ | |||
1 | # This Makefile.am is in the public domain | ||
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 | pkgcfg_DATA = \ | ||
11 | namestore.conf | ||
12 | |||
13 | if USE_COVERAGE | ||
14 | AM_CFLAGS = --coverage -O0 | ||
15 | XLIBS = -lgcov | ||
16 | endif | ||
17 | |||
18 | HEAP_PLUGIN = libgnunet_plugin_namestore_flat.la | ||
19 | if HAVE_TESTING | ||
20 | HEAP_TESTS = test_plugin_namestore_flat \ | ||
21 | test_namestore_api_store_flat \ | ||
22 | test_namestore_api_store_update_flat \ | ||
23 | test_namestore_api_remove_flat \ | ||
24 | test_namestore_api_zone_iteration_flat \ | ||
25 | test_namestore_api_lookup_nick_flat \ | ||
26 | test_namestore_api_monitoring_flat \ | ||
27 | test_namestore_api_lookup_public_flat \ | ||
28 | test_namestore_api_lookup_private_flat \ | ||
29 | test_namestore_api_lookup_shadow_flat \ | ||
30 | test_namestore_api_lookup_shadow_filter_flat \ | ||
31 | test_namestore_api_remove_not_existing_record_flat \ | ||
32 | test_namestore_api_zone_iteration_nick_flat \ | ||
33 | test_namestore_api_zone_iteration_specific_zone_flat \ | ||
34 | test_namestore_api_zone_iteration_stop_flat \ | ||
35 | test_namestore_api_monitoring_existing_flat \ | ||
36 | test_namestore_api_zone_to_name_flat \ | ||
37 | perf_namestore_api_zone_iteration_flat | ||
38 | endif | ||
39 | |||
40 | if HAVE_SQLITE | ||
41 | SQLITE_PLUGIN = libgnunet_plugin_namestore_sqlite.la | ||
42 | if HAVE_TESTING | ||
43 | SQLITE_TESTS = test_plugin_namestore_sqlite \ | ||
44 | test_namestore_api_store_sqlite \ | ||
45 | test_namestore_api_store_update_sqlite \ | ||
46 | test_namestore_api_zone_iteration_sqlite \ | ||
47 | test_namestore_api_remove_sqlite \ | ||
48 | test_namestore_api_lookup_nick_sqlite \ | ||
49 | test_namestore_api_monitoring_sqlite \ | ||
50 | test_namestore_api_lookup_public_sqlite \ | ||
51 | test_namestore_api_lookup_private_sqlite \ | ||
52 | test_namestore_api_lookup_shadow_sqlite \ | ||
53 | test_namestore_api_lookup_shadow_filter_sqlite \ | ||
54 | test_namestore_api_remove_not_existing_record_sqlite \ | ||
55 | test_namestore_api_zone_iteration_nick_sqlite \ | ||
56 | test_namestore_api_zone_iteration_specific_zone_sqlite \ | ||
57 | test_namestore_api_zone_iteration_stop_sqlite \ | ||
58 | test_namestore_api_monitoring_existing_sqlite \ | ||
59 | test_namestore_api_zone_to_name_sqlite \ | ||
60 | perf_namestore_api_zone_iteration_sqlite | ||
61 | endif | ||
62 | endif | ||
63 | |||
64 | if HAVE_POSTGRESQL | ||
65 | POSTGRES_PLUGIN = libgnunet_plugin_namestore_postgres.la | ||
66 | if HAVE_TESTING | ||
67 | POSTGRES_TESTS = test_plugin_namestore_postgres \ | ||
68 | test_namestore_api_store_postgres \ | ||
69 | test_namestore_api_store_update_postgres \ | ||
70 | test_namestore_api_remove_postgres \ | ||
71 | test_namestore_api_zone_iteration_postgres \ | ||
72 | test_namestore_api_lookup_nick_postgres \ | ||
73 | test_namestore_api_monitoring_postgres \ | ||
74 | test_namestore_api_lookup_public_postgres \ | ||
75 | test_namestore_api_lookup_private_postgres \ | ||
76 | test_namestore_api_lookup_shadow_postgres \ | ||
77 | test_namestore_api_lookup_shadow_filter_postgres \ | ||
78 | test_namestore_api_remove_not_existing_record_postgres \ | ||
79 | test_namestore_api_zone_iteration_nick_postgres \ | ||
80 | test_namestore_api_zone_iteration_specific_zone_postgres \ | ||
81 | test_namestore_api_zone_iteration_stop_postgres \ | ||
82 | test_namestore_api_monitoring_existing_postgres \ | ||
83 | test_namestore_api_zone_to_name_postgres \ | ||
84 | perf_namestore_api_zone_iteration_postgres | ||
85 | endif | ||
86 | endif | ||
87 | |||
88 | if HAVE_SQLITE | ||
89 | check_PROGRAMS = \ | ||
90 | $(SQLITE_TESTS) \ | ||
91 | $(POSTGRES_TESTS) \ | ||
92 | $(HEAP_TESTS) | ||
93 | endif | ||
94 | |||
95 | if ENABLE_TEST_RUN | ||
96 | AM_TESTS_ENVIRONMENT=export GNUNET_PREFIX=$${GNUNET_PREFIX:-@libdir@};export PATH=$${GNUNET_PREFIX:-@prefix@}/bin:$$PATH;unset XDG_DATA_HOME;unset XDG_CONFIG_HOME; | ||
97 | TESTS = \ | ||
98 | $(check_PROGRAMS) \ | ||
99 | $(check_SCRIPTS) | ||
100 | endif | ||
101 | |||
102 | REST_PLUGIN = libgnunet_plugin_rest_namestore.la | ||
103 | |||
104 | lib_LTLIBRARIES = \ | ||
105 | libgnunetnamestore.la | ||
106 | |||
107 | |||
108 | libexec_PROGRAMS = \ | ||
109 | gnunet-service-namestore | ||
110 | |||
111 | bin_PROGRAMS = \ | ||
112 | gnunet-namestore \ | ||
113 | gnunet-zoneimport | ||
114 | |||
115 | libexec_PROGRAMS += \ | ||
116 | gnunet-namestore-fcfsd | ||
117 | |||
118 | |||
119 | plugin_LTLIBRARIES = \ | ||
120 | $(SQLITE_PLUGIN) \ | ||
121 | $(POSTGRES_PLUGIN) \ | ||
122 | $(HEAP_PLUGIN) \ | ||
123 | $(REST_PLUGIN) | ||
124 | |||
125 | |||
126 | libgnunet_plugin_rest_namestore_la_SOURCES = \ | ||
127 | plugin_rest_namestore.c | ||
128 | libgnunet_plugin_rest_namestore_la_LIBADD = \ | ||
129 | libgnunetnamestore.la \ | ||
130 | $(top_builddir)/src/rest/libgnunetrest.la \ | ||
131 | $(top_builddir)/src/identity/libgnunetidentity.la \ | ||
132 | $(top_builddir)/src/json/libgnunetjson.la \ | ||
133 | $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \ | ||
134 | $(top_builddir)/src/gnsrecord/libgnunetgnsrecordjson.la \ | ||
135 | $(top_builddir)/src/util/libgnunetutil.la $(XLIBS) \ | ||
136 | $(LTLIBINTL) -ljansson $(MHD_LIBS) | ||
137 | libgnunet_plugin_rest_namestore_la_LDFLAGS = \ | ||
138 | $(GN_PLUGIN_LDFLAGS) | ||
139 | libgnunet_plugin_rest_namestore_la_CFLAGS = $(MHD_CFLAGS) $(AM_CFLAGS) | ||
140 | |||
141 | |||
142 | libgnunetnamestore_la_SOURCES = \ | ||
143 | namestore_api.c \ | ||
144 | namestore_api_monitor.c \ | ||
145 | namestore.h | ||
146 | libgnunetnamestore_la_LIBADD = \ | ||
147 | $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \ | ||
148 | $(top_builddir)/src/identity/libgnunetidentity.la \ | ||
149 | $(top_builddir)/src/statistics/libgnunetstatistics.la \ | ||
150 | $(top_builddir)/src/util/libgnunetutil.la \ | ||
151 | $(GN_LIBINTL) | ||
152 | libgnunetnamestore_la_LDFLAGS = \ | ||
153 | $(GN_LIB_LDFLAGS) \ | ||
154 | -version-info 0:1:0 | ||
155 | |||
156 | |||
157 | |||
158 | gnunet_zoneimport_SOURCES = \ | ||
159 | gnunet-zoneimport.c | ||
160 | gnunet_zoneimport_LDADD = \ | ||
161 | libgnunetnamestore.la \ | ||
162 | $(top_builddir)/src/statistics/libgnunetstatistics.la \ | ||
163 | $(top_builddir)/src/identity/libgnunetidentity.la \ | ||
164 | $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \ | ||
165 | $(top_builddir)/src/util/libgnunetutil.la \ | ||
166 | $(GN_LIBINTL) | ||
167 | |||
168 | gnunet_namestore_SOURCES = \ | ||
169 | gnunet-namestore.c | ||
170 | gnunet_namestore_LDADD = \ | ||
171 | $(top_builddir)/src/identity/libgnunetidentity.la \ | ||
172 | $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \ | ||
173 | $(top_builddir)/src/util/libgnunetutil.la \ | ||
174 | libgnunetnamestore.la \ | ||
175 | $(GN_LIBINTL) | ||
176 | |||
177 | |||
178 | gnunet_namestore_fcfsd_SOURCES = \ | ||
179 | gnunet-namestore-fcfsd.c | ||
180 | gnunet_namestore_fcfsd_LDADD = $(MHD_LIBS) \ | ||
181 | $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \ | ||
182 | $(top_builddir)/src/identity/libgnunetidentity.la \ | ||
183 | libgnunetnamestore.la \ | ||
184 | $(top_builddir)/src/util/libgnunetutil.la \ | ||
185 | $(top_builddir)/src/json/libgnunetjson.la \ | ||
186 | $(GN_LIBINTL) -ljansson | ||
187 | gnunet_namestore_fcfsd_CFLAGS = $(MHD_CFLAGS) $(AM_CFLAGS) | ||
188 | |||
189 | |||
190 | gnunet_service_namestore_SOURCES = \ | ||
191 | gnunet-service-namestore.c | ||
192 | |||
193 | gnunet_service_namestore_LDADD = \ | ||
194 | $(top_builddir)/src/namecache/libgnunetnamecache.la \ | ||
195 | $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \ | ||
196 | $(top_builddir)/src/identity/libgnunetidentity.la \ | ||
197 | $(top_builddir)/src/statistics/libgnunetstatistics.la \ | ||
198 | $(top_builddir)/src/util/libgnunetutil.la \ | ||
199 | libgnunetnamestore.la \ | ||
200 | $(GN_LIBINTL) | ||
201 | |||
202 | |||
203 | |||
204 | libgnunet_plugin_namestore_flat_la_SOURCES = \ | ||
205 | plugin_namestore_flat.c | ||
206 | libgnunet_plugin_namestore_flat_la_LIBADD = \ | ||
207 | $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \ | ||
208 | $(top_builddir)/src/identity/libgnunetidentity.la \ | ||
209 | $(top_builddir)/src/statistics/libgnunetstatistics.la \ | ||
210 | $(top_builddir)/src/util/libgnunetutil.la $(XLIBS) \ | ||
211 | $(LTLIBINTL) | ||
212 | libgnunet_plugin_namestore_flat_la_LDFLAGS = \ | ||
213 | $(GN_PLUGIN_LDFLAGS) | ||
214 | |||
215 | |||
216 | libgnunet_plugin_namestore_sqlite_la_SOURCES = \ | ||
217 | plugin_namestore_sqlite.c | ||
218 | libgnunet_plugin_namestore_sqlite_la_LIBADD = \ | ||
219 | $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \ | ||
220 | $(top_builddir)/src/identity/libgnunetidentity.la \ | ||
221 | $(top_builddir)/src/sq/libgnunetsq.la \ | ||
222 | $(top_builddir)/src/statistics/libgnunetstatistics.la \ | ||
223 | $(top_builddir)/src/util/libgnunetutil.la $(XLIBS) -lsqlite3 \ | ||
224 | $(LTLIBINTL) | ||
225 | libgnunet_plugin_namestore_sqlite_la_LDFLAGS = \ | ||
226 | $(GN_PLUGIN_LDFLAGS) | ||
227 | |||
228 | libgnunet_plugin_namestore_postgres_la_SOURCES = \ | ||
229 | plugin_namestore_postgres.c | ||
230 | libgnunet_plugin_namestore_postgres_la_LIBADD = \ | ||
231 | $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \ | ||
232 | $(top_builddir)/src/identity/libgnunetidentity.la \ | ||
233 | $(top_builddir)/src/pq/libgnunetpq.la \ | ||
234 | $(top_builddir)/src/statistics/libgnunetstatistics.la \ | ||
235 | $(top_builddir)/src/util/libgnunetutil.la $(XLIBS) -lpq \ | ||
236 | $(LTLIBINTL) | ||
237 | libgnunet_plugin_namestore_postgres_la_LDFLAGS = \ | ||
238 | $(GN_PLUGIN_LDFLAGS) $(POSTGRESQL_LDFLAGS) | ||
239 | |||
240 | test_namestore_api_store_flat_SOURCES = \ | ||
241 | test_namestore_api_store.c | ||
242 | test_namestore_api_store_flat_LDADD = \ | ||
243 | $(top_builddir)/src/testing/libgnunettesting.la \ | ||
244 | $(top_builddir)/src/util/libgnunetutil.la \ | ||
245 | $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \ | ||
246 | $(top_builddir)/src/identity/libgnunetidentity.la \ | ||
247 | libgnunetnamestore.la | ||
248 | |||
249 | test_namestore_api_store_sqlite_SOURCES = \ | ||
250 | test_namestore_api_store.c | ||
251 | test_namestore_api_store_sqlite_LDADD = \ | ||
252 | $(top_builddir)/src/testing/libgnunettesting.la \ | ||
253 | $(top_builddir)/src/util/libgnunetutil.la \ | ||
254 | $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \ | ||
255 | $(top_builddir)/src/identity/libgnunetidentity.la \ | ||
256 | libgnunetnamestore.la | ||
257 | |||
258 | test_namestore_api_store_postgres_SOURCES = \ | ||
259 | test_namestore_api_store.c | ||
260 | test_namestore_api_store_postgres_LDADD = \ | ||
261 | $(top_builddir)/src/testing/libgnunettesting.la \ | ||
262 | $(top_builddir)/src/util/libgnunetutil.la \ | ||
263 | $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \ | ||
264 | $(top_builddir)/src/identity/libgnunetidentity.la \ | ||
265 | libgnunetnamestore.la | ||
266 | |||
267 | test_namestore_api_store_update_flat_SOURCES = \ | ||
268 | test_namestore_api_store_update.c | ||
269 | test_namestore_api_store_update_flat_LDADD = \ | ||
270 | $(top_builddir)/src/testing/libgnunettesting.la \ | ||
271 | $(top_builddir)/src/util/libgnunetutil.la \ | ||
272 | $(top_builddir)/src/identity/libgnunetidentity.la \ | ||
273 | $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \ | ||
274 | $(top_builddir)/src/namecache/libgnunetnamecache.la \ | ||
275 | libgnunetnamestore.la | ||
276 | |||
277 | test_namestore_api_store_update_sqlite_SOURCES = \ | ||
278 | test_namestore_api_store_update.c | ||
279 | test_namestore_api_store_update_sqlite_LDADD = \ | ||
280 | $(top_builddir)/src/testing/libgnunettesting.la \ | ||
281 | $(top_builddir)/src/util/libgnunetutil.la \ | ||
282 | $(top_builddir)/src/identity/libgnunetidentity.la \ | ||
283 | $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \ | ||
284 | $(top_builddir)/src/namecache/libgnunetnamecache.la \ | ||
285 | libgnunetnamestore.la | ||
286 | |||
287 | test_namestore_api_store_update_postgres_SOURCES = \ | ||
288 | test_namestore_api_store_update.c | ||
289 | test_namestore_api_store_update_postgres_LDADD = \ | ||
290 | $(top_builddir)/src/testing/libgnunettesting.la \ | ||
291 | $(top_builddir)/src/util/libgnunetutil.la \ | ||
292 | $(top_builddir)/src/identity/libgnunetidentity.la \ | ||
293 | $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \ | ||
294 | $(top_builddir)/src/namecache/libgnunetnamecache.la \ | ||
295 | libgnunetnamestore.la | ||
296 | |||
297 | test_namestore_api_lookup_public_flat_SOURCES = \ | ||
298 | test_namestore_api_lookup_public.c | ||
299 | test_namestore_api_lookup_public_flat_LDADD = \ | ||
300 | $(top_builddir)/src/testing/libgnunettesting.la \ | ||
301 | $(top_builddir)/src/identity/libgnunetidentity.la \ | ||
302 | $(top_builddir)/src/util/libgnunetutil.la \ | ||
303 | $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \ | ||
304 | $(top_builddir)/src/namecache/libgnunetnamecache.la \ | ||
305 | libgnunetnamestore.la | ||
306 | |||
307 | test_namestore_api_lookup_public_sqlite_SOURCES = \ | ||
308 | test_namestore_api_lookup_public.c | ||
309 | test_namestore_api_lookup_public_sqlite_LDADD = \ | ||
310 | $(top_builddir)/src/testing/libgnunettesting.la \ | ||
311 | $(top_builddir)/src/util/libgnunetutil.la \ | ||
312 | $(top_builddir)/src/identity/libgnunetidentity.la \ | ||
313 | $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \ | ||
314 | $(top_builddir)/src/namecache/libgnunetnamecache.la \ | ||
315 | libgnunetnamestore.la | ||
316 | |||
317 | test_namestore_api_lookup_public_postgres_SOURCES = \ | ||
318 | test_namestore_api_lookup_public.c | ||
319 | test_namestore_api_lookup_public_postgres_LDADD = \ | ||
320 | $(top_builddir)/src/testing/libgnunettesting.la \ | ||
321 | $(top_builddir)/src/util/libgnunetutil.la \ | ||
322 | $(top_builddir)/src/identity/libgnunetidentity.la \ | ||
323 | $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \ | ||
324 | $(top_builddir)/src/namecache/libgnunetnamecache.la \ | ||
325 | libgnunetnamestore.la | ||
326 | |||
327 | test_namestore_api_lookup_nick_sqlite_SOURCES = \ | ||
328 | test_namestore_api_lookup_nick.c | ||
329 | test_namestore_api_lookup_nick_sqlite_LDADD = \ | ||
330 | $(top_builddir)/src/testing/libgnunettesting.la \ | ||
331 | $(top_builddir)/src/util/libgnunetutil.la \ | ||
332 | $(top_builddir)/src/identity/libgnunetidentity.la \ | ||
333 | $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \ | ||
334 | $(top_builddir)/src/namecache/libgnunetnamecache.la \ | ||
335 | libgnunetnamestore.la | ||
336 | |||
337 | test_namestore_api_lookup_nick_postgres_SOURCES = \ | ||
338 | test_namestore_api_lookup_nick.c | ||
339 | test_namestore_api_lookup_nick_postgres_LDADD = \ | ||
340 | $(top_builddir)/src/testing/libgnunettesting.la \ | ||
341 | $(top_builddir)/src/util/libgnunetutil.la \ | ||
342 | $(top_builddir)/src/identity/libgnunetidentity.la \ | ||
343 | $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \ | ||
344 | $(top_builddir)/src/namecache/libgnunetnamecache.la \ | ||
345 | libgnunetnamestore.la | ||
346 | |||
347 | test_namestore_api_lookup_nick_flat_SOURCES = \ | ||
348 | test_namestore_api_lookup_nick.c | ||
349 | test_namestore_api_lookup_nick_flat_LDADD = \ | ||
350 | $(top_builddir)/src/testing/libgnunettesting.la \ | ||
351 | $(top_builddir)/src/identity/libgnunetidentity.la \ | ||
352 | $(top_builddir)/src/util/libgnunetutil.la \ | ||
353 | $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \ | ||
354 | $(top_builddir)/src/namecache/libgnunetnamecache.la \ | ||
355 | libgnunetnamestore.la | ||
356 | |||
357 | test_namestore_api_lookup_private_flat_SOURCES = \ | ||
358 | test_namestore_api_lookup_private.c | ||
359 | test_namestore_api_lookup_private_flat_LDADD = \ | ||
360 | $(top_builddir)/src/testing/libgnunettesting.la \ | ||
361 | $(top_builddir)/src/identity/libgnunetidentity.la \ | ||
362 | $(top_builddir)/src/util/libgnunetutil.la \ | ||
363 | $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \ | ||
364 | $(top_builddir)/src/namecache/libgnunetnamecache.la \ | ||
365 | libgnunetnamestore.la | ||
366 | |||
367 | test_namestore_api_lookup_private_sqlite_SOURCES = \ | ||
368 | test_namestore_api_lookup_private.c | ||
369 | test_namestore_api_lookup_private_sqlite_LDADD = \ | ||
370 | $(top_builddir)/src/testing/libgnunettesting.la \ | ||
371 | $(top_builddir)/src/identity/libgnunetidentity.la \ | ||
372 | $(top_builddir)/src/util/libgnunetutil.la \ | ||
373 | $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \ | ||
374 | $(top_builddir)/src/namecache/libgnunetnamecache.la \ | ||
375 | libgnunetnamestore.la | ||
376 | |||
377 | test_namestore_api_lookup_private_postgres_SOURCES = \ | ||
378 | test_namestore_api_lookup_private.c | ||
379 | test_namestore_api_lookup_private_postgres_LDADD = \ | ||
380 | $(top_builddir)/src/identity/libgnunetidentity.la \ | ||
381 | $(top_builddir)/src/testing/libgnunettesting.la \ | ||
382 | $(top_builddir)/src/util/libgnunetutil.la \ | ||
383 | $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \ | ||
384 | $(top_builddir)/src/namecache/libgnunetnamecache.la \ | ||
385 | libgnunetnamestore.la | ||
386 | |||
387 | test_namestore_api_lookup_shadow_flat_SOURCES = \ | ||
388 | test_namestore_api_lookup_shadow.c | ||
389 | test_namestore_api_lookup_shadow_flat_LDADD = \ | ||
390 | $(top_builddir)/src/testing/libgnunettesting.la \ | ||
391 | $(top_builddir)/src/identity/libgnunetidentity.la \ | ||
392 | $(top_builddir)/src/util/libgnunetutil.la \ | ||
393 | $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \ | ||
394 | $(top_builddir)/src/namecache/libgnunetnamecache.la \ | ||
395 | libgnunetnamestore.la | ||
396 | |||
397 | test_namestore_api_lookup_shadow_sqlite_SOURCES = \ | ||
398 | test_namestore_api_lookup_shadow.c | ||
399 | test_namestore_api_lookup_shadow_sqlite_LDADD = \ | ||
400 | $(top_builddir)/src/testing/libgnunettesting.la \ | ||
401 | $(top_builddir)/src/util/libgnunetutil.la \ | ||
402 | $(top_builddir)/src/identity/libgnunetidentity.la \ | ||
403 | $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \ | ||
404 | $(top_builddir)/src/namecache/libgnunetnamecache.la \ | ||
405 | libgnunetnamestore.la | ||
406 | |||
407 | test_namestore_api_lookup_shadow_postgres_SOURCES = \ | ||
408 | test_namestore_api_lookup_shadow.c | ||
409 | test_namestore_api_lookup_shadow_postgres_LDADD = \ | ||
410 | $(top_builddir)/src/testing/libgnunettesting.la \ | ||
411 | $(top_builddir)/src/util/libgnunetutil.la \ | ||
412 | $(top_builddir)/src/identity/libgnunetidentity.la \ | ||
413 | $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \ | ||
414 | $(top_builddir)/src/namecache/libgnunetnamecache.la \ | ||
415 | libgnunetnamestore.la | ||
416 | |||
417 | test_namestore_api_lookup_shadow_filter_flat_SOURCES = \ | ||
418 | test_namestore_api_lookup_shadow_filter.c | ||
419 | test_namestore_api_lookup_shadow_filter_flat_LDADD = \ | ||
420 | $(top_builddir)/src/testing/libgnunettesting.la \ | ||
421 | $(top_builddir)/src/util/libgnunetutil.la \ | ||
422 | $(top_builddir)/src/identity/libgnunetidentity.la \ | ||
423 | $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \ | ||
424 | $(top_builddir)/src/namecache/libgnunetnamecache.la \ | ||
425 | libgnunetnamestore.la | ||
426 | |||
427 | test_namestore_api_lookup_shadow_filter_sqlite_SOURCES = \ | ||
428 | test_namestore_api_lookup_shadow_filter.c | ||
429 | test_namestore_api_lookup_shadow_filter_sqlite_LDADD = \ | ||
430 | $(top_builddir)/src/testing/libgnunettesting.la \ | ||
431 | $(top_builddir)/src/identity/libgnunetidentity.la \ | ||
432 | $(top_builddir)/src/util/libgnunetutil.la \ | ||
433 | $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \ | ||
434 | $(top_builddir)/src/namecache/libgnunetnamecache.la \ | ||
435 | libgnunetnamestore.la | ||
436 | test_namestore_api_lookup_shadow_filter_postgres_SOURCES = \ | ||
437 | test_namestore_api_lookup_shadow_filter.c | ||
438 | test_namestore_api_lookup_shadow_filter_postgres_LDADD = \ | ||
439 | $(top_builddir)/src/testing/libgnunettesting.la \ | ||
440 | $(top_builddir)/src/identity/libgnunetidentity.la \ | ||
441 | $(top_builddir)/src/util/libgnunetutil.la \ | ||
442 | $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \ | ||
443 | $(top_builddir)/src/namecache/libgnunetnamecache.la \ | ||
444 | libgnunetnamestore.la | ||
445 | |||
446 | test_namestore_api_remove_sqlite_SOURCES = \ | ||
447 | test_namestore_api_remove.c | ||
448 | test_namestore_api_remove_sqlite_LDADD = \ | ||
449 | $(top_builddir)/src/identity/libgnunetidentity.la \ | ||
450 | $(top_builddir)/src/testing/libgnunettesting.la \ | ||
451 | $(top_builddir)/src/util/libgnunetutil.la \ | ||
452 | $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \ | ||
453 | libgnunetnamestore.la | ||
454 | |||
455 | test_namestore_api_remove_postgres_SOURCES = \ | ||
456 | test_namestore_api_remove.c | ||
457 | test_namestore_api_remove_postgres_LDADD = \ | ||
458 | $(top_builddir)/src/identity/libgnunetidentity.la \ | ||
459 | $(top_builddir)/src/testing/libgnunettesting.la \ | ||
460 | $(top_builddir)/src/util/libgnunetutil.la \ | ||
461 | $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \ | ||
462 | libgnunetnamestore.la | ||
463 | |||
464 | test_namestore_api_remove_flat_SOURCES = \ | ||
465 | test_namestore_api_remove.c | ||
466 | test_namestore_api_remove_flat_LDADD = \ | ||
467 | $(top_builddir)/src/testing/libgnunettesting.la \ | ||
468 | $(top_builddir)/src/identity/libgnunetidentity.la \ | ||
469 | $(top_builddir)/src/util/libgnunetutil.la \ | ||
470 | $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \ | ||
471 | libgnunetnamestore.la | ||
472 | |||
473 | test_namestore_api_remove_not_existing_record_flat_SOURCES = \ | ||
474 | test_namestore_api_remove_not_existing_record.c | ||
475 | test_namestore_api_remove_not_existing_record_flat_LDADD = \ | ||
476 | $(top_builddir)/src/testing/libgnunettesting.la \ | ||
477 | $(top_builddir)/src/identity/libgnunetidentity.la \ | ||
478 | $(top_builddir)/src/util/libgnunetutil.la \ | ||
479 | $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \ | ||
480 | libgnunetnamestore.la | ||
481 | |||
482 | test_namestore_api_remove_not_existing_record_sqlite_SOURCES = \ | ||
483 | test_namestore_api_remove_not_existing_record.c | ||
484 | test_namestore_api_remove_not_existing_record_sqlite_LDADD = \ | ||
485 | $(top_builddir)/src/testing/libgnunettesting.la \ | ||
486 | $(top_builddir)/src/util/libgnunetutil.la \ | ||
487 | $(top_builddir)/src/identity/libgnunetidentity.la \ | ||
488 | $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \ | ||
489 | libgnunetnamestore.la | ||
490 | |||
491 | test_namestore_api_remove_not_existing_record_postgres_SOURCES = \ | ||
492 | test_namestore_api_remove_not_existing_record.c | ||
493 | test_namestore_api_remove_not_existing_record_postgres_LDADD = \ | ||
494 | $(top_builddir)/src/testing/libgnunettesting.la \ | ||
495 | $(top_builddir)/src/identity/libgnunetidentity.la \ | ||
496 | $(top_builddir)/src/util/libgnunetutil.la \ | ||
497 | $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \ | ||
498 | libgnunetnamestore.la | ||
499 | |||
500 | test_namestore_api_zone_to_name_flat_SOURCES = \ | ||
501 | test_namestore_api_zone_to_name.c | ||
502 | test_namestore_api_zone_to_name_flat_LDADD = \ | ||
503 | $(top_builddir)/src/identity/libgnunetidentity.la \ | ||
504 | $(top_builddir)/src/testing/libgnunettesting.la \ | ||
505 | $(top_builddir)/src/util/libgnunetutil.la \ | ||
506 | libgnunetnamestore.la | ||
507 | |||
508 | test_namestore_api_zone_to_name_sqlite_SOURCES = \ | ||
509 | test_namestore_api_zone_to_name.c | ||
510 | test_namestore_api_zone_to_name_sqlite_LDADD = \ | ||
511 | $(top_builddir)/src/identity/libgnunetidentity.la \ | ||
512 | $(top_builddir)/src/testing/libgnunettesting.la \ | ||
513 | $(top_builddir)/src/util/libgnunetutil.la \ | ||
514 | libgnunetnamestore.la | ||
515 | |||
516 | test_namestore_api_zone_to_name_postgres_SOURCES = \ | ||
517 | test_namestore_api_zone_to_name.c | ||
518 | test_namestore_api_zone_to_name_postgres_LDADD = \ | ||
519 | $(top_builddir)/src/identity/libgnunetidentity.la \ | ||
520 | $(top_builddir)/src/testing/libgnunettesting.la \ | ||
521 | $(top_builddir)/src/util/libgnunetutil.la \ | ||
522 | libgnunetnamestore.la | ||
523 | |||
524 | test_namestore_api_monitoring_flat_SOURCES = \ | ||
525 | test_namestore_api_monitoring.c | ||
526 | test_namestore_api_monitoring_flat_LDADD = \ | ||
527 | $(top_builddir)/src/testing/libgnunettesting.la \ | ||
528 | libgnunetnamestore.la \ | ||
529 | $(top_builddir)/src/identity/libgnunetidentity.la \ | ||
530 | $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \ | ||
531 | $(top_builddir)/src/util/libgnunetutil.la | ||
532 | |||
533 | test_namestore_api_monitoring_sqlite_SOURCES = \ | ||
534 | test_namestore_api_monitoring.c | ||
535 | test_namestore_api_monitoring_sqlite_LDADD = \ | ||
536 | $(top_builddir)/src/identity/libgnunetidentity.la \ | ||
537 | $(top_builddir)/src/testing/libgnunettesting.la \ | ||
538 | libgnunetnamestore.la \ | ||
539 | $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \ | ||
540 | $(top_builddir)/src/util/libgnunetutil.la | ||
541 | |||
542 | test_namestore_api_monitoring_postgres_SOURCES = \ | ||
543 | test_namestore_api_monitoring.c | ||
544 | test_namestore_api_monitoring_postgres_LDADD = \ | ||
545 | $(top_builddir)/src/testing/libgnunettesting.la \ | ||
546 | $(top_builddir)/src/identity/libgnunetidentity.la \ | ||
547 | libgnunetnamestore.la \ | ||
548 | $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \ | ||
549 | $(top_builddir)/src/util/libgnunetutil.la | ||
550 | |||
551 | test_namestore_api_monitoring_existing_flat_SOURCES = \ | ||
552 | test_namestore_api_monitoring_existing.c | ||
553 | test_namestore_api_monitoring_existing_flat_LDADD = \ | ||
554 | $(top_builddir)/src/testing/libgnunettesting.la \ | ||
555 | $(top_builddir)/src/identity/libgnunetidentity.la \ | ||
556 | libgnunetnamestore.la \ | ||
557 | $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \ | ||
558 | $(top_builddir)/src/util/libgnunetutil.la | ||
559 | |||
560 | test_namestore_api_monitoring_existing_sqlite_SOURCES = \ | ||
561 | test_namestore_api_monitoring_existing.c | ||
562 | test_namestore_api_monitoring_existing_sqlite_LDADD = \ | ||
563 | $(top_builddir)/src/testing/libgnunettesting.la \ | ||
564 | $(top_builddir)/src/identity/libgnunetidentity.la \ | ||
565 | libgnunetnamestore.la \ | ||
566 | $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \ | ||
567 | $(top_builddir)/src/util/libgnunetutil.la | ||
568 | |||
569 | test_namestore_api_monitoring_existing_postgres_SOURCES = \ | ||
570 | test_namestore_api_monitoring_existing.c | ||
571 | test_namestore_api_monitoring_existing_postgres_LDADD = \ | ||
572 | $(top_builddir)/src/testing/libgnunettesting.la \ | ||
573 | libgnunetnamestore.la \ | ||
574 | $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \ | ||
575 | $(top_builddir)/src/identity/libgnunetidentity.la \ | ||
576 | $(top_builddir)/src/util/libgnunetutil.la | ||
577 | |||
578 | test_namestore_api_zone_iteration_flat_SOURCES = \ | ||
579 | test_namestore_api_zone_iteration.c | ||
580 | test_namestore_api_zone_iteration_flat_LDADD = \ | ||
581 | $(top_builddir)/src/testing/libgnunettesting.la \ | ||
582 | $(top_builddir)/src/identity/libgnunetidentity.la \ | ||
583 | $(top_builddir)/src/util/libgnunetutil.la \ | ||
584 | $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \ | ||
585 | libgnunetnamestore.la | ||
586 | |||
587 | test_namestore_api_zone_iteration_sqlite_SOURCES = \ | ||
588 | test_namestore_api_zone_iteration.c | ||
589 | test_namestore_api_zone_iteration_sqlite_LDADD = \ | ||
590 | $(top_builddir)/src/testing/libgnunettesting.la \ | ||
591 | $(top_builddir)/src/identity/libgnunetidentity.la \ | ||
592 | $(top_builddir)/src/util/libgnunetutil.la \ | ||
593 | $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \ | ||
594 | libgnunetnamestore.la | ||
595 | |||
596 | test_namestore_api_zone_iteration_postgres_SOURCES = \ | ||
597 | test_namestore_api_zone_iteration.c | ||
598 | test_namestore_api_zone_iteration_postgres_LDADD = \ | ||
599 | $(top_builddir)/src/testing/libgnunettesting.la \ | ||
600 | $(top_builddir)/src/identity/libgnunetidentity.la \ | ||
601 | $(top_builddir)/src/util/libgnunetutil.la \ | ||
602 | $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \ | ||
603 | libgnunetnamestore.la | ||
604 | |||
605 | perf_namestore_api_zone_iteration_postgres_SOURCES = \ | ||
606 | perf_namestore_api_zone_iteration.c | ||
607 | perf_namestore_api_zone_iteration_postgres_LDADD = \ | ||
608 | $(top_builddir)/src/testing/libgnunettesting.la \ | ||
609 | $(top_builddir)/src/util/libgnunetutil.la \ | ||
610 | $(top_builddir)/src/identity/libgnunetidentity.la \ | ||
611 | $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \ | ||
612 | libgnunetnamestore.la | ||
613 | |||
614 | perf_namestore_api_zone_iteration_sqlite_SOURCES = \ | ||
615 | perf_namestore_api_zone_iteration.c | ||
616 | perf_namestore_api_zone_iteration_sqlite_LDADD = \ | ||
617 | $(top_builddir)/src/testing/libgnunettesting.la \ | ||
618 | $(top_builddir)/src/identity/libgnunetidentity.la \ | ||
619 | $(top_builddir)/src/util/libgnunetutil.la \ | ||
620 | $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \ | ||
621 | libgnunetnamestore.la | ||
622 | |||
623 | perf_namestore_api_zone_iteration_flat_SOURCES = \ | ||
624 | perf_namestore_api_zone_iteration.c | ||
625 | perf_namestore_api_zone_iteration_flat_LDADD = \ | ||
626 | $(top_builddir)/src/testing/libgnunettesting.la \ | ||
627 | $(top_builddir)/src/identity/libgnunetidentity.la \ | ||
628 | $(top_builddir)/src/util/libgnunetutil.la \ | ||
629 | $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \ | ||
630 | libgnunetnamestore.la | ||
631 | |||
632 | test_namestore_api_zone_iteration_nick_flat_SOURCES = \ | ||
633 | test_namestore_api_zone_iteration_nick.c | ||
634 | test_namestore_api_zone_iteration_nick_flat_LDADD = \ | ||
635 | $(top_builddir)/src/testing/libgnunettesting.la \ | ||
636 | $(top_builddir)/src/util/libgnunetutil.la \ | ||
637 | $(top_builddir)/src/identity/libgnunetidentity.la \ | ||
638 | $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \ | ||
639 | libgnunetnamestore.la | ||
640 | |||
641 | test_namestore_api_zone_iteration_nick_sqlite_SOURCES = \ | ||
642 | test_namestore_api_zone_iteration_nick.c | ||
643 | test_namestore_api_zone_iteration_nick_sqlite_LDADD = \ | ||
644 | $(top_builddir)/src/testing/libgnunettesting.la \ | ||
645 | $(top_builddir)/src/identity/libgnunetidentity.la \ | ||
646 | $(top_builddir)/src/util/libgnunetutil.la \ | ||
647 | $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \ | ||
648 | libgnunetnamestore.la | ||
649 | |||
650 | test_namestore_api_zone_iteration_nick_postgres_SOURCES = \ | ||
651 | test_namestore_api_zone_iteration_nick.c | ||
652 | test_namestore_api_zone_iteration_nick_postgres_LDADD = \ | ||
653 | $(top_builddir)/src/testing/libgnunettesting.la \ | ||
654 | $(top_builddir)/src/identity/libgnunetidentity.la \ | ||
655 | $(top_builddir)/src/util/libgnunetutil.la \ | ||
656 | $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \ | ||
657 | libgnunetnamestore.la | ||
658 | |||
659 | test_namestore_api_zone_iteration_specific_zone_flat_SOURCES = \ | ||
660 | test_namestore_api_zone_iteration_specific_zone.c | ||
661 | test_namestore_api_zone_iteration_specific_zone_flat_LDADD = \ | ||
662 | $(top_builddir)/src/testing/libgnunettesting.la \ | ||
663 | $(top_builddir)/src/identity/libgnunetidentity.la \ | ||
664 | $(top_builddir)/src/util/libgnunetutil.la \ | ||
665 | $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \ | ||
666 | libgnunetnamestore.la | ||
667 | |||
668 | test_namestore_api_zone_iteration_specific_zone_sqlite_SOURCES = \ | ||
669 | test_namestore_api_zone_iteration_specific_zone.c | ||
670 | test_namestore_api_zone_iteration_specific_zone_sqlite_LDADD = \ | ||
671 | $(top_builddir)/src/testing/libgnunettesting.la \ | ||
672 | $(top_builddir)/src/identity/libgnunetidentity.la \ | ||
673 | $(top_builddir)/src/util/libgnunetutil.la \ | ||
674 | $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \ | ||
675 | libgnunetnamestore.la | ||
676 | |||
677 | test_namestore_api_zone_iteration_specific_zone_postgres_SOURCES = \ | ||
678 | test_namestore_api_zone_iteration_specific_zone.c | ||
679 | test_namestore_api_zone_iteration_specific_zone_postgres_LDADD = \ | ||
680 | $(top_builddir)/src/testing/libgnunettesting.la \ | ||
681 | $(top_builddir)/src/identity/libgnunetidentity.la \ | ||
682 | $(top_builddir)/src/util/libgnunetutil.la \ | ||
683 | $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \ | ||
684 | libgnunetnamestore.la | ||
685 | |||
686 | test_namestore_api_zone_iteration_stop_flat_SOURCES = \ | ||
687 | test_namestore_api_zone_iteration_stop.c | ||
688 | test_namestore_api_zone_iteration_stop_flat_LDADD = \ | ||
689 | $(top_builddir)/src/testing/libgnunettesting.la \ | ||
690 | $(top_builddir)/src/identity/libgnunetidentity.la \ | ||
691 | $(top_builddir)/src/util/libgnunetutil.la \ | ||
692 | $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \ | ||
693 | libgnunetnamestore.la | ||
694 | |||
695 | test_namestore_api_zone_iteration_stop_sqlite_SOURCES = \ | ||
696 | test_namestore_api_zone_iteration_stop.c | ||
697 | test_namestore_api_zone_iteration_stop_sqlite_LDADD = \ | ||
698 | $(top_builddir)/src/testing/libgnunettesting.la \ | ||
699 | $(top_builddir)/src/identity/libgnunetidentity.la \ | ||
700 | $(top_builddir)/src/util/libgnunetutil.la \ | ||
701 | $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \ | ||
702 | libgnunetnamestore.la | ||
703 | |||
704 | test_namestore_api_zone_iteration_stop_postgres_SOURCES = \ | ||
705 | test_namestore_api_zone_iteration_stop.c | ||
706 | test_namestore_api_zone_iteration_stop_postgres_LDADD = \ | ||
707 | $(top_builddir)/src/testing/libgnunettesting.la \ | ||
708 | $(top_builddir)/src/identity/libgnunetidentity.la \ | ||
709 | $(top_builddir)/src/util/libgnunetutil.la \ | ||
710 | $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \ | ||
711 | libgnunetnamestore.la | ||
712 | |||
713 | test_plugin_namestore_flat_SOURCES = \ | ||
714 | test_plugin_namestore.c | ||
715 | test_plugin_namestore_flat_LDADD = \ | ||
716 | $(top_builddir)/src/testing/libgnunettesting.la \ | ||
717 | $(top_builddir)/src/identity/libgnunetidentity.la \ | ||
718 | $(top_builddir)/src/util/libgnunetutil.la | ||
719 | |||
720 | test_plugin_namestore_sqlite_SOURCES = \ | ||
721 | test_plugin_namestore.c | ||
722 | test_plugin_namestore_sqlite_LDADD = \ | ||
723 | $(top_builddir)/src/testing/libgnunettesting.la \ | ||
724 | $(top_builddir)/src/identity/libgnunetidentity.la \ | ||
725 | $(top_builddir)/src/util/libgnunetutil.la | ||
726 | |||
727 | test_plugin_namestore_postgres_SOURCES = \ | ||
728 | test_plugin_namestore.c | ||
729 | test_plugin_namestore_postgres_LDADD = \ | ||
730 | $(top_builddir)/src/identity/libgnunetidentity.la \ | ||
731 | $(top_builddir)/src/testing/libgnunettesting.la \ | ||
732 | $(top_builddir)/src/util/libgnunetutil.la | ||
733 | |||
734 | check_SCRIPTS = \ | ||
735 | test_namestore_put.sh \ | ||
736 | test_namestore_lookup.sh \ | ||
737 | test_namestore_delete.sh | ||
738 | |||
739 | check_SCRIPTS += \ | ||
740 | test_plugin_rest_namestore.sh | ||
741 | |||
742 | EXTRA_DIST = \ | ||
743 | test_common.c \ | ||
744 | test_namestore_api.conf \ | ||
745 | test_namestore_api_postgres.conf \ | ||
746 | test_namestore_api_sqlite.conf \ | ||
747 | test_namestore_api_flat.conf \ | ||
748 | perf_namestore_api_postgres.conf \ | ||
749 | perf_namestore_api_sqlite.conf \ | ||
750 | perf_namestore_api_flat.conf \ | ||
751 | test_plugin_namestore_sqlite.conf \ | ||
752 | test_plugin_namestore_postgres.conf \ | ||
753 | test_plugin_namestore_flat.conf \ | ||
754 | test_hostkey \ | ||
755 | $(check_SCRIPTS) | ||
diff --git a/src/namestore/gnunet-namestore-fcfsd.c b/src/namestore/gnunet-namestore-fcfsd.c deleted file mode 100644 index 95d4c5878..000000000 --- a/src/namestore/gnunet-namestore-fcfsd.c +++ /dev/null | |||
@@ -1,1138 +0,0 @@ | |||
1 | /* | ||
2 | This file is part of GNUnet. | ||
3 | Copyright (C) 2012-2021 GNUnet e.V. | ||
4 | |||
5 | GNUnet is free software: you can redistribute it and/or modify it | ||
6 | under the terms of the GNU Affero General Public License as published | ||
7 | by the Free Software Foundation, either version 3 of the License, | ||
8 | or (at your option) any later version. | ||
9 | |||
10 | GNUnet is distributed in the hope that it will be useful, but | ||
11 | WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
13 | Affero General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU Affero General Public License | ||
16 | along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
17 | |||
18 | SPDX-License-Identifier: AGPL3.0-or-later | ||
19 | */ | ||
20 | |||
21 | /** | ||
22 | * @file gnunet-namestore-fcfsd.c | ||
23 | * @brief HTTP daemon that offers first-come-first-serve GNS domain registration | ||
24 | * @author Christian Grothoff | ||
25 | */ | ||
26 | |||
27 | #include "platform.h" | ||
28 | #include <microhttpd.h> | ||
29 | #include "gnunet_util_lib.h" | ||
30 | #include "gnunet_identity_service.h" | ||
31 | #include "gnunet_gnsrecord_lib.h" | ||
32 | #include "gnunet_namestore_service.h" | ||
33 | #include "gnunet_mhd_compat.h" | ||
34 | #include "gnunet_json_lib.h" | ||
35 | |||
36 | /** | ||
37 | * Structure representing a static page. | ||
38 | * "Static" means that the server does not process the page before sending it | ||
39 | * to the client. Clients can still process the received data, for example | ||
40 | * because there are scripting elements within. | ||
41 | */ | ||
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_IDENTITY_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_IDENTITY_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 | * Task ran at shutdown to clean up everything. | ||
169 | * | ||
170 | * @param cls unused | ||
171 | */ | ||
172 | static void | ||
173 | do_shutdown (void *cls) | ||
174 | { | ||
175 | /* We cheat a bit here: the file descriptor is implicitly closed by MHD, so | ||
176 | calling `GNUNET_DISK_file_close' would generate a spurious warning message | ||
177 | in the log. Since that function does nothing but close the descriptor and | ||
178 | free the allocated memory, After destroying the response all that's left to | ||
179 | do is call `GNUNET_free'. */ | ||
180 | if (NULL != main_page) | ||
181 | { | ||
182 | MHD_destroy_response (main_page->response); | ||
183 | GNUNET_free (main_page->handle); | ||
184 | GNUNET_free (main_page); | ||
185 | } | ||
186 | if (NULL != notfound_page) | ||
187 | { | ||
188 | MHD_destroy_response (notfound_page->response); | ||
189 | GNUNET_free (notfound_page->handle); | ||
190 | GNUNET_free (notfound_page); | ||
191 | } | ||
192 | if (NULL != forbidden_page) | ||
193 | { | ||
194 | MHD_destroy_response (forbidden_page->response); | ||
195 | GNUNET_free (forbidden_page->handle); | ||
196 | GNUNET_free (forbidden_page); | ||
197 | } | ||
198 | |||
199 | if (NULL != namestore) | ||
200 | { | ||
201 | GNUNET_NAMESTORE_disconnect (namestore); | ||
202 | } | ||
203 | |||
204 | if (NULL != identity) | ||
205 | { | ||
206 | GNUNET_IDENTITY_disconnect (identity); | ||
207 | } | ||
208 | } | ||
209 | |||
210 | |||
211 | /** | ||
212 | * Called when the HTTP server has some pending operations. | ||
213 | * | ||
214 | * @param cls unused | ||
215 | */ | ||
216 | static void | ||
217 | do_httpd (void *cls); | ||
218 | |||
219 | /** | ||
220 | * Schedule a task to run MHD. | ||
221 | */ | ||
222 | static void | ||
223 | run_httpd (void) | ||
224 | { | ||
225 | fd_set rs; | ||
226 | fd_set ws; | ||
227 | fd_set es; | ||
228 | |||
229 | struct GNUNET_NETWORK_FDSet *grs = GNUNET_NETWORK_fdset_create (); | ||
230 | struct GNUNET_NETWORK_FDSet *gws = GNUNET_NETWORK_fdset_create (); | ||
231 | struct GNUNET_NETWORK_FDSet *ges = GNUNET_NETWORK_fdset_create (); | ||
232 | |||
233 | FD_ZERO (&rs); | ||
234 | FD_ZERO (&ws); | ||
235 | FD_ZERO (&es); | ||
236 | |||
237 | int max = -1; | ||
238 | GNUNET_assert (MHD_YES == MHD_get_fdset (httpd, &rs, &ws, &es, &max)); | ||
239 | |||
240 | unsigned MHD_LONG_LONG timeout = 0; | ||
241 | struct GNUNET_TIME_Relative gtime = GNUNET_TIME_UNIT_FOREVER_REL; | ||
242 | if (MHD_YES == MHD_get_timeout (httpd, &timeout)) | ||
243 | { | ||
244 | gtime = GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MILLISECONDS, | ||
245 | timeout); | ||
246 | } | ||
247 | |||
248 | GNUNET_NETWORK_fdset_copy_native (grs, &rs, max + 1); | ||
249 | GNUNET_NETWORK_fdset_copy_native (gws, &ws, max + 1); | ||
250 | GNUNET_NETWORK_fdset_copy_native (ges, &es, max + 1); | ||
251 | |||
252 | httpd_task = GNUNET_SCHEDULER_add_select (GNUNET_SCHEDULER_PRIORITY_HIGH, | ||
253 | gtime, | ||
254 | grs, | ||
255 | gws, | ||
256 | &do_httpd, | ||
257 | NULL); | ||
258 | GNUNET_NETWORK_fdset_destroy (grs); | ||
259 | GNUNET_NETWORK_fdset_destroy (gws); | ||
260 | GNUNET_NETWORK_fdset_destroy (ges); | ||
261 | } | ||
262 | |||
263 | |||
264 | /** | ||
265 | * Called when the HTTP server has some pending operations. | ||
266 | * | ||
267 | * @param cls unused | ||
268 | */ | ||
269 | static void | ||
270 | do_httpd (void *cls) | ||
271 | { | ||
272 | httpd_task = NULL; | ||
273 | MHD_run (httpd); | ||
274 | run_httpd (); | ||
275 | } | ||
276 | |||
277 | |||
278 | static void | ||
279 | run_httpd_now (void) | ||
280 | { | ||
281 | if (NULL != httpd_task) | ||
282 | { | ||
283 | GNUNET_SCHEDULER_cancel (httpd_task); | ||
284 | httpd_task = NULL; | ||
285 | } | ||
286 | httpd_task = GNUNET_SCHEDULER_add_now (&do_httpd, NULL); | ||
287 | } | ||
288 | |||
289 | |||
290 | /** | ||
291 | * Generate a JSON object. | ||
292 | * | ||
293 | * @param key the key for the first element | ||
294 | * @param value the value for the first element | ||
295 | * @param ... key-value pairs of the object, terminated by NULL | ||
296 | * @return a JSON string (allocated) | ||
297 | */ | ||
298 | static char * | ||
299 | make_json (const char *key, const char *value, ...) | ||
300 | { | ||
301 | va_list args; | ||
302 | va_start (args, value); | ||
303 | |||
304 | json_t *obj = NULL; | ||
305 | |||
306 | obj = json_object (); | ||
307 | if ((NULL == key) || (NULL == value)) | ||
308 | { | ||
309 | va_end (args); | ||
310 | return json_dumps (obj, JSON_COMPACT); | ||
311 | } | ||
312 | |||
313 | json_object_set (obj, key, json_string (value)); | ||
314 | |||
315 | char *k = va_arg (args, char *); | ||
316 | if (NULL == k) | ||
317 | { | ||
318 | va_end (args); | ||
319 | return json_dumps (obj, JSON_COMPACT); | ||
320 | } | ||
321 | char *v = va_arg (args, char *); | ||
322 | if (NULL == v) | ||
323 | { | ||
324 | va_end (args); | ||
325 | return json_dumps (obj, JSON_COMPACT); | ||
326 | } | ||
327 | |||
328 | while (NULL != k && NULL != v) | ||
329 | { | ||
330 | json_object_set (obj, k, json_string (v)); | ||
331 | k = va_arg (args, char *); | ||
332 | if (NULL != k) | ||
333 | { | ||
334 | v = va_arg (args, char *); | ||
335 | } | ||
336 | } | ||
337 | |||
338 | va_end (args); | ||
339 | |||
340 | char *json = json_dumps (obj, JSON_COMPACT); | ||
341 | json_decref (obj); | ||
342 | |||
343 | return json; | ||
344 | } | ||
345 | |||
346 | |||
347 | /** | ||
348 | * The namestore search task failed. | ||
349 | * | ||
350 | * @param cls the request data | ||
351 | */ | ||
352 | static void | ||
353 | search_error_cb (void *cls) | ||
354 | { | ||
355 | struct RequestData *rd = cls; | ||
356 | MHD_resume_connection (rd->c); | ||
357 | rd->searching = NULL; | ||
358 | rd->body = make_json ("error", "true", | ||
359 | "message", _ ("can not search the namestore"), | ||
360 | NULL); | ||
361 | rd->body_length = strlen (rd->body); | ||
362 | rd->code = MHD_HTTP_INTERNAL_SERVER_ERROR; | ||
363 | run_httpd_now (); | ||
364 | } | ||
365 | |||
366 | |||
367 | /** | ||
368 | * The lookup terminated with some results. | ||
369 | * | ||
370 | * @param cls closure | ||
371 | * @param zone the private key of the zone | ||
372 | * @param label the result label | ||
373 | * @param count number of records found | ||
374 | * @param d records found | ||
375 | */ | ||
376 | static void | ||
377 | search_done_cb (void *cls, | ||
378 | const struct GNUNET_IDENTITY_PrivateKey *zone, | ||
379 | const char *label, | ||
380 | unsigned int count, | ||
381 | const struct GNUNET_GNSRECORD_Data *d) | ||
382 | { | ||
383 | (void) zone; | ||
384 | (void) d; | ||
385 | |||
386 | struct RequestData *rd = cls; | ||
387 | MHD_resume_connection (rd->c); | ||
388 | |||
389 | rd->searching = NULL; | ||
390 | rd->body = make_json ("error", "false", | ||
391 | "free", (0 == count) ? "true" : "false", | ||
392 | NULL); | ||
393 | rd->body_length = strlen (rd->body); | ||
394 | rd->code = MHD_HTTP_OK; | ||
395 | |||
396 | run_httpd_now (); | ||
397 | } | ||
398 | |||
399 | |||
400 | /** | ||
401 | * An error occurred while registering a name. | ||
402 | * | ||
403 | * @param cls the connection | ||
404 | */ | ||
405 | static void | ||
406 | register_error_cb (void *cls) | ||
407 | { | ||
408 | struct RequestData *rd = cls; | ||
409 | |||
410 | MHD_resume_connection (rd->c); | ||
411 | rd->searching = NULL; | ||
412 | rd->body = make_json ("error", "true", | ||
413 | "message", _ ("unable to scan namestore"), | ||
414 | NULL); | ||
415 | rd->body_length = strlen (rd->body); | ||
416 | rd->code = MHD_HTTP_INTERNAL_SERVER_ERROR; | ||
417 | run_httpd_now (); | ||
418 | } | ||
419 | |||
420 | |||
421 | /** | ||
422 | * A name/key pair has been successfully registered, or maybe not. | ||
423 | * | ||
424 | * @param cls the connection | ||
425 | * @param status result of the operation | ||
426 | * @param emsg error message if any | ||
427 | */ | ||
428 | static void | ||
429 | register_done_cb (void *cls, | ||
430 | int32_t status, | ||
431 | const char *emsg) | ||
432 | { | ||
433 | struct RequestData *rd = cls; | ||
434 | |||
435 | MHD_resume_connection (rd->c); | ||
436 | rd->searching = NULL; | ||
437 | |||
438 | if ((GNUNET_SYSERR == status) || (GNUNET_NO == status)) | ||
439 | { | ||
440 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, | ||
441 | _ ("Failed to create record for `%s': %s\n"), | ||
442 | rd->register_name, | ||
443 | emsg); | ||
444 | rd->body = make_json ("error", "true", | ||
445 | "message", emsg, | ||
446 | NULL); | ||
447 | rd->body_length = strlen (rd->body); | ||
448 | rd->code = MHD_HTTP_INTERNAL_SERVER_ERROR; | ||
449 | } | ||
450 | else | ||
451 | { | ||
452 | rd->body = make_json ("error", "false", | ||
453 | "message", _ ("no errors"), | ||
454 | NULL); | ||
455 | rd->body_length = strlen (rd->body); | ||
456 | rd->code = MHD_HTTP_OK; | ||
457 | } | ||
458 | |||
459 | run_httpd_now (); | ||
460 | } | ||
461 | |||
462 | |||
463 | /** | ||
464 | * Attempt to register the requested name. | ||
465 | * | ||
466 | * @param cls the connection | ||
467 | * @param key the zone key | ||
468 | * @param label name of the record | ||
469 | * @param count number of records found | ||
470 | * @param d records | ||
471 | */ | ||
472 | static void | ||
473 | register_do_cb (void *cls, | ||
474 | const struct GNUNET_IDENTITY_PrivateKey *key, | ||
475 | const char *label, | ||
476 | unsigned int count, | ||
477 | const struct GNUNET_GNSRECORD_Data *d) | ||
478 | { | ||
479 | (void) key; | ||
480 | (void) d; | ||
481 | |||
482 | struct RequestData *rd = cls; | ||
483 | |||
484 | rd->searching = NULL; | ||
485 | |||
486 | if (0 != count) | ||
487 | { | ||
488 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, | ||
489 | _ ("The requested key `%s' exists as `%s'\n"), | ||
490 | rd->register_key, | ||
491 | label); | ||
492 | |||
493 | MHD_resume_connection (rd->c); | ||
494 | rd->searching = NULL; | ||
495 | rd->body = make_json ("error", "true", | ||
496 | "message", _ ("key exists"), | ||
497 | NULL); | ||
498 | rd->body_length = strlen (rd->body); | ||
499 | rd->code = MHD_HTTP_FORBIDDEN; | ||
500 | run_httpd_now (); | ||
501 | return; | ||
502 | } | ||
503 | |||
504 | struct GNUNET_GNSRECORD_Data gd; | ||
505 | char *gdraw = NULL; | ||
506 | |||
507 | if (GNUNET_OK != GNUNET_GNSRECORD_data_from_identity (&(rd->key), | ||
508 | &gdraw, | ||
509 | &(gd.data_size), | ||
510 | &(gd.record_type))) | ||
511 | { | ||
512 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, | ||
513 | _ ("Error creating record data\n")); | ||
514 | MHD_resume_connection (rd->c); | ||
515 | rd->searching = NULL; | ||
516 | rd->body = make_json ("error", "true", | ||
517 | "message", _ ("unable to store record"), | ||
518 | NULL); | ||
519 | rd->body_length = strlen (rd->body); | ||
520 | rd->code = MHD_HTTP_INTERNAL_SERVER_ERROR; | ||
521 | run_httpd_now (); | ||
522 | return; | ||
523 | } | ||
524 | |||
525 | gd.data = gdraw; | ||
526 | gd.expiration_time = UINT64_MAX; | ||
527 | gd.flags = GNUNET_GNSRECORD_RF_NONE; | ||
528 | |||
529 | rd->searching = GNUNET_NAMESTORE_records_store (namestore, | ||
530 | zone_key, | ||
531 | rd->register_name, | ||
532 | 1, | ||
533 | &gd, | ||
534 | ®ister_done_cb, | ||
535 | rd); | ||
536 | |||
537 | GNUNET_free (gdraw); | ||
538 | } | ||
539 | |||
540 | |||
541 | /** | ||
542 | * An error occurred while iterating the namestore. | ||
543 | * | ||
544 | * @param cls the connection | ||
545 | */ | ||
546 | static void | ||
547 | iterate_error_cb (void *cls) | ||
548 | { | ||
549 | struct RequestData *rd = cls; | ||
550 | |||
551 | MHD_resume_connection (rd->c); | ||
552 | rd->iterating = NULL; | ||
553 | rd->body = make_json ("error", "true", | ||
554 | "message", _ ("unable to scan namestore"), | ||
555 | NULL); | ||
556 | rd->body_length = strlen (rd->body); | ||
557 | rd->code = MHD_HTTP_INTERNAL_SERVER_ERROR; | ||
558 | run_httpd_now (); | ||
559 | } | ||
560 | |||
561 | |||
562 | /** | ||
563 | * A block was received from the namestore. | ||
564 | * | ||
565 | * @param cls the connection | ||
566 | * @param key the zone key | ||
567 | * @param label the records' label | ||
568 | * @param count number of records found | ||
569 | * @param d the found records | ||
570 | */ | ||
571 | static void | ||
572 | iterate_do_cb (void *cls, | ||
573 | const struct GNUNET_IDENTITY_PrivateKey *key, | ||
574 | const char *label, | ||
575 | unsigned int count, | ||
576 | const struct GNUNET_GNSRECORD_Data *d) | ||
577 | { | ||
578 | (void) key; | ||
579 | (void) label; | ||
580 | (void) d; | ||
581 | |||
582 | struct RequestData *rd = cls; | ||
583 | |||
584 | if (0 == strcmp (label, rd->register_name)) | ||
585 | { | ||
586 | GNUNET_break (0 != count); | ||
587 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, | ||
588 | _ ("Requested name `%s' exists with `%u' records\n"), | ||
589 | rd->register_name, | ||
590 | count); | ||
591 | |||
592 | MHD_resume_connection (rd->c); | ||
593 | rd->body = make_json ("error", "true", | ||
594 | "message", _ ("name exists\n"), | ||
595 | NULL); | ||
596 | rd->body_length = strlen (rd->body); | ||
597 | rd->code = MHD_HTTP_FORBIDDEN; | ||
598 | GNUNET_NAMESTORE_zone_iteration_stop (rd->iterating); | ||
599 | run_httpd_now (); | ||
600 | return; | ||
601 | } | ||
602 | |||
603 | GNUNET_NAMESTORE_zone_iterator_next (rd->iterating, 1); | ||
604 | } | ||
605 | |||
606 | |||
607 | /** | ||
608 | * All entries in the namestore have been iterated over. | ||
609 | * | ||
610 | * @param cls the connection | ||
611 | */ | ||
612 | static void | ||
613 | iterate_done_cb (void *cls) | ||
614 | { | ||
615 | struct RequestData *rd = cls; | ||
616 | |||
617 | rd->iterating = NULL; | ||
618 | |||
619 | /* See if the key was not registered already */ | ||
620 | rd->searching = GNUNET_NAMESTORE_zone_to_name (namestore, | ||
621 | zone_key, | ||
622 | &(rd->key), | ||
623 | ®ister_error_cb, | ||
624 | rd, | ||
625 | ®ister_do_cb, | ||
626 | rd); | ||
627 | } | ||
628 | |||
629 | |||
630 | /** | ||
631 | * Generate a response containing JSON and send it to the client. | ||
632 | * | ||
633 | * @param c the connection | ||
634 | * @param body the response body | ||
635 | * @param length the body length in bytes | ||
636 | * @param code the response code | ||
637 | * @return MHD_NO on error | ||
638 | */ | ||
639 | static MHD_RESULT | ||
640 | serve_json (struct MHD_Connection *c, | ||
641 | char *body, | ||
642 | size_t length, | ||
643 | int code) | ||
644 | { | ||
645 | struct MHD_Response *response = | ||
646 | MHD_create_response_from_buffer (length, | ||
647 | body, | ||
648 | MHD_RESPMEM_PERSISTENT); | ||
649 | MHD_RESULT r = MHD_queue_response (c, code, response); | ||
650 | MHD_destroy_response (response); | ||
651 | return r; | ||
652 | } | ||
653 | |||
654 | |||
655 | /** | ||
656 | * Send a response back to a connected client. | ||
657 | * | ||
658 | * @param cls unused | ||
659 | * @param connection the connection with the client | ||
660 | * @param url the requested address | ||
661 | * @param method the HTTP method used | ||
662 | * @param version the protocol version (including the "HTTP/" part) | ||
663 | * @param upload_data data sent with a POST request | ||
664 | * @param upload_data_size length in bytes of the POST data | ||
665 | * @param ptr used to pass data between request handling phases | ||
666 | * @return MHD_NO on error | ||
667 | */ | ||
668 | static MHD_RESULT | ||
669 | create_response (void *cls, | ||
670 | struct MHD_Connection *connection, | ||
671 | const char *url, | ||
672 | const char *method, | ||
673 | const char *version, | ||
674 | const char *upload_data, | ||
675 | size_t *upload_data_size, | ||
676 | void **ptr) | ||
677 | { | ||
678 | (void) cls; | ||
679 | (void) version; | ||
680 | |||
681 | struct RequestData *rd = *ptr; | ||
682 | |||
683 | if (0 == strcmp (method, MHD_HTTP_METHOD_GET)) | ||
684 | { | ||
685 | /* Handle a previously suspended request */ | ||
686 | if (NULL != rd) | ||
687 | { | ||
688 | return serve_json (rd->c, rd->body, rd->body_length, rd->code); | ||
689 | } | ||
690 | |||
691 | if (0 == strcmp ("/", url)) | ||
692 | { | ||
693 | return MHD_queue_response (connection, | ||
694 | MHD_HTTP_OK, | ||
695 | main_page->response); | ||
696 | } | ||
697 | |||
698 | if (0 == strcmp ("/search", url)) | ||
699 | { | ||
700 | const char *name = MHD_lookup_connection_value (connection, | ||
701 | MHD_GET_ARGUMENT_KIND, | ||
702 | "name"); | ||
703 | if (NULL == name) | ||
704 | { | ||
705 | return MHD_queue_response (connection, | ||
706 | MHD_HTTP_BAD_REQUEST, | ||
707 | forbidden_page->response); | ||
708 | } | ||
709 | |||
710 | MHD_suspend_connection (connection); | ||
711 | rd = GNUNET_new (struct RequestData); | ||
712 | rd->c = connection; | ||
713 | rd->searching = GNUNET_NAMESTORE_records_lookup (namestore, | ||
714 | zone_key, | ||
715 | name, | ||
716 | &search_error_cb, | ||
717 | rd, | ||
718 | &search_done_cb, | ||
719 | rd); | ||
720 | *ptr = rd; | ||
721 | return MHD_YES; | ||
722 | } | ||
723 | |||
724 | return MHD_queue_response (connection, | ||
725 | MHD_HTTP_NOT_FOUND, | ||
726 | notfound_page->response); | ||
727 | } | ||
728 | |||
729 | if (0 == strcmp (method, MHD_HTTP_METHOD_HEAD)) | ||
730 | { | ||
731 | /* We take a shortcut here by always serving the main page: starting a | ||
732 | namestore lookup, allocating the necessary resources, waiting for the | ||
733 | lookup to complete and then discard everything just because it was a HEAD | ||
734 | and thus only the headers are significative, is an unnecessary waste of | ||
735 | resources. The handling of this method could be smarter, for example by | ||
736 | sending a proper content type header based on the endpoint, but this is | ||
737 | not a service in which HEAD requests are significant, so there's no need | ||
738 | to spend too much time here. */ | ||
739 | return MHD_queue_response (connection, | ||
740 | MHD_HTTP_OK, | ||
741 | main_page->response); | ||
742 | } | ||
743 | |||
744 | if (0 == strcmp (method, MHD_HTTP_METHOD_POST)) | ||
745 | { | ||
746 | if (0 == strcmp ("/register", url)) | ||
747 | { | ||
748 | /* Handle a previously suspended request */ | ||
749 | if ((NULL != rd) && (NULL != rd->body)) | ||
750 | { | ||
751 | return serve_json (rd->c, rd->body, rd->body_length, rd->code); | ||
752 | } | ||
753 | |||
754 | if (NULL == rd) | ||
755 | { | ||
756 | rd = GNUNET_new (struct RequestData); | ||
757 | rd->c = connection; | ||
758 | rd->body = NULL; | ||
759 | rd->ptr = NULL; | ||
760 | *ptr = rd; | ||
761 | } | ||
762 | |||
763 | json_t *json = NULL; | ||
764 | enum GNUNET_JSON_PostResult result = | ||
765 | GNUNET_JSON_post_parser (32 * 1024, | ||
766 | connection, | ||
767 | &(rd->ptr), | ||
768 | upload_data, | ||
769 | upload_data_size, | ||
770 | &json); | ||
771 | |||
772 | switch (result) | ||
773 | { | ||
774 | case GNUNET_JSON_PR_CONTINUE: | ||
775 | /* Keep processing POST data */ | ||
776 | return MHD_YES; | ||
777 | case GNUNET_JSON_PR_OUT_OF_MEMORY: | ||
778 | case GNUNET_JSON_PR_REQUEST_TOO_LARGE: | ||
779 | rd->body = make_json ("error", "true", | ||
780 | "message", _ ("unable to process submitted data"), | ||
781 | NULL); | ||
782 | rd->body_length = strlen (rd->body); | ||
783 | rd->code = MHD_HTTP_PAYLOAD_TOO_LARGE; | ||
784 | return MHD_YES; | ||
785 | case GNUNET_JSON_PR_JSON_INVALID: | ||
786 | rd->body = make_json ("error", "true", | ||
787 | "message", _ ("the submitted data is invalid"), | ||
788 | NULL); | ||
789 | rd->body_length = strlen (rd->body); | ||
790 | rd->code = MHD_HTTP_BAD_REQUEST; | ||
791 | return MHD_YES; | ||
792 | default: | ||
793 | break; | ||
794 | } | ||
795 | |||
796 | /* POST data has been read in its entirety */ | ||
797 | |||
798 | const char *name = json_string_value (json_object_get (json, "name")); | ||
799 | const char *key = json_string_value (json_object_get (json, "key")); | ||
800 | if ((NULL == name) || (NULL == key) || (0 == strlen (name)) || (0 == | ||
801 | strlen ( | ||
802 | key))) | ||
803 | { | ||
804 | json_decref (json); | ||
805 | rd->body = make_json ("error", "true", | ||
806 | "message", _ ("invalid parameters"), | ||
807 | NULL); | ||
808 | rd->body_length = strlen (rd->body); | ||
809 | rd->code = MHD_HTTP_BAD_REQUEST; | ||
810 | return MHD_YES; | ||
811 | } | ||
812 | |||
813 | rd->register_name = strdup (name); | ||
814 | rd->register_key = strdup (key); | ||
815 | |||
816 | json_decref (json); | ||
817 | GNUNET_JSON_post_parser_cleanup (rd->ptr); | ||
818 | |||
819 | if ((NULL != strchr (rd->register_name, '.')) || | ||
820 | (NULL != strchr (rd->register_name, '+'))) | ||
821 | { | ||
822 | rd->body = make_json ("error", "true", | ||
823 | "message", _ ("invalid name"), | ||
824 | NULL); | ||
825 | rd->body_length = strlen (rd->body); | ||
826 | rd->code = MHD_HTTP_BAD_REQUEST; | ||
827 | return MHD_YES; | ||
828 | } | ||
829 | |||
830 | if (GNUNET_OK != GNUNET_IDENTITY_public_key_from_string (rd->register_key, | ||
831 | &(rd->key))) | ||
832 | { | ||
833 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, | ||
834 | _ ("Unable to parse key %s\n"), | ||
835 | rd->register_key); | ||
836 | |||
837 | rd->body = make_json ("error", "true", | ||
838 | "message", _ ("unable to parse key"), | ||
839 | NULL); | ||
840 | rd->body_length = strlen (rd->body); | ||
841 | rd->code = MHD_HTTP_INTERNAL_SERVER_ERROR; | ||
842 | return MHD_YES; | ||
843 | } | ||
844 | |||
845 | MHD_suspend_connection (connection); | ||
846 | /* See if the requested name is free */ | ||
847 | rd->iterating = | ||
848 | GNUNET_NAMESTORE_zone_iteration_start (namestore, | ||
849 | zone_key, | ||
850 | &iterate_error_cb, | ||
851 | rd, | ||
852 | &iterate_do_cb, | ||
853 | rd, | ||
854 | &iterate_done_cb, | ||
855 | rd); | ||
856 | return MHD_YES; | ||
857 | } | ||
858 | |||
859 | return MHD_queue_response (connection, | ||
860 | MHD_HTTP_FORBIDDEN, | ||
861 | forbidden_page->response); | ||
862 | } | ||
863 | |||
864 | return MHD_queue_response (connection, | ||
865 | MHD_HTTP_NOT_IMPLEMENTED, | ||
866 | forbidden_page->response); | ||
867 | } | ||
868 | |||
869 | |||
870 | /** | ||
871 | * Called when a request is completed. | ||
872 | * | ||
873 | * @param cls unused | ||
874 | * @param connection the connection | ||
875 | * @param ptr connection-specific data | ||
876 | * @param status status code | ||
877 | */ | ||
878 | static void | ||
879 | completed_cb (void *cls, | ||
880 | struct MHD_Connection *connection, | ||
881 | void **ptr, | ||
882 | enum MHD_RequestTerminationCode status) | ||
883 | { | ||
884 | (void) cls; | ||
885 | (void) connection; | ||
886 | (void) status; | ||
887 | |||
888 | struct RequestData *rd = *ptr; | ||
889 | |||
890 | if (NULL == rd) | ||
891 | { | ||
892 | return; | ||
893 | } | ||
894 | |||
895 | if (NULL == rd->body) | ||
896 | { | ||
897 | GNUNET_free (rd->body); | ||
898 | } | ||
899 | |||
900 | if (NULL != rd->searching) | ||
901 | { | ||
902 | GNUNET_NAMESTORE_cancel (rd->searching); | ||
903 | } | ||
904 | |||
905 | if (NULL != rd->register_name) | ||
906 | { | ||
907 | GNUNET_free (rd->register_name); | ||
908 | } | ||
909 | |||
910 | if (NULL != rd->register_key) | ||
911 | { | ||
912 | GNUNET_free (rd->register_key); | ||
913 | } | ||
914 | |||
915 | if (NULL != rd->iterating) | ||
916 | { | ||
917 | GNUNET_NAMESTORE_zone_iteration_stop (rd->iterating); | ||
918 | } | ||
919 | |||
920 | GNUNET_free (rd); | ||
921 | } | ||
922 | |||
923 | |||
924 | /** | ||
925 | * Called for each ego provided by the identity service. | ||
926 | * | ||
927 | * @param cls closure | ||
928 | * @param ego the ego | ||
929 | * @param ctx application-provided data for the ego | ||
930 | * @param name the ego name | ||
931 | */ | ||
932 | static void | ||
933 | identity_cb (void *cls, | ||
934 | struct GNUNET_IDENTITY_Ego *ego, | ||
935 | void **ctx, | ||
936 | const char *name) | ||
937 | { | ||
938 | (void) cls; | ||
939 | (void) ctx; | ||
940 | |||
941 | if ((NULL == name) || (0 != strcmp (name, zone))) | ||
942 | { | ||
943 | return; | ||
944 | } | ||
945 | |||
946 | if (NULL == ego) | ||
947 | { | ||
948 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
949 | _ ("No ego configured for `fcfsd` subsystem\n")); | ||
950 | GNUNET_SCHEDULER_shutdown (); | ||
951 | return; | ||
952 | } | ||
953 | |||
954 | zone_key = GNUNET_IDENTITY_ego_get_private_key (ego); | ||
955 | |||
956 | int flags = MHD_USE_DUAL_STACK | MHD_USE_DEBUG | MHD_ALLOW_SUSPEND_RESUME; | ||
957 | do | ||
958 | { | ||
959 | httpd = MHD_start_daemon (flags, | ||
960 | (uint16_t) port, | ||
961 | NULL, NULL, | ||
962 | &create_response, NULL, | ||
963 | MHD_OPTION_CONNECTION_LIMIT, 128, | ||
964 | MHD_OPTION_PER_IP_CONNECTION_LIMIT, 1, | ||
965 | MHD_OPTION_CONNECTION_TIMEOUT, 4 * 1024, | ||
966 | MHD_OPTION_NOTIFY_COMPLETED, &completed_cb, NULL, | ||
967 | MHD_OPTION_END); | ||
968 | flags = MHD_USE_DEBUG; | ||
969 | } while (NULL == httpd && flags != MHD_USE_DEBUG); | ||
970 | |||
971 | if (NULL == httpd) | ||
972 | { | ||
973 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
974 | _ ("Failed to start HTTP server\n")); | ||
975 | GNUNET_SCHEDULER_shutdown (); | ||
976 | return; | ||
977 | } | ||
978 | |||
979 | run_httpd (); | ||
980 | } | ||
981 | |||
982 | |||
983 | /** | ||
984 | * Open a file on disk and generate a response object for it. | ||
985 | * | ||
986 | * @param name name of the file to open | ||
987 | * @param basedir directory where the file is located | ||
988 | * @return #GNUNET_SYSERR on error | ||
989 | */ | ||
990 | static struct StaticPage * | ||
991 | open_static_page (const char *name, const char *basedir) | ||
992 | { | ||
993 | char *fullname = NULL; | ||
994 | GNUNET_asprintf (&fullname, "%s/fcfsd-%s", basedir, name); | ||
995 | |||
996 | struct GNUNET_DISK_FileHandle *f = | ||
997 | GNUNET_DISK_file_open (fullname, | ||
998 | GNUNET_DISK_OPEN_READ, | ||
999 | GNUNET_DISK_PERM_NONE); | ||
1000 | GNUNET_free (fullname); | ||
1001 | |||
1002 | if (NULL == f) | ||
1003 | { | ||
1004 | return NULL; | ||
1005 | } | ||
1006 | |||
1007 | off_t size = 0; | ||
1008 | if (GNUNET_SYSERR == GNUNET_DISK_file_handle_size (f, &size)) | ||
1009 | { | ||
1010 | GNUNET_DISK_file_close (f); | ||
1011 | return NULL; | ||
1012 | } | ||
1013 | |||
1014 | struct MHD_Response *response = | ||
1015 | MHD_create_response_from_fd64 (size, | ||
1016 | f->fd); | ||
1017 | |||
1018 | if (NULL == response) | ||
1019 | { | ||
1020 | GNUNET_DISK_file_close (f); | ||
1021 | return NULL; | ||
1022 | } | ||
1023 | |||
1024 | struct StaticPage *page = GNUNET_new (struct StaticPage); | ||
1025 | page->handle = f; | ||
1026 | page->size = (uint64_t) size; | ||
1027 | page->response = response; | ||
1028 | return page; | ||
1029 | } | ||
1030 | |||
1031 | |||
1032 | /** | ||
1033 | * Called after the service is up. | ||
1034 | * | ||
1035 | * @param cls closure | ||
1036 | * @param args remaining command line arguments | ||
1037 | * @param cfgfile name of the configuration file | ||
1038 | * @param cfg the service configuration | ||
1039 | */ | ||
1040 | static void | ||
1041 | run_service (void *cls, | ||
1042 | char *const *args, | ||
1043 | const char *cfgfile, | ||
1044 | const struct GNUNET_CONFIGURATION_Handle *cfg) | ||
1045 | { | ||
1046 | (void) cls; | ||
1047 | (void) args; | ||
1048 | (void) cfgfile; | ||
1049 | |||
1050 | GNUNET_log_setup ("fcfsd", "WARNING", NULL); | ||
1051 | |||
1052 | if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_number (cfg, | ||
1053 | "fcfsd", | ||
1054 | "HTTPPORT", | ||
1055 | &port)) | ||
1056 | { | ||
1057 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, | ||
1058 | _ ("No port specified, using default value\n")); | ||
1059 | } | ||
1060 | |||
1061 | GNUNET_SCHEDULER_add_shutdown (&do_shutdown, NULL); | ||
1062 | |||
1063 | namestore = GNUNET_NAMESTORE_connect (cfg); | ||
1064 | if (NULL == namestore) | ||
1065 | { | ||
1066 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
1067 | _ ("Failed to connect to namestore\n")); | ||
1068 | GNUNET_SCHEDULER_shutdown (); | ||
1069 | return; | ||
1070 | } | ||
1071 | |||
1072 | identity = GNUNET_IDENTITY_connect (cfg, &identity_cb, NULL); | ||
1073 | if (NULL == identity) | ||
1074 | { | ||
1075 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
1076 | _ ("Failed to connect to identity\n")); | ||
1077 | GNUNET_SCHEDULER_shutdown (); | ||
1078 | return; | ||
1079 | } | ||
1080 | |||
1081 | char *basedir = NULL; | ||
1082 | if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_filename (cfg, | ||
1083 | "fcfsd", | ||
1084 | "HTMLDIR", | ||
1085 | &basedir)) | ||
1086 | { | ||
1087 | basedir = GNUNET_OS_installation_get_path (GNUNET_OS_IPK_DATADIR); | ||
1088 | } | ||
1089 | |||
1090 | main_page = open_static_page ("index.html", basedir); | ||
1091 | notfound_page = open_static_page ("notfound.html", basedir); | ||
1092 | forbidden_page = open_static_page ("forbidden.html", basedir); | ||
1093 | |||
1094 | GNUNET_free (basedir); | ||
1095 | |||
1096 | if ((NULL == main_page) || (NULL == notfound_page) || (NULL == | ||
1097 | forbidden_page) ) | ||
1098 | { | ||
1099 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
1100 | _ ("Unable to set up the daemon\n")); | ||
1101 | GNUNET_SCHEDULER_shutdown (); | ||
1102 | return; | ||
1103 | } | ||
1104 | } | ||
1105 | |||
1106 | |||
1107 | /** | ||
1108 | * The main function of the fcfs daemon. | ||
1109 | * | ||
1110 | * @param argc number of arguments from the command line | ||
1111 | * @parsm argv the command line arguments | ||
1112 | * @return 0 successful exit, a different value otherwise | ||
1113 | */ | ||
1114 | int | ||
1115 | main (int argc, char *const *argv) | ||
1116 | { | ||
1117 | struct GNUNET_GETOPT_CommandLineOption options[] = { | ||
1118 | GNUNET_GETOPT_option_mandatory | ||
1119 | (GNUNET_GETOPT_option_string ('z', | ||
1120 | "zone", | ||
1121 | "EGO", | ||
1122 | gettext_noop ( | ||
1123 | "name of the zone managed by FCFSD"), | ||
1124 | &zone)), | ||
1125 | GNUNET_GETOPT_OPTION_END | ||
1126 | }; | ||
1127 | |||
1128 | return ((GNUNET_OK == GNUNET_PROGRAM_run (argc, | ||
1129 | argv, | ||
1130 | "gnunet-namestore-fcfsd", | ||
1131 | _ ( | ||
1132 | "GNU Name System First-Come-First-Served name registration service"), | ||
1133 | options, | ||
1134 | &run_service, | ||
1135 | NULL)) ? | ||
1136 | 0 : | ||
1137 | 1); | ||
1138 | } | ||
diff --git a/src/namestore/gnunet-namestore.c b/src/namestore/gnunet-namestore.c deleted file mode 100644 index 92d2cf627..000000000 --- a/src/namestore/gnunet-namestore.c +++ /dev/null | |||
@@ -1,1717 +0,0 @@ | |||
1 | /* | ||
2 | This file is part of GNUnet. | ||
3 | Copyright (C) 2012, 2013, 2014, 2019 GNUnet e.V. | ||
4 | |||
5 | GNUnet is free software: you can redistribute it and/or modify it | ||
6 | under the terms of the GNU Affero General Public License as published | ||
7 | by the Free Software Foundation, either version 3 of the License, | ||
8 | or (at your option) any later version. | ||
9 | |||
10 | GNUnet is distributed in the hope that it will be useful, but | ||
11 | WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
13 | Affero General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU Affero General Public License | ||
16 | along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
17 | |||
18 | SPDX-License-Identifier: AGPL3.0-or-later | ||
19 | */ | ||
20 | /** | ||
21 | * @file gnunet-namestore.c | ||
22 | * @brief command line tool to manipulate the local zone | ||
23 | * @author Christian Grothoff | ||
24 | * | ||
25 | * TODO: | ||
26 | * - test | ||
27 | */ | ||
28 | #include "platform.h" | ||
29 | #include <gnunet_util_lib.h> | ||
30 | #include <gnunet_dnsparser_lib.h> | ||
31 | #include <gnunet_identity_service.h> | ||
32 | #include <gnunet_gnsrecord_lib.h> | ||
33 | #include <gnunet_gns_service.h> | ||
34 | #include <gnunet_namestore_service.h> | ||
35 | |||
36 | |||
37 | /** | ||
38 | * Entry in record set for bulk processing. | ||
39 | */ | ||
40 | struct RecordSetEntry | ||
41 | { | ||
42 | /** | ||
43 | * Kept in a linked list. | ||
44 | */ | ||
45 | struct RecordSetEntry *next; | ||
46 | |||
47 | /** | ||
48 | * The record to add/remove. | ||
49 | */ | ||
50 | struct GNUNET_GNSRECORD_Data record; | ||
51 | }; | ||
52 | |||
53 | |||
54 | /** | ||
55 | * Handle to the namestore. | ||
56 | */ | ||
57 | static struct GNUNET_NAMESTORE_Handle *ns; | ||
58 | |||
59 | /** | ||
60 | * Private key for the our zone. | ||
61 | */ | ||
62 | static struct GNUNET_IDENTITY_PrivateKey zone_pkey; | ||
63 | |||
64 | /** | ||
65 | * Handle to identity lookup. | ||
66 | */ | ||
67 | static struct GNUNET_IDENTITY_EgoLookup *el; | ||
68 | |||
69 | /** | ||
70 | * Identity service handle | ||
71 | */ | ||
72 | static struct GNUNET_IDENTITY_Handle *idh; | ||
73 | |||
74 | /** | ||
75 | * Obtain default ego | ||
76 | */ | ||
77 | struct GNUNET_IDENTITY_Operation *get_default; | ||
78 | |||
79 | /** | ||
80 | * Name of the ego controlling the zone. | ||
81 | */ | ||
82 | static char *ego_name; | ||
83 | |||
84 | /** | ||
85 | * Desired action is to add a record. | ||
86 | */ | ||
87 | static int add; | ||
88 | |||
89 | /** | ||
90 | * Queue entry for the 'add-uri' operation. | ||
91 | */ | ||
92 | static struct GNUNET_NAMESTORE_QueueEntry *add_qe_uri; | ||
93 | |||
94 | /** | ||
95 | * Queue entry for the 'add' operation. | ||
96 | */ | ||
97 | static struct GNUNET_NAMESTORE_QueueEntry *add_qe; | ||
98 | |||
99 | /** | ||
100 | * Queue entry for the 'lookup' operation. | ||
101 | */ | ||
102 | static struct GNUNET_NAMESTORE_QueueEntry *get_qe; | ||
103 | |||
104 | /** | ||
105 | * Queue entry for the 'reverse lookup' operation (in combination with a name). | ||
106 | */ | ||
107 | static struct GNUNET_NAMESTORE_QueueEntry *reverse_qe; | ||
108 | |||
109 | /** | ||
110 | * Desired action is to list records. | ||
111 | */ | ||
112 | static int list; | ||
113 | |||
114 | /** | ||
115 | * List iterator for the 'list' operation. | ||
116 | */ | ||
117 | static struct GNUNET_NAMESTORE_ZoneIterator *list_it; | ||
118 | |||
119 | /** | ||
120 | * Desired action is to remove a record. | ||
121 | */ | ||
122 | static int del; | ||
123 | |||
124 | /** | ||
125 | * Is record public (opposite of #GNUNET_GNSRECORD_RF_PRIVATE) | ||
126 | */ | ||
127 | static int is_public; | ||
128 | |||
129 | /** | ||
130 | * Is record a shadow record (#GNUNET_GNSRECORD_RF_SHADOW_RECORD) | ||
131 | */ | ||
132 | static int is_shadow; | ||
133 | |||
134 | /** | ||
135 | * Queue entry for the 'del' operation. | ||
136 | */ | ||
137 | static struct GNUNET_NAMESTORE_QueueEntry *del_qe; | ||
138 | |||
139 | /** | ||
140 | * Queue entry for the 'set/replace' operation. | ||
141 | */ | ||
142 | static struct GNUNET_NAMESTORE_QueueEntry *set_qe; | ||
143 | |||
144 | /** | ||
145 | * Name of the records to add/list/remove. | ||
146 | */ | ||
147 | static char *name; | ||
148 | |||
149 | /** | ||
150 | * Value of the record to add/remove. | ||
151 | */ | ||
152 | static char *value; | ||
153 | |||
154 | /** | ||
155 | * URI to import. | ||
156 | */ | ||
157 | static char *uri; | ||
158 | |||
159 | /** | ||
160 | * Reverse lookup to perform. | ||
161 | */ | ||
162 | static char *reverse_pkey; | ||
163 | |||
164 | /** | ||
165 | * Type of the record to add/remove, NULL to remove all. | ||
166 | */ | ||
167 | static char *typestring; | ||
168 | |||
169 | /** | ||
170 | * Desired expiration time. | ||
171 | */ | ||
172 | static char *expirationstring; | ||
173 | |||
174 | /** | ||
175 | * Desired nick name. | ||
176 | */ | ||
177 | static char *nickstring; | ||
178 | |||
179 | /** | ||
180 | * Global return value | ||
181 | */ | ||
182 | static int ret; | ||
183 | |||
184 | /** | ||
185 | * Type string converted to DNS type value. | ||
186 | */ | ||
187 | static uint32_t type; | ||
188 | |||
189 | /** | ||
190 | * Value in binary format. | ||
191 | */ | ||
192 | static void *data; | ||
193 | |||
194 | /** | ||
195 | * Number of bytes in #data. | ||
196 | */ | ||
197 | static size_t data_size; | ||
198 | |||
199 | /** | ||
200 | * Expiration string converted to numeric value. | ||
201 | */ | ||
202 | static uint64_t etime; | ||
203 | |||
204 | /** | ||
205 | * Is expiration time relative or absolute time? | ||
206 | */ | ||
207 | static int etime_is_rel = GNUNET_SYSERR; | ||
208 | |||
209 | /** | ||
210 | * Monitor handle. | ||
211 | */ | ||
212 | static struct GNUNET_NAMESTORE_ZoneMonitor *zm; | ||
213 | |||
214 | /** | ||
215 | * Enables monitor mode. | ||
216 | */ | ||
217 | static int monitor; | ||
218 | |||
219 | /** | ||
220 | * Entry in record set for processing records in bulk. | ||
221 | */ | ||
222 | static struct RecordSetEntry *recordset; | ||
223 | |||
224 | |||
225 | /** | ||
226 | * Task run on shutdown. Cleans up everything. | ||
227 | * | ||
228 | * @param cls unused | ||
229 | */ | ||
230 | static void | ||
231 | do_shutdown (void *cls) | ||
232 | { | ||
233 | (void) cls; | ||
234 | if (NULL != get_default) | ||
235 | { | ||
236 | GNUNET_IDENTITY_cancel (get_default); | ||
237 | get_default = NULL; | ||
238 | } | ||
239 | if (NULL != idh) | ||
240 | { | ||
241 | GNUNET_IDENTITY_disconnect (idh); | ||
242 | idh = NULL; | ||
243 | } | ||
244 | if (NULL != el) | ||
245 | { | ||
246 | GNUNET_IDENTITY_ego_lookup_cancel (el); | ||
247 | el = NULL; | ||
248 | } | ||
249 | if (NULL != list_it) | ||
250 | { | ||
251 | GNUNET_NAMESTORE_zone_iteration_stop (list_it); | ||
252 | list_it = NULL; | ||
253 | } | ||
254 | if (NULL != add_qe) | ||
255 | { | ||
256 | GNUNET_NAMESTORE_cancel (add_qe); | ||
257 | add_qe = NULL; | ||
258 | } | ||
259 | if (NULL != set_qe) | ||
260 | { | ||
261 | GNUNET_NAMESTORE_cancel (set_qe); | ||
262 | set_qe = NULL; | ||
263 | } | ||
264 | if (NULL != add_qe_uri) | ||
265 | { | ||
266 | GNUNET_NAMESTORE_cancel (add_qe_uri); | ||
267 | add_qe_uri = NULL; | ||
268 | } | ||
269 | if (NULL != get_qe) | ||
270 | { | ||
271 | GNUNET_NAMESTORE_cancel (get_qe); | ||
272 | get_qe = NULL; | ||
273 | } | ||
274 | if (NULL != del_qe) | ||
275 | { | ||
276 | GNUNET_NAMESTORE_cancel (del_qe); | ||
277 | del_qe = NULL; | ||
278 | } | ||
279 | if (NULL != ns) | ||
280 | { | ||
281 | GNUNET_NAMESTORE_disconnect (ns); | ||
282 | ns = NULL; | ||
283 | } | ||
284 | memset (&zone_pkey, 0, sizeof(zone_pkey)); | ||
285 | if (NULL != uri) | ||
286 | { | ||
287 | GNUNET_free (uri); | ||
288 | uri = NULL; | ||
289 | } | ||
290 | if (NULL != zm) | ||
291 | { | ||
292 | GNUNET_NAMESTORE_zone_monitor_stop (zm); | ||
293 | zm = NULL; | ||
294 | } | ||
295 | if (NULL != data) | ||
296 | { | ||
297 | GNUNET_free (data); | ||
298 | data = NULL; | ||
299 | } | ||
300 | } | ||
301 | |||
302 | |||
303 | /** | ||
304 | * Check if we are finished, and if so, perform shutdown. | ||
305 | */ | ||
306 | static void | ||
307 | test_finished () | ||
308 | { | ||
309 | if ((NULL == add_qe) && (NULL == add_qe_uri) && (NULL == get_qe) && | ||
310 | (NULL == del_qe) && (NULL == reverse_qe) && (NULL == list_it)) | ||
311 | GNUNET_SCHEDULER_shutdown (); | ||
312 | } | ||
313 | |||
314 | |||
315 | /** | ||
316 | * Continuation called to notify client about result of the | ||
317 | * operation. | ||
318 | * | ||
319 | * @param cls closure, location of the QueueEntry pointer to NULL out | ||
320 | * @param success #GNUNET_SYSERR on failure (including timeout/queue drop/failure to validate) | ||
321 | * #GNUNET_NO if content was already there | ||
322 | * #GNUNET_YES (or other positive value) on success | ||
323 | * @param emsg NULL on success, otherwise an error message | ||
324 | */ | ||
325 | static void | ||
326 | add_continuation (void *cls, int32_t success, const char *emsg) | ||
327 | { | ||
328 | struct GNUNET_NAMESTORE_QueueEntry **qe = cls; | ||
329 | |||
330 | *qe = NULL; | ||
331 | if (GNUNET_YES != success) | ||
332 | { | ||
333 | fprintf (stderr, | ||
334 | _ ("Adding record failed: %s\n"), | ||
335 | (GNUNET_NO == success) ? "record exists" : emsg); | ||
336 | if (GNUNET_NO != success) | ||
337 | ret = 1; | ||
338 | } | ||
339 | ret = 0; | ||
340 | test_finished (); | ||
341 | } | ||
342 | |||
343 | |||
344 | /** | ||
345 | * Continuation called to notify client about result of the | ||
346 | * operation. | ||
347 | * | ||
348 | * @param cls closure, unused | ||
349 | * @param success #GNUNET_SYSERR on failure (including timeout/queue drop/failure to validate) | ||
350 | * #GNUNET_NO if content was already there | ||
351 | * #GNUNET_YES (or other positive value) on success | ||
352 | * @param emsg NULL on success, otherwise an error message | ||
353 | */ | ||
354 | static void | ||
355 | del_continuation (void *cls, int32_t success, const char *emsg) | ||
356 | { | ||
357 | (void) cls; | ||
358 | del_qe = NULL; | ||
359 | if (GNUNET_NO == success) | ||
360 | { | ||
361 | fprintf (stderr, | ||
362 | _ ("Deleting record failed, record does not exist%s%s\n"), | ||
363 | (NULL != emsg) ? ": " : "", | ||
364 | (NULL != emsg) ? emsg : ""); | ||
365 | } | ||
366 | if (GNUNET_SYSERR == success) | ||
367 | { | ||
368 | fprintf (stderr, | ||
369 | _ ("Deleting record failed%s%s\n"), | ||
370 | (NULL != emsg) ? ": " : "", | ||
371 | (NULL != emsg) ? emsg : ""); | ||
372 | } | ||
373 | test_finished (); | ||
374 | } | ||
375 | |||
376 | |||
377 | /** | ||
378 | * Function called when we are done with a zone iteration. | ||
379 | */ | ||
380 | static void | ||
381 | zone_iteration_finished (void *cls) | ||
382 | { | ||
383 | (void) cls; | ||
384 | list_it = NULL; | ||
385 | test_finished (); | ||
386 | } | ||
387 | |||
388 | |||
389 | /** | ||
390 | * Function called when we encountered an error in a zone iteration. | ||
391 | */ | ||
392 | static void | ||
393 | zone_iteration_error_cb (void *cls) | ||
394 | { | ||
395 | (void) cls; | ||
396 | list_it = NULL; | ||
397 | fprintf (stderr, "Error iterating over zone\n"); | ||
398 | ret = 1; | ||
399 | test_finished (); | ||
400 | } | ||
401 | |||
402 | |||
403 | /** | ||
404 | * Process a record that was stored in the namestore. | ||
405 | * | ||
406 | * @param rname name that is being mapped (at most 255 characters long) | ||
407 | * @param rd_len number of entries in @a rd array | ||
408 | * @param rd array of records with data to store | ||
409 | */ | ||
410 | static void | ||
411 | display_record (const char *rname, | ||
412 | unsigned int rd_len, | ||
413 | const struct GNUNET_GNSRECORD_Data *rd) | ||
414 | { | ||
415 | const char *typestr; | ||
416 | char *s; | ||
417 | const char *ets; | ||
418 | struct GNUNET_TIME_Absolute at; | ||
419 | struct GNUNET_TIME_Relative rt; | ||
420 | int have_record; | ||
421 | |||
422 | if ((NULL != name) && (0 != strcmp (name, rname))) | ||
423 | { | ||
424 | GNUNET_NAMESTORE_zone_iterator_next (list_it, 1); | ||
425 | return; | ||
426 | } | ||
427 | have_record = GNUNET_NO; | ||
428 | for (unsigned int i = 0; i < rd_len; i++) | ||
429 | { | ||
430 | if ((GNUNET_GNSRECORD_TYPE_NICK == rd[i].record_type) && | ||
431 | (0 != strcmp (rname, GNUNET_GNS_EMPTY_LABEL_AT))) | ||
432 | continue; | ||
433 | if ((type != rd[i].record_type) && (GNUNET_GNSRECORD_TYPE_ANY != type)) | ||
434 | continue; | ||
435 | have_record = GNUNET_YES; | ||
436 | break; | ||
437 | } | ||
438 | if (GNUNET_NO == have_record) | ||
439 | return; | ||
440 | fprintf (stdout, "%s:\n", rname); | ||
441 | if (NULL != typestring) | ||
442 | type = GNUNET_GNSRECORD_typename_to_number (typestring); | ||
443 | else | ||
444 | type = GNUNET_GNSRECORD_TYPE_ANY; | ||
445 | for (unsigned int i = 0; i < rd_len; i++) | ||
446 | { | ||
447 | if ((GNUNET_GNSRECORD_TYPE_NICK == rd[i].record_type) && | ||
448 | (0 != strcmp (rname, GNUNET_GNS_EMPTY_LABEL_AT))) | ||
449 | continue; | ||
450 | if ((type != rd[i].record_type) && (GNUNET_GNSRECORD_TYPE_ANY != type)) | ||
451 | continue; | ||
452 | typestr = GNUNET_GNSRECORD_number_to_typename (rd[i].record_type); | ||
453 | s = GNUNET_GNSRECORD_value_to_string (rd[i].record_type, | ||
454 | rd[i].data, | ||
455 | rd[i].data_size); | ||
456 | if (NULL == s) | ||
457 | { | ||
458 | fprintf (stdout, | ||
459 | _ ("\tCorrupt or unsupported record of type %u\n"), | ||
460 | (unsigned int) rd[i].record_type); | ||
461 | continue; | ||
462 | } | ||
463 | if (0 != (rd[i].flags & GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION)) | ||
464 | { | ||
465 | rt.rel_value_us = rd[i].expiration_time; | ||
466 | ets = GNUNET_STRINGS_relative_time_to_string (rt, GNUNET_YES); | ||
467 | } | ||
468 | else | ||
469 | { | ||
470 | at.abs_value_us = rd[i].expiration_time; | ||
471 | ets = GNUNET_STRINGS_absolute_time_to_string (at); | ||
472 | } | ||
473 | fprintf (stdout, | ||
474 | "\t%s: %s (%s)\t%s\t%s\n", | ||
475 | typestr, | ||
476 | s, | ||
477 | ets, | ||
478 | (0 != (rd[i].flags & GNUNET_GNSRECORD_RF_PRIVATE)) ? "PRIVATE" | ||
479 | : "PUBLIC", | ||
480 | (0 != (rd[i].flags & GNUNET_GNSRECORD_RF_SHADOW_RECORD)) ? "SHADOW" | ||
481 | : ""); | ||
482 | GNUNET_free (s); | ||
483 | } | ||
484 | fprintf (stdout, "%s", "\n"); | ||
485 | } | ||
486 | |||
487 | |||
488 | /** | ||
489 | * Process a record that was stored in the namestore. | ||
490 | * | ||
491 | * @param cls closure | ||
492 | * @param zone_key private key of the zone | ||
493 | * @param rname name that is being mapped (at most 255 characters long) | ||
494 | * @param rd_len number of entries in @a rd array | ||
495 | * @param rd array of records with data to store | ||
496 | */ | ||
497 | static void | ||
498 | display_record_iterator (void *cls, | ||
499 | const struct GNUNET_IDENTITY_PrivateKey *zone_key, | ||
500 | const char *rname, | ||
501 | unsigned int rd_len, | ||
502 | const struct GNUNET_GNSRECORD_Data *rd) | ||
503 | { | ||
504 | (void) cls; | ||
505 | (void) zone_key; | ||
506 | display_record (rname, rd_len, rd); | ||
507 | GNUNET_NAMESTORE_zone_iterator_next (list_it, 1); | ||
508 | } | ||
509 | |||
510 | |||
511 | /** | ||
512 | * Process a record that was stored in the namestore. | ||
513 | * | ||
514 | * @param cls closure | ||
515 | * @param zone_key private key of the zone | ||
516 | * @param rname name that is being mapped (at most 255 characters long) | ||
517 | * @param rd_len number of entries in @a rd array | ||
518 | * @param rd array of records with data to store | ||
519 | */ | ||
520 | static void | ||
521 | display_record_monitor (void *cls, | ||
522 | const struct GNUNET_IDENTITY_PrivateKey *zone_key, | ||
523 | const char *rname, | ||
524 | unsigned int rd_len, | ||
525 | const struct GNUNET_GNSRECORD_Data *rd) | ||
526 | { | ||
527 | (void) cls; | ||
528 | (void) zone_key; | ||
529 | display_record (rname, rd_len, rd); | ||
530 | GNUNET_NAMESTORE_zone_monitor_next (zm, 1); | ||
531 | } | ||
532 | |||
533 | |||
534 | /** | ||
535 | * Process a record that was stored in the namestore. | ||
536 | * | ||
537 | * @param cls closure | ||
538 | * @param zone_key private key of the zone | ||
539 | * @param rname name that is being mapped (at most 255 characters long) | ||
540 | * @param rd_len number of entries in @a rd array | ||
541 | * @param rd array of records with data to store | ||
542 | */ | ||
543 | static void | ||
544 | display_record_lookup (void *cls, | ||
545 | const struct GNUNET_IDENTITY_PrivateKey *zone_key, | ||
546 | const char *rname, | ||
547 | unsigned int rd_len, | ||
548 | const struct GNUNET_GNSRECORD_Data *rd) | ||
549 | { | ||
550 | (void) cls; | ||
551 | (void) zone_key; | ||
552 | get_qe = NULL; | ||
553 | display_record (rname, rd_len, rd); | ||
554 | test_finished (); | ||
555 | } | ||
556 | |||
557 | |||
558 | /** | ||
559 | * Function called once we are in sync in monitor mode. | ||
560 | * | ||
561 | * @param cls NULL | ||
562 | */ | ||
563 | static void | ||
564 | sync_cb (void *cls) | ||
565 | { | ||
566 | (void) cls; | ||
567 | fprintf (stdout, "%s", "Monitor is now in sync.\n"); | ||
568 | } | ||
569 | |||
570 | |||
571 | /** | ||
572 | * Function called on errors while monitoring. | ||
573 | * | ||
574 | * @param cls NULL | ||
575 | */ | ||
576 | static void | ||
577 | monitor_error_cb (void *cls) | ||
578 | { | ||
579 | (void) cls; | ||
580 | fprintf (stderr, "%s", "Monitor disconnected and out of sync.\n"); | ||
581 | } | ||
582 | |||
583 | |||
584 | /** | ||
585 | * Function called on errors while monitoring. | ||
586 | * | ||
587 | * @param cls NULL | ||
588 | */ | ||
589 | static void | ||
590 | lookup_error_cb (void *cls) | ||
591 | { | ||
592 | (void) cls; | ||
593 | get_qe = NULL; | ||
594 | fprintf (stderr, "%s", "Failed to lookup record.\n"); | ||
595 | test_finished (); | ||
596 | } | ||
597 | |||
598 | |||
599 | /** | ||
600 | * Function called if lookup fails. | ||
601 | */ | ||
602 | static void | ||
603 | add_error_cb (void *cls) | ||
604 | { | ||
605 | (void) cls; | ||
606 | add_qe = NULL; | ||
607 | GNUNET_break (0); | ||
608 | ret = 1; | ||
609 | test_finished (); | ||
610 | } | ||
611 | |||
612 | |||
613 | /** | ||
614 | * We're storing a record; this function is given the existing record | ||
615 | * so that we can merge the information. | ||
616 | * | ||
617 | * @param cls closure, unused | ||
618 | * @param zone_key private key of the zone | ||
619 | * @param rec_name name that is being mapped (at most 255 characters long) | ||
620 | * @param rd_count number of entries in @a rd array | ||
621 | * @param rd array of records with data to store | ||
622 | */ | ||
623 | static void | ||
624 | get_existing_record (void *cls, | ||
625 | const struct GNUNET_IDENTITY_PrivateKey *zone_key, | ||
626 | const char *rec_name, | ||
627 | unsigned int rd_count, | ||
628 | const struct GNUNET_GNSRECORD_Data *rd) | ||
629 | { | ||
630 | struct GNUNET_GNSRECORD_Data rdn[rd_count + 1]; | ||
631 | struct GNUNET_GNSRECORD_Data *rde; | ||
632 | |||
633 | (void) cls; | ||
634 | (void) zone_key; | ||
635 | add_qe = NULL; | ||
636 | if (0 != strcmp (rec_name, name)) | ||
637 | { | ||
638 | GNUNET_break (0); | ||
639 | ret = 1; | ||
640 | test_finished (); | ||
641 | return; | ||
642 | } | ||
643 | |||
644 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
645 | "Received %u records for name `%s'\n", | ||
646 | rd_count, | ||
647 | rec_name); | ||
648 | for (unsigned int i = 0; i < rd_count; i++) | ||
649 | { | ||
650 | switch (rd[i].record_type) | ||
651 | { | ||
652 | case GNUNET_DNSPARSER_TYPE_CNAME: | ||
653 | fprintf ( | ||
654 | stderr, | ||
655 | _ ( | ||
656 | "A %s record exists already under `%s', no other records can be added.\n"), | ||
657 | "CNAME", | ||
658 | rec_name); | ||
659 | ret = 1; | ||
660 | test_finished (); | ||
661 | return; | ||
662 | |||
663 | case GNUNET_GNSRECORD_TYPE_PKEY: | ||
664 | case GNUNET_GNSRECORD_TYPE_EDKEY: | ||
665 | fprintf ( | ||
666 | stderr, | ||
667 | _ ( | ||
668 | "A zone key record exists already under `%s', no other records can be added.\n"), | ||
669 | rec_name); | ||
670 | ret = 1; | ||
671 | test_finished (); | ||
672 | return; | ||
673 | |||
674 | case GNUNET_DNSPARSER_TYPE_SOA: | ||
675 | if (GNUNET_DNSPARSER_TYPE_SOA == type) | ||
676 | { | ||
677 | fprintf ( | ||
678 | stderr, | ||
679 | _ ( | ||
680 | "A SOA record exists already under `%s', cannot add a second SOA to the same zone.\n"), | ||
681 | rec_name); | ||
682 | ret = 1; | ||
683 | test_finished (); | ||
684 | return; | ||
685 | } | ||
686 | break; | ||
687 | } | ||
688 | } | ||
689 | switch (type) | ||
690 | { | ||
691 | case GNUNET_DNSPARSER_TYPE_CNAME: | ||
692 | if (0 != rd_count) | ||
693 | { | ||
694 | fprintf (stderr, | ||
695 | _ ( | ||
696 | "Records already exist under `%s', cannot add `%s' record.\n"), | ||
697 | rec_name, | ||
698 | "CNAME"); | ||
699 | ret = 1; | ||
700 | test_finished (); | ||
701 | return; | ||
702 | } | ||
703 | break; | ||
704 | |||
705 | case GNUNET_GNSRECORD_TYPE_PKEY: | ||
706 | case GNUNET_GNSRECORD_TYPE_EDKEY: | ||
707 | if (0 != rd_count) | ||
708 | { | ||
709 | fprintf (stderr, | ||
710 | _ ( | ||
711 | "Records already exist under `%s', cannot add record.\n"), | ||
712 | rec_name); | ||
713 | ret = 1; | ||
714 | test_finished (); | ||
715 | return; | ||
716 | } | ||
717 | break; | ||
718 | |||
719 | case GNUNET_GNSRECORD_TYPE_GNS2DNS: | ||
720 | for (unsigned int i = 0; i < rd_count; i++) | ||
721 | if (GNUNET_GNSRECORD_TYPE_GNS2DNS != rd[i].record_type) | ||
722 | { | ||
723 | fprintf ( | ||
724 | stderr, | ||
725 | _ ( | ||
726 | "Non-GNS2DNS records already exist under `%s', cannot add GNS2DNS record.\n"), | ||
727 | rec_name); | ||
728 | ret = 1; | ||
729 | test_finished (); | ||
730 | return; | ||
731 | } | ||
732 | break; | ||
733 | } | ||
734 | memset (rdn, 0, sizeof(struct GNUNET_GNSRECORD_Data)); | ||
735 | GNUNET_memcpy (&rdn[1], rd, rd_count * sizeof(struct GNUNET_GNSRECORD_Data)); | ||
736 | rde = &rdn[0]; | ||
737 | rde->data = data; | ||
738 | rde->data_size = data_size; | ||
739 | rde->record_type = type; | ||
740 | if (1 == is_shadow) | ||
741 | rde->flags |= GNUNET_GNSRECORD_RF_SHADOW_RECORD; | ||
742 | if (1 != is_public) | ||
743 | rde->flags |= GNUNET_GNSRECORD_RF_PRIVATE; | ||
744 | rde->expiration_time = etime; | ||
745 | if (GNUNET_YES == etime_is_rel) | ||
746 | rde->flags |= GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION; | ||
747 | else if (GNUNET_NO != etime_is_rel) | ||
748 | rde->expiration_time = GNUNET_TIME_UNIT_FOREVER_ABS.abs_value_us; | ||
749 | GNUNET_assert (NULL != name); | ||
750 | add_qe = GNUNET_NAMESTORE_records_store (ns, | ||
751 | &zone_pkey, | ||
752 | name, | ||
753 | rd_count + 1, | ||
754 | rde, | ||
755 | &add_continuation, | ||
756 | &add_qe); | ||
757 | } | ||
758 | |||
759 | |||
760 | /** | ||
761 | * Function called if we encountered an error in zone-to-name. | ||
762 | */ | ||
763 | static void | ||
764 | reverse_error_cb (void *cls) | ||
765 | { | ||
766 | (void) cls; | ||
767 | reverse_qe = NULL; | ||
768 | fprintf (stdout, "%s.zkey\n", reverse_pkey); | ||
769 | } | ||
770 | |||
771 | |||
772 | /** | ||
773 | * Function called with the result of our attempt to obtain a name for a given | ||
774 | * public key. | ||
775 | * | ||
776 | * @param cls NULL | ||
777 | * @param zone private key of the zone; NULL on disconnect | ||
778 | * @param label label of the records; NULL on disconnect | ||
779 | * @param rd_count number of entries in @a rd array, 0 if label was deleted | ||
780 | * @param rd array of records with data to store | ||
781 | */ | ||
782 | static void | ||
783 | handle_reverse_lookup (void *cls, | ||
784 | const struct GNUNET_IDENTITY_PrivateKey *zone, | ||
785 | const char *label, | ||
786 | unsigned int rd_count, | ||
787 | const struct GNUNET_GNSRECORD_Data *rd) | ||
788 | { | ||
789 | (void) cls; | ||
790 | (void) zone; | ||
791 | (void) rd_count; | ||
792 | (void) rd; | ||
793 | reverse_qe = NULL; | ||
794 | if (NULL == label) | ||
795 | fprintf (stdout, "%s\n", reverse_pkey); | ||
796 | else | ||
797 | fprintf (stdout, "%s.%s\n", label, ego_name); | ||
798 | test_finished (); | ||
799 | } | ||
800 | |||
801 | |||
802 | /** | ||
803 | * Function called if lookup for deletion fails. | ||
804 | */ | ||
805 | static void | ||
806 | del_lookup_error_cb (void *cls) | ||
807 | { | ||
808 | (void) cls; | ||
809 | del_qe = NULL; | ||
810 | GNUNET_break (0); | ||
811 | ret = 1; | ||
812 | test_finished (); | ||
813 | } | ||
814 | |||
815 | |||
816 | /** | ||
817 | * We were asked to delete something; this function is called with | ||
818 | * the existing records. Now we should determine what should be | ||
819 | * deleted and then issue the deletion operation. | ||
820 | * | ||
821 | * @param cls NULL | ||
822 | * @param zone private key of the zone we are deleting from | ||
823 | * @param label name of the records we are editing | ||
824 | * @param rd_count size of the @a rd array | ||
825 | * @param rd existing records | ||
826 | */ | ||
827 | static void | ||
828 | del_monitor (void *cls, | ||
829 | const struct GNUNET_IDENTITY_PrivateKey *zone, | ||
830 | const char *label, | ||
831 | unsigned int rd_count, | ||
832 | const struct GNUNET_GNSRECORD_Data *rd) | ||
833 | { | ||
834 | struct GNUNET_GNSRECORD_Data rdx[rd_count]; | ||
835 | unsigned int rd_left; | ||
836 | uint32_t type; | ||
837 | char *vs; | ||
838 | |||
839 | (void) cls; | ||
840 | (void) zone; | ||
841 | del_qe = NULL; | ||
842 | if (0 == rd_count) | ||
843 | { | ||
844 | fprintf (stderr, | ||
845 | _ ( | ||
846 | "There are no records under label `%s' that could be deleted.\n"), | ||
847 | label); | ||
848 | ret = 1; | ||
849 | test_finished (); | ||
850 | return; | ||
851 | } | ||
852 | if ((NULL == value) && (NULL == typestring)) | ||
853 | { | ||
854 | /* delete everything */ | ||
855 | del_qe = GNUNET_NAMESTORE_records_store (ns, | ||
856 | &zone_pkey, | ||
857 | name, | ||
858 | 0, | ||
859 | NULL, | ||
860 | &del_continuation, | ||
861 | NULL); | ||
862 | return; | ||
863 | } | ||
864 | rd_left = 0; | ||
865 | if (NULL != typestring) | ||
866 | type = GNUNET_GNSRECORD_typename_to_number (typestring); | ||
867 | else | ||
868 | type = GNUNET_GNSRECORD_TYPE_ANY; | ||
869 | for (unsigned int i = 0; i < rd_count; i++) | ||
870 | { | ||
871 | vs = NULL; | ||
872 | if (! (((GNUNET_GNSRECORD_TYPE_ANY == type) || | ||
873 | (rd[i].record_type == type)) && | ||
874 | ((NULL == value) || | ||
875 | (NULL == | ||
876 | (vs = (GNUNET_GNSRECORD_value_to_string (rd[i].record_type, | ||
877 | rd[i].data, | ||
878 | rd[i].data_size)))) || | ||
879 | (0 == strcmp (vs, value))))) | ||
880 | rdx[rd_left++] = rd[i]; | ||
881 | GNUNET_free (vs); | ||
882 | } | ||
883 | if (rd_count == rd_left) | ||
884 | { | ||
885 | /* nothing got deleted */ | ||
886 | fprintf ( | ||
887 | stderr, | ||
888 | _ ( | ||
889 | "There are no records under label `%s' that match the request for deletion.\n"), | ||
890 | label); | ||
891 | test_finished (); | ||
892 | return; | ||
893 | } | ||
894 | /* delete everything but what we copied to 'rdx' */ | ||
895 | del_qe = GNUNET_NAMESTORE_records_store (ns, | ||
896 | &zone_pkey, | ||
897 | name, | ||
898 | rd_left, | ||
899 | rdx, | ||
900 | &del_continuation, | ||
901 | NULL); | ||
902 | } | ||
903 | |||
904 | |||
905 | /** | ||
906 | * Parse expiration time. | ||
907 | * | ||
908 | * @param expirationstring text to parse | ||
909 | * @param etime_is_rel[out] set to #GNUNET_YES if time is relative | ||
910 | * @param etime[out] set to expiration time (abs or rel) | ||
911 | * @return #GNUNET_OK on success | ||
912 | */ | ||
913 | static int | ||
914 | parse_expiration (const char *expirationstring, | ||
915 | int *etime_is_rel, | ||
916 | uint64_t *etime) | ||
917 | { | ||
918 | struct GNUNET_TIME_Relative etime_rel; | ||
919 | struct GNUNET_TIME_Absolute etime_abs; | ||
920 | |||
921 | if (0 == strcmp (expirationstring, "never")) | ||
922 | { | ||
923 | *etime = GNUNET_TIME_UNIT_FOREVER_ABS.abs_value_us; | ||
924 | *etime_is_rel = GNUNET_NO; | ||
925 | return GNUNET_OK; | ||
926 | } | ||
927 | if (GNUNET_OK == | ||
928 | GNUNET_STRINGS_fancy_time_to_relative (expirationstring, &etime_rel)) | ||
929 | { | ||
930 | *etime_is_rel = GNUNET_YES; | ||
931 | *etime = etime_rel.rel_value_us; | ||
932 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
933 | "Storing record with relative expiration time of %s\n", | ||
934 | GNUNET_STRINGS_relative_time_to_string (etime_rel, GNUNET_NO)); | ||
935 | return GNUNET_OK; | ||
936 | } | ||
937 | if (GNUNET_OK == | ||
938 | GNUNET_STRINGS_fancy_time_to_absolute (expirationstring, &etime_abs)) | ||
939 | { | ||
940 | *etime_is_rel = GNUNET_NO; | ||
941 | *etime = etime_abs.abs_value_us; | ||
942 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
943 | "Storing record with absolute expiration time of %s\n", | ||
944 | GNUNET_STRINGS_absolute_time_to_string (etime_abs)); | ||
945 | return GNUNET_OK; | ||
946 | } | ||
947 | return GNUNET_SYSERR; | ||
948 | } | ||
949 | |||
950 | |||
951 | /** | ||
952 | * Function called when namestore is done with the replace | ||
953 | * operation. | ||
954 | * | ||
955 | * @param cls NULL | ||
956 | * @param success #GNUNET_SYSERR on failure (including timeout/queue drop/failure to validate) | ||
957 | * #GNUNET_NO if content was already there or not found | ||
958 | * #GNUNET_YES (or other positive value) on success | ||
959 | * @param emsg NULL on success, otherwise an error message | ||
960 | */ | ||
961 | static void | ||
962 | replace_cont (void *cls, int success, const char *emsg) | ||
963 | { | ||
964 | (void) cls; | ||
965 | |||
966 | set_qe = NULL; | ||
967 | if (GNUNET_OK != success) | ||
968 | { | ||
969 | GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE, | ||
970 | _ ("Failed to replace records: %s\n"), | ||
971 | emsg); | ||
972 | ret = 1; /* fail from 'main' */ | ||
973 | } | ||
974 | GNUNET_SCHEDULER_shutdown (); | ||
975 | } | ||
976 | |||
977 | |||
978 | /** | ||
979 | * We have obtained the zone's private key, so now process | ||
980 | * the main commands using it. | ||
981 | * | ||
982 | * @param cfg configuration to use | ||
983 | */ | ||
984 | static void | ||
985 | run_with_zone_pkey (const struct GNUNET_CONFIGURATION_Handle *cfg) | ||
986 | { | ||
987 | struct GNUNET_GNSRECORD_Data rd; | ||
988 | |||
989 | if (! (add | del | list | (NULL != nickstring) | (NULL != uri) | ||
990 | | (NULL != reverse_pkey) | (NULL != recordset))) | ||
991 | { | ||
992 | /* nothing more to be done */ | ||
993 | fprintf (stderr, _ ("No options given\n")); | ||
994 | GNUNET_SCHEDULER_shutdown (); | ||
995 | return; | ||
996 | } | ||
997 | ns = GNUNET_NAMESTORE_connect (cfg); | ||
998 | if (NULL == ns) | ||
999 | { | ||
1000 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
1001 | _ ("Failed to connect to namestore\n")); | ||
1002 | return; | ||
1003 | } | ||
1004 | |||
1005 | if (NULL != recordset) | ||
1006 | { | ||
1007 | /* replace entire record set */ | ||
1008 | unsigned int rd_count; | ||
1009 | struct GNUNET_GNSRECORD_Data *rd; | ||
1010 | |||
1011 | if (NULL == name) | ||
1012 | { | ||
1013 | fprintf (stderr, | ||
1014 | _ ("Missing option `%s' for operation `%s'\n"), | ||
1015 | "-R", | ||
1016 | _ ("replace")); | ||
1017 | GNUNET_SCHEDULER_shutdown (); | ||
1018 | ret = 1; | ||
1019 | return; | ||
1020 | } | ||
1021 | rd_count = 0; | ||
1022 | for (struct RecordSetEntry *e = recordset; NULL != e; e = e->next) | ||
1023 | rd_count++; | ||
1024 | rd = GNUNET_new_array (rd_count, struct GNUNET_GNSRECORD_Data); | ||
1025 | rd_count = 0; | ||
1026 | for (struct RecordSetEntry *e = recordset; NULL != e; e = e->next) | ||
1027 | { | ||
1028 | rd[rd_count] = e->record; | ||
1029 | rd_count++; | ||
1030 | } | ||
1031 | set_qe = GNUNET_NAMESTORE_records_store (ns, | ||
1032 | &zone_pkey, | ||
1033 | name, | ||
1034 | rd_count, | ||
1035 | rd, | ||
1036 | &replace_cont, | ||
1037 | NULL); | ||
1038 | GNUNET_free (rd); | ||
1039 | return; | ||
1040 | } | ||
1041 | if (NULL != nickstring) | ||
1042 | { | ||
1043 | if (0 == strlen (nickstring)) | ||
1044 | { | ||
1045 | fprintf (stderr, _ ("Invalid nick `%s'\n"), nickstring); | ||
1046 | GNUNET_SCHEDULER_shutdown (); | ||
1047 | ret = 1; | ||
1048 | return; | ||
1049 | } | ||
1050 | add = 1; | ||
1051 | typestring = GNUNET_strdup (GNUNET_GNSRECORD_number_to_typename ( | ||
1052 | GNUNET_GNSRECORD_TYPE_NICK)); | ||
1053 | name = GNUNET_strdup (GNUNET_GNS_EMPTY_LABEL_AT); | ||
1054 | value = GNUNET_strdup (nickstring); | ||
1055 | is_public = 0; | ||
1056 | expirationstring = GNUNET_strdup ("never"); | ||
1057 | GNUNET_free (nickstring); | ||
1058 | nickstring = NULL; | ||
1059 | } | ||
1060 | |||
1061 | if (add) | ||
1062 | { | ||
1063 | if (NULL == name) | ||
1064 | { | ||
1065 | fprintf (stderr, | ||
1066 | _ ("Missing option `%s' for operation `%s'\n"), | ||
1067 | "-n", | ||
1068 | _ ("add")); | ||
1069 | GNUNET_SCHEDULER_shutdown (); | ||
1070 | ret = 1; | ||
1071 | return; | ||
1072 | } | ||
1073 | if (NULL == typestring) | ||
1074 | { | ||
1075 | fprintf (stderr, | ||
1076 | _ ("Missing option `%s' for operation `%s'\n"), | ||
1077 | "-t", | ||
1078 | _ ("add")); | ||
1079 | GNUNET_SCHEDULER_shutdown (); | ||
1080 | ret = 1; | ||
1081 | return; | ||
1082 | } | ||
1083 | type = GNUNET_GNSRECORD_typename_to_number (typestring); | ||
1084 | if (UINT32_MAX == type) | ||
1085 | { | ||
1086 | fprintf (stderr, _ ("Unsupported type `%s'\n"), typestring); | ||
1087 | GNUNET_SCHEDULER_shutdown (); | ||
1088 | ret = 1; | ||
1089 | return; | ||
1090 | } | ||
1091 | if ((GNUNET_DNSPARSER_TYPE_SRV == type) || | ||
1092 | (GNUNET_DNSPARSER_TYPE_TLSA == type) || | ||
1093 | (GNUNET_DNSPARSER_TYPE_OPENPGPKEY == type)) | ||
1094 | { | ||
1095 | fprintf (stderr, | ||
1096 | _ ("For DNS record types `SRV', `TLSA' and `OPENPGPKEY'")); | ||
1097 | fprintf (stderr, ", please use a `BOX' record instead\n"); | ||
1098 | GNUNET_SCHEDULER_shutdown (); | ||
1099 | ret = 1; | ||
1100 | return; | ||
1101 | } | ||
1102 | if (NULL == value) | ||
1103 | { | ||
1104 | fprintf (stderr, | ||
1105 | _ ("Missing option `%s' for operation `%s'\n"), | ||
1106 | "-V", | ||
1107 | _ ("add")); | ||
1108 | ret = 1; | ||
1109 | GNUNET_SCHEDULER_shutdown (); | ||
1110 | return; | ||
1111 | } | ||
1112 | if (GNUNET_OK != | ||
1113 | GNUNET_GNSRECORD_string_to_value (type, value, &data, &data_size)) | ||
1114 | { | ||
1115 | fprintf (stderr, | ||
1116 | _ ("Value `%s' invalid for record type `%s'\n"), | ||
1117 | value, | ||
1118 | typestring); | ||
1119 | GNUNET_SCHEDULER_shutdown (); | ||
1120 | ret = 1; | ||
1121 | return; | ||
1122 | } | ||
1123 | if (NULL == expirationstring) | ||
1124 | { | ||
1125 | fprintf (stderr, | ||
1126 | _ ("Missing option `%s' for operation `%s'\n"), | ||
1127 | "-e", | ||
1128 | _ ("add")); | ||
1129 | GNUNET_SCHEDULER_shutdown (); | ||
1130 | ret = 1; | ||
1131 | return; | ||
1132 | } | ||
1133 | if (GNUNET_OK != parse_expiration (expirationstring, &etime_is_rel, &etime)) | ||
1134 | { | ||
1135 | fprintf (stderr, _ ("Invalid time format `%s'\n"), expirationstring); | ||
1136 | GNUNET_SCHEDULER_shutdown (); | ||
1137 | ret = 1; | ||
1138 | return; | ||
1139 | } | ||
1140 | add_qe = GNUNET_NAMESTORE_records_lookup (ns, | ||
1141 | &zone_pkey, | ||
1142 | name, | ||
1143 | &add_error_cb, | ||
1144 | NULL, | ||
1145 | &get_existing_record, | ||
1146 | NULL); | ||
1147 | } | ||
1148 | if (del) | ||
1149 | { | ||
1150 | if (NULL == name) | ||
1151 | { | ||
1152 | fprintf (stderr, | ||
1153 | _ ("Missing option `%s' for operation `%s'\n"), | ||
1154 | "-n", | ||
1155 | _ ("del")); | ||
1156 | GNUNET_SCHEDULER_shutdown (); | ||
1157 | ret = 1; | ||
1158 | return; | ||
1159 | } | ||
1160 | del_qe = GNUNET_NAMESTORE_records_lookup (ns, | ||
1161 | &zone_pkey, | ||
1162 | name, | ||
1163 | &del_lookup_error_cb, | ||
1164 | NULL, | ||
1165 | &del_monitor, | ||
1166 | NULL); | ||
1167 | } | ||
1168 | if (list) | ||
1169 | { | ||
1170 | if (NULL != name) | ||
1171 | get_qe = GNUNET_NAMESTORE_records_lookup (ns, | ||
1172 | &zone_pkey, | ||
1173 | name, | ||
1174 | &lookup_error_cb, | ||
1175 | NULL, | ||
1176 | &display_record_lookup, | ||
1177 | NULL); | ||
1178 | else | ||
1179 | list_it = GNUNET_NAMESTORE_zone_iteration_start (ns, | ||
1180 | &zone_pkey, | ||
1181 | &zone_iteration_error_cb, | ||
1182 | NULL, | ||
1183 | &display_record_iterator, | ||
1184 | NULL, | ||
1185 | &zone_iteration_finished, | ||
1186 | NULL); | ||
1187 | } | ||
1188 | if (NULL != reverse_pkey) | ||
1189 | { | ||
1190 | struct GNUNET_IDENTITY_PublicKey pubkey; | ||
1191 | |||
1192 | if (GNUNET_OK != | ||
1193 | GNUNET_IDENTITY_public_key_from_string (reverse_pkey, | ||
1194 | &pubkey)) | ||
1195 | { | ||
1196 | fprintf (stderr, | ||
1197 | _ ("Invalid public key for reverse lookup `%s'\n"), | ||
1198 | reverse_pkey); | ||
1199 | GNUNET_SCHEDULER_shutdown (); | ||
1200 | } | ||
1201 | reverse_qe = GNUNET_NAMESTORE_zone_to_name (ns, | ||
1202 | &zone_pkey, | ||
1203 | &pubkey, | ||
1204 | &reverse_error_cb, | ||
1205 | NULL, | ||
1206 | &handle_reverse_lookup, | ||
1207 | NULL); | ||
1208 | } | ||
1209 | if (NULL != uri) | ||
1210 | { | ||
1211 | char sh[105]; | ||
1212 | char sname[64]; | ||
1213 | struct GNUNET_IDENTITY_PublicKey pkey; | ||
1214 | |||
1215 | GNUNET_STRINGS_utf8_tolower (uri, uri); | ||
1216 | if ((2 != (sscanf (uri, "gnunet://gns/%52s/%63s", sh, sname))) || | ||
1217 | (GNUNET_OK != | ||
1218 | GNUNET_IDENTITY_public_key_from_string (sh, &pkey))) | ||
1219 | { | ||
1220 | fprintf (stderr, _ ("Invalid URI `%s'\n"), uri); | ||
1221 | GNUNET_SCHEDULER_shutdown (); | ||
1222 | ret = 1; | ||
1223 | return; | ||
1224 | } | ||
1225 | if (NULL == expirationstring) | ||
1226 | { | ||
1227 | fprintf (stderr, | ||
1228 | _ ("Missing option `%s' for operation `%s'\n"), | ||
1229 | "-e", | ||
1230 | _ ("add")); | ||
1231 | GNUNET_SCHEDULER_shutdown (); | ||
1232 | ret = 1; | ||
1233 | return; | ||
1234 | } | ||
1235 | if (GNUNET_OK != parse_expiration (expirationstring, &etime_is_rel, &etime)) | ||
1236 | { | ||
1237 | fprintf (stderr, _ ("Invalid time format `%s'\n"), expirationstring); | ||
1238 | GNUNET_SCHEDULER_shutdown (); | ||
1239 | ret = 1; | ||
1240 | return; | ||
1241 | } | ||
1242 | memset (&rd, 0, sizeof(rd)); | ||
1243 | rd.data = &pkey; | ||
1244 | rd.data_size = GNUNET_IDENTITY_key_get_length (&pkey); | ||
1245 | rd.record_type = ntohl (pkey.type); | ||
1246 | rd.expiration_time = etime; | ||
1247 | if (GNUNET_YES == etime_is_rel) | ||
1248 | rd.flags |= GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION; | ||
1249 | if (1 == is_shadow) | ||
1250 | rd.flags |= GNUNET_GNSRECORD_RF_SHADOW_RECORD; | ||
1251 | add_qe_uri = GNUNET_NAMESTORE_records_store (ns, | ||
1252 | &zone_pkey, | ||
1253 | sname, | ||
1254 | 1, | ||
1255 | &rd, | ||
1256 | &add_continuation, | ||
1257 | &add_qe_uri); | ||
1258 | } | ||
1259 | if (monitor) | ||
1260 | { | ||
1261 | zm = GNUNET_NAMESTORE_zone_monitor_start (cfg, | ||
1262 | &zone_pkey, | ||
1263 | GNUNET_YES, | ||
1264 | &monitor_error_cb, | ||
1265 | NULL, | ||
1266 | &display_record_monitor, | ||
1267 | NULL, | ||
1268 | &sync_cb, | ||
1269 | NULL); | ||
1270 | } | ||
1271 | } | ||
1272 | |||
1273 | |||
1274 | /** | ||
1275 | * Callback invoked from identity service with ego information. | ||
1276 | * An @a ego of NULL means the ego was not found. | ||
1277 | * | ||
1278 | * @param cls closure with the configuration | ||
1279 | * @param ego an ego known to identity service, or NULL | ||
1280 | */ | ||
1281 | static void | ||
1282 | identity_cb (void *cls, struct GNUNET_IDENTITY_Ego *ego) | ||
1283 | { | ||
1284 | const struct GNUNET_CONFIGURATION_Handle *cfg = cls; | ||
1285 | |||
1286 | el = NULL; | ||
1287 | if ((NULL != name) && (0 != strchr (name, '.'))) | ||
1288 | { | ||
1289 | fprintf (stderr, | ||
1290 | _ ("Label `%s' contains `.' which is not allowed\n"), | ||
1291 | name); | ||
1292 | GNUNET_SCHEDULER_shutdown (); | ||
1293 | ret = -1; | ||
1294 | return; | ||
1295 | } | ||
1296 | |||
1297 | if (NULL == ego) | ||
1298 | { | ||
1299 | if (NULL != ego_name) | ||
1300 | { | ||
1301 | fprintf (stderr, | ||
1302 | _ ("Ego `%s' not known to identity service\n"), | ||
1303 | ego_name); | ||
1304 | } | ||
1305 | GNUNET_SCHEDULER_shutdown (); | ||
1306 | ret = -1; | ||
1307 | return; | ||
1308 | } | ||
1309 | zone_pkey = *GNUNET_IDENTITY_ego_get_private_key (ego); | ||
1310 | GNUNET_free (ego_name); | ||
1311 | ego_name = NULL; | ||
1312 | run_with_zone_pkey (cfg); | ||
1313 | } | ||
1314 | |||
1315 | |||
1316 | /** | ||
1317 | * Function called with the default ego to be used for GNS | ||
1318 | * operations. Used if the user did not specify a zone via | ||
1319 | * command-line or environment variables. | ||
1320 | * | ||
1321 | * @param cls NULL | ||
1322 | * @param ego default ego, NULL for none | ||
1323 | * @param ctx NULL | ||
1324 | * @param name unused | ||
1325 | */ | ||
1326 | static void | ||
1327 | default_ego_cb (void *cls, | ||
1328 | struct GNUNET_IDENTITY_Ego *ego, | ||
1329 | void **ctx, | ||
1330 | const char *name) | ||
1331 | { | ||
1332 | const struct GNUNET_CONFIGURATION_Handle *cfg = cls; | ||
1333 | |||
1334 | (void) ctx; | ||
1335 | (void) name; | ||
1336 | get_default = NULL; | ||
1337 | if (NULL == ego) | ||
1338 | { | ||
1339 | fprintf (stderr, | ||
1340 | _ ("No default identity configured for `namestore' subsystem\n" | ||
1341 | "Run gnunet-identity -s namestore -e $NAME to set the default to $NAME\n" | ||
1342 | "Run gnunet-identity -d to get a list of choices for $NAME\n")); | ||
1343 | GNUNET_SCHEDULER_shutdown (); | ||
1344 | ret = -1; | ||
1345 | return; | ||
1346 | } | ||
1347 | else | ||
1348 | { | ||
1349 | identity_cb ((void *) cfg, ego); | ||
1350 | } | ||
1351 | } | ||
1352 | |||
1353 | |||
1354 | /** | ||
1355 | * Function called with ALL of the egos known to the | ||
1356 | * identity service, used on startup if the user did | ||
1357 | * not specify a zone on the command-line. | ||
1358 | * Once the iteration is done (@a ego is NULL), we | ||
1359 | * ask for the default ego for "namestore". | ||
1360 | * | ||
1361 | * @param cls a `struct GNUNET_CONFIGURATION_Handle` | ||
1362 | * @param ego an ego, NULL for end of iteration | ||
1363 | * @param ctx NULL | ||
1364 | * @param name name associated with @a ego | ||
1365 | */ | ||
1366 | static void | ||
1367 | id_connect_cb (void *cls, | ||
1368 | struct GNUNET_IDENTITY_Ego *ego, | ||
1369 | void **ctx, | ||
1370 | const char *name) | ||
1371 | { | ||
1372 | const struct GNUNET_CONFIGURATION_Handle *cfg = cls; | ||
1373 | |||
1374 | (void) ctx; | ||
1375 | (void) name; | ||
1376 | if (NULL != ego) | ||
1377 | return; | ||
1378 | get_default = | ||
1379 | GNUNET_IDENTITY_get (idh, "namestore", &default_ego_cb, (void *) cfg); | ||
1380 | } | ||
1381 | |||
1382 | |||
1383 | /** | ||
1384 | * Main function that will be run. | ||
1385 | * | ||
1386 | * @param cls closure | ||
1387 | * @param args remaining command-line arguments | ||
1388 | * @param cfgfile name of the configuration file used (for saving, can be NULL!) | ||
1389 | * @param cfg configuration | ||
1390 | */ | ||
1391 | static void | ||
1392 | run (void *cls, | ||
1393 | char *const *args, | ||
1394 | const char *cfgfile, | ||
1395 | const struct GNUNET_CONFIGURATION_Handle *cfg) | ||
1396 | { | ||
1397 | const char *pkey_str; | ||
1398 | |||
1399 | (void) cls; | ||
1400 | (void) args; | ||
1401 | (void) cfgfile; | ||
1402 | if (NULL != args[0]) | ||
1403 | GNUNET_log ( | ||
1404 | GNUNET_ERROR_TYPE_WARNING, | ||
1405 | _ ("Superfluous command line arguments (starting with `%s') ignored\n"), | ||
1406 | args[0]); | ||
1407 | if ((NULL != args[0]) && (NULL == uri)) | ||
1408 | uri = GNUNET_strdup (args[0]); | ||
1409 | |||
1410 | GNUNET_SCHEDULER_add_shutdown (&do_shutdown, (void *) cfg); | ||
1411 | pkey_str = getenv ("GNUNET_NAMESTORE_EGO_PRIVATE_KEY"); | ||
1412 | if (NULL != pkey_str) | ||
1413 | { | ||
1414 | if (GNUNET_OK != GNUNET_STRINGS_string_to_data (pkey_str, | ||
1415 | strlen (pkey_str), | ||
1416 | &zone_pkey, | ||
1417 | sizeof(zone_pkey))) | ||
1418 | { | ||
1419 | fprintf (stderr, | ||
1420 | "Malformed private key `%s' in $%s\n", | ||
1421 | pkey_str, | ||
1422 | "GNUNET_NAMESTORE_EGO_PRIVATE_KEY"); | ||
1423 | ret = 1; | ||
1424 | GNUNET_SCHEDULER_shutdown (); | ||
1425 | return; | ||
1426 | } | ||
1427 | run_with_zone_pkey (cfg); | ||
1428 | return; | ||
1429 | } | ||
1430 | if (NULL == ego_name) | ||
1431 | { | ||
1432 | idh = GNUNET_IDENTITY_connect (cfg, &id_connect_cb, (void *) cfg); | ||
1433 | if (NULL == idh) | ||
1434 | fprintf (stderr, _ ("Cannot connect to identity service\n")); | ||
1435 | ret = -1; | ||
1436 | return; | ||
1437 | } | ||
1438 | el = GNUNET_IDENTITY_ego_lookup (cfg, ego_name, &identity_cb, (void *) cfg); | ||
1439 | } | ||
1440 | |||
1441 | |||
1442 | /** | ||
1443 | * Command-line option parser function that allows the user to specify | ||
1444 | * a complete record as one argument for adding/removing. A pointer | ||
1445 | * to the head of the list of record sets must be passed as the "scls" | ||
1446 | * argument. | ||
1447 | * | ||
1448 | * @param ctx command line processor context | ||
1449 | * @param scls must be of type "struct GNUNET_FS_Uri **" | ||
1450 | * @param option name of the option (typically 'R') | ||
1451 | * @param value command line argument given; format is | ||
1452 | * "TTL TYPE FLAGS VALUE" where TTL is an expiration time (rel or abs), | ||
1453 | * always given in seconds (without the unit), | ||
1454 | * TYPE is a DNS/GNS record type, FLAGS is either "n" for no flags or | ||
1455 | * a combination of 's' (shadow) and 'p' (public) and VALUE is the | ||
1456 | * value (in human-readable format) | ||
1457 | * @return #GNUNET_OK on success | ||
1458 | */ | ||
1459 | static int | ||
1460 | multirecord_process (struct GNUNET_GETOPT_CommandLineProcessorContext *ctx, | ||
1461 | void *scls, | ||
1462 | const char *option, | ||
1463 | const char *value) | ||
1464 | { | ||
1465 | struct RecordSetEntry **head = scls; | ||
1466 | struct RecordSetEntry *r; | ||
1467 | struct GNUNET_GNSRECORD_Data record; | ||
1468 | char *cp; | ||
1469 | char *tok; | ||
1470 | char *saveptr; | ||
1471 | int etime_is_rel; | ||
1472 | void *raw_data; | ||
1473 | |||
1474 | (void) ctx; | ||
1475 | (void) option; | ||
1476 | cp = GNUNET_strdup (value); | ||
1477 | tok = strtok_r (cp, " ", &saveptr); | ||
1478 | if (NULL == tok) | ||
1479 | { | ||
1480 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
1481 | _ ("Empty record line argument is not allowed.\n")); | ||
1482 | GNUNET_free (cp); | ||
1483 | return GNUNET_SYSERR; | ||
1484 | } | ||
1485 | { | ||
1486 | char *etime_in_s; | ||
1487 | |||
1488 | GNUNET_asprintf (&etime_in_s, "%s s", tok); | ||
1489 | if (GNUNET_OK != | ||
1490 | parse_expiration (etime_in_s, &etime_is_rel, &record.expiration_time)) | ||
1491 | { | ||
1492 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
1493 | _ ("Invalid expiration time `%s' (must be without unit)\n"), | ||
1494 | tok); | ||
1495 | GNUNET_free (cp); | ||
1496 | GNUNET_free (etime_in_s); | ||
1497 | return GNUNET_SYSERR; | ||
1498 | } | ||
1499 | GNUNET_free (etime_in_s); | ||
1500 | } | ||
1501 | tok = strtok_r (NULL, " ", &saveptr); | ||
1502 | if (NULL == tok) | ||
1503 | { | ||
1504 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
1505 | _ ("Missing entries in record line `%s'.\n"), | ||
1506 | value); | ||
1507 | GNUNET_free (cp); | ||
1508 | return GNUNET_SYSERR; | ||
1509 | } | ||
1510 | record.record_type = GNUNET_GNSRECORD_typename_to_number (tok); | ||
1511 | if (UINT32_MAX == record.record_type) | ||
1512 | { | ||
1513 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _ ("Unknown record type `%s'\n"), tok); | ||
1514 | GNUNET_free (cp); | ||
1515 | return GNUNET_SYSERR; | ||
1516 | } | ||
1517 | tok = strtok_r (NULL, " ", &saveptr); | ||
1518 | if (NULL == tok) | ||
1519 | { | ||
1520 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
1521 | _ ("Missing entries in record line `%s'.\n"), | ||
1522 | value); | ||
1523 | GNUNET_free (cp); | ||
1524 | return GNUNET_SYSERR; | ||
1525 | } | ||
1526 | record.flags = GNUNET_GNSRECORD_RF_NONE; | ||
1527 | if (etime_is_rel) | ||
1528 | record.flags |= GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION; | ||
1529 | if (NULL == strchr (tok, (unsigned char) 'p')) /* p = public */ | ||
1530 | record.flags |= GNUNET_GNSRECORD_RF_PRIVATE; | ||
1531 | if (NULL != strchr (tok, (unsigned char) 's')) | ||
1532 | record.flags |= GNUNET_GNSRECORD_RF_SHADOW_RECORD; | ||
1533 | /* find beginning of record value */ | ||
1534 | tok = strchr (&value[tok - cp], (unsigned char) ' '); | ||
1535 | if (NULL == tok) | ||
1536 | { | ||
1537 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
1538 | _ ("Missing entries in record line `%s'.\n"), | ||
1539 | value); | ||
1540 | GNUNET_free (cp); | ||
1541 | return GNUNET_SYSERR; | ||
1542 | } | ||
1543 | GNUNET_free (cp); | ||
1544 | tok++; /* skip space */ | ||
1545 | if (GNUNET_OK != GNUNET_GNSRECORD_string_to_value (record.record_type, | ||
1546 | tok, | ||
1547 | &raw_data, | ||
1548 | &record.data_size)) | ||
1549 | { | ||
1550 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
1551 | _ ("Invalid record data for type %s: `%s'.\n"), | ||
1552 | GNUNET_GNSRECORD_number_to_typename (record.record_type), | ||
1553 | tok); | ||
1554 | return GNUNET_SYSERR; | ||
1555 | } | ||
1556 | |||
1557 | r = GNUNET_malloc (sizeof(struct RecordSetEntry) + record.data_size); | ||
1558 | r->next = *head; | ||
1559 | record.data = &r[1]; | ||
1560 | memcpy (&r[1], raw_data, record.data_size); | ||
1561 | GNUNET_free (raw_data); | ||
1562 | r->record = record; | ||
1563 | *head = r; | ||
1564 | return GNUNET_OK; | ||
1565 | } | ||
1566 | |||
1567 | |||
1568 | /** | ||
1569 | * Allow user to specify keywords. | ||
1570 | * | ||
1571 | * @param shortName short name of the option | ||
1572 | * @param name long name of the option | ||
1573 | * @param argumentHelp help text for the option argument | ||
1574 | * @param description long help text for the option | ||
1575 | * @param[out] topKeywords set to the desired value | ||
1576 | */ | ||
1577 | struct GNUNET_GETOPT_CommandLineOption | ||
1578 | multirecord_option (char shortName, | ||
1579 | const char *name, | ||
1580 | const char *argumentHelp, | ||
1581 | const char *description, | ||
1582 | struct RecordSetEntry **rs) | ||
1583 | { | ||
1584 | struct GNUNET_GETOPT_CommandLineOption clo = { .shortName = shortName, | ||
1585 | .name = name, | ||
1586 | .argumentHelp = argumentHelp, | ||
1587 | .description = description, | ||
1588 | .require_argument = 1, | ||
1589 | .processor = | ||
1590 | &multirecord_process, | ||
1591 | .scls = (void *) rs }; | ||
1592 | |||
1593 | return clo; | ||
1594 | } | ||
1595 | |||
1596 | |||
1597 | /** | ||
1598 | * The main function for gnunet-namestore. | ||
1599 | * | ||
1600 | * @param argc number of arguments from the command line | ||
1601 | * @param argv command line arguments | ||
1602 | * @return 0 ok, 1 on error | ||
1603 | */ | ||
1604 | int | ||
1605 | main (int argc, char *const *argv) | ||
1606 | { | ||
1607 | struct GNUNET_GETOPT_CommandLineOption options[] = | ||
1608 | { GNUNET_GETOPT_option_flag ('a', "add", gettext_noop ("add record"), &add), | ||
1609 | GNUNET_GETOPT_option_flag ('d', | ||
1610 | "delete", | ||
1611 | gettext_noop ("delete record"), | ||
1612 | &del), | ||
1613 | GNUNET_GETOPT_option_flag ('D', | ||
1614 | "display", | ||
1615 | gettext_noop ("display records"), | ||
1616 | &list), | ||
1617 | GNUNET_GETOPT_option_string ( | ||
1618 | 'e', | ||
1619 | "expiration", | ||
1620 | "TIME", | ||
1621 | gettext_noop ( | ||
1622 | "expiration time for record to use (for adding only), \"never\" is possible"), | ||
1623 | &expirationstring), | ||
1624 | GNUNET_GETOPT_option_string ('i', | ||
1625 | "nick", | ||
1626 | "NICKNAME", | ||
1627 | gettext_noop ( | ||
1628 | "set the desired nick name for the zone"), | ||
1629 | &nickstring), | ||
1630 | GNUNET_GETOPT_option_flag ('m', | ||
1631 | "monitor", | ||
1632 | gettext_noop ( | ||
1633 | "monitor changes in the namestore"), | ||
1634 | &monitor), | ||
1635 | GNUNET_GETOPT_option_string ('n', | ||
1636 | "name", | ||
1637 | "NAME", | ||
1638 | gettext_noop ( | ||
1639 | "name of the record to add/delete/display"), | ||
1640 | &name), | ||
1641 | GNUNET_GETOPT_option_string ('r', | ||
1642 | "reverse", | ||
1643 | "PKEY", | ||
1644 | gettext_noop ( | ||
1645 | "determine our name for the given PKEY"), | ||
1646 | &reverse_pkey), | ||
1647 | multirecord_option ( | ||
1648 | 'R', | ||
1649 | "replace", | ||
1650 | "RECORDLINE", | ||
1651 | gettext_noop ( | ||
1652 | "set record set to values given by (possibly multiple) RECORDLINES; can be specified multiple times"), | ||
1653 | &recordset), | ||
1654 | GNUNET_GETOPT_option_string ('t', | ||
1655 | "type", | ||
1656 | "TYPE", | ||
1657 | gettext_noop ( | ||
1658 | "type of the record to add/delete/display"), | ||
1659 | &typestring), | ||
1660 | GNUNET_GETOPT_option_string ('u', | ||
1661 | "uri", | ||
1662 | "URI", | ||
1663 | gettext_noop ("URI to import into our zone"), | ||
1664 | &uri), | ||
1665 | GNUNET_GETOPT_option_string ('V', | ||
1666 | "value", | ||
1667 | "VALUE", | ||
1668 | gettext_noop ( | ||
1669 | "value of the record to add/delete"), | ||
1670 | &value), | ||
1671 | GNUNET_GETOPT_option_flag ('p', | ||
1672 | "public", | ||
1673 | gettext_noop ("create or list public record"), | ||
1674 | &is_public), | ||
1675 | GNUNET_GETOPT_option_flag ( | ||
1676 | 's', | ||
1677 | "shadow", | ||
1678 | gettext_noop ( | ||
1679 | "create shadow record (only valid if all other records of the same type have expired"), | ||
1680 | &is_shadow), | ||
1681 | GNUNET_GETOPT_option_string ('z', | ||
1682 | "zone", | ||
1683 | "EGO", | ||
1684 | gettext_noop ( | ||
1685 | "name of the ego controlling the zone"), | ||
1686 | &ego_name), | ||
1687 | GNUNET_GETOPT_OPTION_END }; | ||
1688 | int lret; | ||
1689 | |||
1690 | if (GNUNET_OK != GNUNET_STRINGS_get_utf8_args (argc, argv, &argc, &argv)) | ||
1691 | return 2; | ||
1692 | |||
1693 | is_public = -1; | ||
1694 | is_shadow = -1; | ||
1695 | GNUNET_log_setup ("gnunet-namestore", "WARNING", NULL); | ||
1696 | if (GNUNET_OK != | ||
1697 | (lret = GNUNET_PROGRAM_run (argc, | ||
1698 | argv, | ||
1699 | "gnunet-namestore", | ||
1700 | _ ("GNUnet zone manipulation tool"), | ||
1701 | options, | ||
1702 | &run, | ||
1703 | NULL))) | ||
1704 | { | ||
1705 | GNUNET_free_nz ((void *) argv); | ||
1706 | //FIXME | ||
1707 | //GNUNET_CRYPTO_ecdsa_key_clear (&zone_pkey); | ||
1708 | return lret; | ||
1709 | } | ||
1710 | GNUNET_free_nz ((void *) argv); | ||
1711 | //FIXME | ||
1712 | //GNUNET_CRYPTO_ecdsa_key_clear (&zone_pkey); | ||
1713 | return ret; | ||
1714 | } | ||
1715 | |||
1716 | |||
1717 | /* end of gnunet-namestore.c */ | ||
diff --git a/src/namestore/gnunet-service-namestore.c b/src/namestore/gnunet-service-namestore.c deleted file mode 100644 index cd953492e..000000000 --- a/src/namestore/gnunet-service-namestore.c +++ /dev/null | |||
@@ -1,2276 +0,0 @@ | |||
1 | /* | ||
2 | This file is part of GNUnet. | ||
3 | Copyright (C) 2012, 2013, 2014, 2018 GNUnet e.V. | ||
4 | |||
5 | GNUnet is free software: you can redistribute it and/or modify it | ||
6 | under the terms of the GNU Affero General Public License as published | ||
7 | by the Free Software Foundation, either version 3 of the License, | ||
8 | or (at your option) any later version. | ||
9 | |||
10 | GNUnet is distributed in the hope that it will be useful, but | ||
11 | WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
13 | Affero General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU Affero General Public License | ||
16 | along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
17 | |||
18 | SPDX-License-Identifier: AGPL3.0-or-later | ||
19 | */ | ||
20 | |||
21 | /** | ||
22 | * @file namestore/gnunet-service-namestore.c | ||
23 | * @brief namestore for the GNUnet naming system | ||
24 | * @author Matthias Wachs | ||
25 | * @author Christian Grothoff | ||
26 | */ | ||
27 | #include "platform.h" | ||
28 | #include "gnunet_util_lib.h" | ||
29 | #include "gnunet_dnsparser_lib.h" | ||
30 | #include "gnunet_gns_service.h" | ||
31 | #include "gnunet_namecache_service.h" | ||
32 | #include "gnunet_namestore_service.h" | ||
33 | #include "gnunet_namestore_plugin.h" | ||
34 | #include "gnunet_statistics_service.h" | ||
35 | #include "gnunet_signatures.h" | ||
36 | #include "namestore.h" | ||
37 | |||
38 | #define LOG_STRERROR_FILE(kind, syscall, filename) \ | ||
39 | GNUNET_log_from_strerror_file (kind, "util", syscall, filename) | ||
40 | |||
41 | /** | ||
42 | * If a monitor takes more than 1 minute to process an event, print a warning. | ||
43 | */ | ||
44 | #define MONITOR_STALL_WARN_DELAY GNUNET_TIME_UNIT_MINUTES | ||
45 | |||
46 | /** | ||
47 | * Size of the cache used by #get_nick_record() | ||
48 | */ | ||
49 | #define NC_SIZE 16 | ||
50 | |||
51 | /** | ||
52 | * A namestore client | ||
53 | */ | ||
54 | struct NamestoreClient; | ||
55 | |||
56 | |||
57 | /** | ||
58 | * A namestore iteration operation. | ||
59 | */ | ||
60 | struct ZoneIteration | ||
61 | { | ||
62 | /** | ||
63 | * Next element in the DLL | ||
64 | */ | ||
65 | struct ZoneIteration *next; | ||
66 | |||
67 | /** | ||
68 | * Previous element in the DLL | ||
69 | */ | ||
70 | struct ZoneIteration *prev; | ||
71 | |||
72 | /** | ||
73 | * Namestore client which intiated this zone iteration | ||
74 | */ | ||
75 | struct NamestoreClient *nc; | ||
76 | |||
77 | /** | ||
78 | * The nick to add to the records | ||
79 | */ | ||
80 | struct GNUNET_GNSRECORD_Data *nick; | ||
81 | |||
82 | /** | ||
83 | * Key of the zone we are iterating over. | ||
84 | */ | ||
85 | struct GNUNET_IDENTITY_PrivateKey zone; | ||
86 | |||
87 | /** | ||
88 | * Last sequence number in the zone iteration used to address next | ||
89 | * result of the zone iteration in the store | ||
90 | * | ||
91 | * Initially set to 0. | ||
92 | * Updated in #zone_iterate_proc() | ||
93 | */ | ||
94 | uint64_t seq; | ||
95 | |||
96 | /** | ||
97 | * The operation id for the zone iteration in the response for the client | ||
98 | */ | ||
99 | uint32_t request_id; | ||
100 | |||
101 | /** | ||
102 | * Offset of the zone iteration used to address next result of the zone | ||
103 | * iteration in the store | ||
104 | * | ||
105 | * Initially set to 0 in #handle_iteration_start | ||
106 | * Incremented with by every call to #handle_iteration_next | ||
107 | */ | ||
108 | uint32_t offset; | ||
109 | |||
110 | /** | ||
111 | * Number of pending cache operations triggered by this zone iteration which we | ||
112 | * need to wait for before allowing the client to continue. | ||
113 | */ | ||
114 | unsigned int cache_ops; | ||
115 | |||
116 | /** | ||
117 | * Set to #GNUNET_YES if the last iteration exhausted the limit set by the | ||
118 | * client and we should send the #GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_RESULT_END | ||
119 | * message and free the data structure once @e cache_ops is zero. | ||
120 | */ | ||
121 | int send_end; | ||
122 | }; | ||
123 | |||
124 | |||
125 | /** | ||
126 | * A namestore client | ||
127 | */ | ||
128 | struct NamestoreClient | ||
129 | { | ||
130 | /** | ||
131 | * The client | ||
132 | */ | ||
133 | struct GNUNET_SERVICE_Client *client; | ||
134 | |||
135 | /** | ||
136 | * Message queue for transmission to @e client | ||
137 | */ | ||
138 | struct GNUNET_MQ_Handle *mq; | ||
139 | |||
140 | /** | ||
141 | * Head of the DLL of | ||
142 | * Zone iteration operations in progress initiated by this client | ||
143 | */ | ||
144 | struct ZoneIteration *op_head; | ||
145 | |||
146 | /** | ||
147 | * Tail of the DLL of | ||
148 | * Zone iteration operations in progress initiated by this client | ||
149 | */ | ||
150 | struct ZoneIteration *op_tail; | ||
151 | }; | ||
152 | |||
153 | |||
154 | /** | ||
155 | * A namestore monitor. | ||
156 | */ | ||
157 | struct ZoneMonitor | ||
158 | { | ||
159 | /** | ||
160 | * Next element in the DLL | ||
161 | */ | ||
162 | struct ZoneMonitor *next; | ||
163 | |||
164 | /** | ||
165 | * Previous element in the DLL | ||
166 | */ | ||
167 | struct ZoneMonitor *prev; | ||
168 | |||
169 | /** | ||
170 | * Namestore client which intiated this zone monitor | ||
171 | */ | ||
172 | struct NamestoreClient *nc; | ||
173 | |||
174 | /** | ||
175 | * Private key of the zone. | ||
176 | */ | ||
177 | struct GNUNET_IDENTITY_PrivateKey zone; | ||
178 | |||
179 | /** | ||
180 | * Task active during initial iteration. | ||
181 | */ | ||
182 | struct GNUNET_SCHEDULER_Task *task; | ||
183 | |||
184 | /** | ||
185 | * Task to warn about slow monitors. | ||
186 | */ | ||
187 | struct GNUNET_SCHEDULER_Task *sa_wait_warning; | ||
188 | |||
189 | /** | ||
190 | * Since when are we blocked on this monitor? | ||
191 | */ | ||
192 | struct GNUNET_TIME_Absolute sa_waiting_start; | ||
193 | |||
194 | /** | ||
195 | * Last sequence number in the zone iteration used to address next | ||
196 | * result of the zone iteration in the store | ||
197 | * | ||
198 | * Initially set to 0. | ||
199 | * Updated in #monitor_iterate_cb() | ||
200 | */ | ||
201 | uint64_t seq; | ||
202 | |||
203 | /** | ||
204 | * Current limit of how many more messages we are allowed | ||
205 | * to queue to this monitor. | ||
206 | */ | ||
207 | uint64_t limit; | ||
208 | |||
209 | /** | ||
210 | * How many more requests may we receive from the iterator | ||
211 | * before it is at the limit we gave it? Will be below or | ||
212 | * equal to @e limit. The effective limit for monitor | ||
213 | * events is thus @e iteration_cnt - @e limit! | ||
214 | */ | ||
215 | uint64_t iteration_cnt; | ||
216 | |||
217 | /** | ||
218 | * Are we (still) in the initial iteration pass? | ||
219 | */ | ||
220 | int in_first_iteration; | ||
221 | |||
222 | /** | ||
223 | * Is there a store activity waiting for this monitor? We only raise the | ||
224 | * flag when it happens and search the DLL for the store activity when we | ||
225 | * had a limit increase. If we cannot find any waiting store activity at | ||
226 | * that time, we clear the flag again. | ||
227 | */ | ||
228 | int sa_waiting; | ||
229 | }; | ||
230 | |||
231 | |||
232 | /** | ||
233 | * Pending operation on the namecache. | ||
234 | */ | ||
235 | struct CacheOperation | ||
236 | { | ||
237 | /** | ||
238 | * Kept in a DLL. | ||
239 | */ | ||
240 | struct CacheOperation *prev; | ||
241 | |||
242 | /** | ||
243 | * Kept in a DLL. | ||
244 | */ | ||
245 | struct CacheOperation *next; | ||
246 | |||
247 | /** | ||
248 | * Handle to namecache queue. | ||
249 | */ | ||
250 | struct GNUNET_NAMECACHE_QueueEntry *qe; | ||
251 | |||
252 | /** | ||
253 | * Client to notify about the result, can be NULL. | ||
254 | */ | ||
255 | struct NamestoreClient *nc; | ||
256 | |||
257 | /** | ||
258 | * Zone iteration to call #zone_iteration_done_client_continue() | ||
259 | * for if applicable, can be NULL. | ||
260 | */ | ||
261 | struct ZoneIteration *zi; | ||
262 | |||
263 | /** | ||
264 | * Client's request ID. | ||
265 | */ | ||
266 | uint32_t rid; | ||
267 | }; | ||
268 | |||
269 | |||
270 | /** | ||
271 | * Information for an ongoing #handle_record_store() operation. | ||
272 | * Needed as we may wait for monitors to be ready for the notification. | ||
273 | */ | ||
274 | struct StoreActivity | ||
275 | { | ||
276 | /** | ||
277 | * Kept in a DLL. | ||
278 | */ | ||
279 | struct StoreActivity *next; | ||
280 | |||
281 | /** | ||
282 | * Kept in a DLL. | ||
283 | */ | ||
284 | struct StoreActivity *prev; | ||
285 | |||
286 | /** | ||
287 | * Which client triggered the store activity? | ||
288 | */ | ||
289 | struct NamestoreClient *nc; | ||
290 | |||
291 | /** | ||
292 | * Copy of the original store message (as data fields in @e rd will | ||
293 | * point into it!). | ||
294 | */ | ||
295 | const struct RecordStoreMessage *rsm; | ||
296 | |||
297 | /** | ||
298 | * Next zone monitor that still needs to be notified about this PUT. | ||
299 | */ | ||
300 | struct ZoneMonitor *zm_pos; | ||
301 | |||
302 | /** | ||
303 | * Label nicely canonicalized (lower case). | ||
304 | */ | ||
305 | char *conv_name; | ||
306 | }; | ||
307 | |||
308 | |||
309 | /** | ||
310 | * Entry in list of cached nick resolutions. | ||
311 | */ | ||
312 | struct NickCache | ||
313 | { | ||
314 | /** | ||
315 | * Zone the cache entry is for. | ||
316 | */ | ||
317 | struct GNUNET_IDENTITY_PrivateKey zone; | ||
318 | |||
319 | /** | ||
320 | * Cached record data. | ||
321 | */ | ||
322 | struct GNUNET_GNSRECORD_Data *rd; | ||
323 | |||
324 | /** | ||
325 | * Timestamp when this cache entry was used last. | ||
326 | */ | ||
327 | struct GNUNET_TIME_Absolute last_used; | ||
328 | }; | ||
329 | |||
330 | |||
331 | /** | ||
332 | * We cache nick records to reduce DB load. | ||
333 | */ | ||
334 | static struct NickCache nick_cache[NC_SIZE]; | ||
335 | |||
336 | /** | ||
337 | * Public key of all zeros. | ||
338 | */ | ||
339 | static const struct GNUNET_IDENTITY_PrivateKey zero; | ||
340 | |||
341 | /** | ||
342 | * Configuration handle. | ||
343 | */ | ||
344 | static const struct GNUNET_CONFIGURATION_Handle *GSN_cfg; | ||
345 | |||
346 | /** | ||
347 | * Handle to the statistics service | ||
348 | */ | ||
349 | static struct GNUNET_STATISTICS_Handle *statistics; | ||
350 | |||
351 | /** | ||
352 | * Namecache handle. | ||
353 | */ | ||
354 | static struct GNUNET_NAMECACHE_Handle *namecache; | ||
355 | |||
356 | /** | ||
357 | * Database handle | ||
358 | */ | ||
359 | static struct GNUNET_NAMESTORE_PluginFunctions *GSN_database; | ||
360 | |||
361 | /** | ||
362 | * Name of the database plugin | ||
363 | */ | ||
364 | static char *db_lib_name; | ||
365 | |||
366 | /** | ||
367 | * Head of cop DLL. | ||
368 | */ | ||
369 | static struct CacheOperation *cop_head; | ||
370 | |||
371 | /** | ||
372 | * Tail of cop DLL. | ||
373 | */ | ||
374 | static struct CacheOperation *cop_tail; | ||
375 | |||
376 | /** | ||
377 | * First active zone monitor. | ||
378 | */ | ||
379 | static struct ZoneMonitor *monitor_head; | ||
380 | |||
381 | /** | ||
382 | * Last active zone monitor. | ||
383 | */ | ||
384 | static struct ZoneMonitor *monitor_tail; | ||
385 | |||
386 | /** | ||
387 | * Head of DLL of monitor-blocked store activities. | ||
388 | */ | ||
389 | static struct StoreActivity *sa_head; | ||
390 | |||
391 | /** | ||
392 | * Tail of DLL of monitor-blocked store activities. | ||
393 | */ | ||
394 | static struct StoreActivity *sa_tail; | ||
395 | |||
396 | /** | ||
397 | * Notification context shared by all monitors. | ||
398 | */ | ||
399 | static struct GNUNET_NotificationContext *monitor_nc; | ||
400 | |||
401 | /** | ||
402 | * Optimize block insertion by caching map of private keys to | ||
403 | * public keys in memory? | ||
404 | */ | ||
405 | static int cache_keys; | ||
406 | |||
407 | /** | ||
408 | * Use the namecache? Doing so creates additional cryptographic | ||
409 | * operations whenever we touch a record. | ||
410 | */ | ||
411 | static int disable_namecache; | ||
412 | |||
413 | |||
414 | /** | ||
415 | * Task run during shutdown. | ||
416 | * | ||
417 | * @param cls unused | ||
418 | */ | ||
419 | static void | ||
420 | cleanup_task (void *cls) | ||
421 | { | ||
422 | struct CacheOperation *cop; | ||
423 | |||
424 | (void) cls; | ||
425 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Stopping namestore service\n"); | ||
426 | while (NULL != (cop = cop_head)) | ||
427 | { | ||
428 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, | ||
429 | "Aborting incomplete namecache operation\n"); | ||
430 | GNUNET_NAMECACHE_cancel (cop->qe); | ||
431 | GNUNET_CONTAINER_DLL_remove (cop_head, cop_tail, cop); | ||
432 | GNUNET_free (cop); | ||
433 | } | ||
434 | if (NULL != namecache) | ||
435 | { | ||
436 | GNUNET_NAMECACHE_disconnect (namecache); | ||
437 | namecache = NULL; | ||
438 | } | ||
439 | GNUNET_break (NULL == GNUNET_PLUGIN_unload (db_lib_name, GSN_database)); | ||
440 | GNUNET_free (db_lib_name); | ||
441 | db_lib_name = NULL; | ||
442 | if (NULL != monitor_nc) | ||
443 | { | ||
444 | GNUNET_notification_context_destroy (monitor_nc); | ||
445 | monitor_nc = NULL; | ||
446 | } | ||
447 | if (NULL != statistics) | ||
448 | { | ||
449 | GNUNET_STATISTICS_destroy (statistics, GNUNET_NO); | ||
450 | statistics = NULL; | ||
451 | } | ||
452 | } | ||
453 | |||
454 | |||
455 | /** | ||
456 | * Release memory used by @a sa. | ||
457 | * | ||
458 | * @param sa activity to free | ||
459 | */ | ||
460 | static void | ||
461 | free_store_activity (struct StoreActivity *sa) | ||
462 | { | ||
463 | GNUNET_CONTAINER_DLL_remove (sa_head, sa_tail, sa); | ||
464 | GNUNET_free (sa->conv_name); | ||
465 | GNUNET_free (sa); | ||
466 | } | ||
467 | |||
468 | |||
469 | /** | ||
470 | * Function called with the records for the #GNUNET_GNS_EMPTY_LABEL_AT | ||
471 | * label in the zone. Used to locate the #GNUNET_GNSRECORD_TYPE_NICK | ||
472 | * record, which (if found) is then copied to @a cls for future use. | ||
473 | * | ||
474 | * @param cls a `struct GNUNET_GNSRECORD_Data **` for storing the nick (if found) | ||
475 | * @param seq sequence number of the record, MUST NOT BE ZERO | ||
476 | * @param private_key the private key of the zone (unused) | ||
477 | * @param label should be #GNUNET_GNS_EMPTY_LABEL_AT | ||
478 | * @param rd_count number of records in @a rd | ||
479 | * @param rd records stored under @a label in the zone | ||
480 | */ | ||
481 | static void | ||
482 | lookup_nick_it (void *cls, | ||
483 | uint64_t seq, | ||
484 | const struct GNUNET_IDENTITY_PrivateKey *private_key, | ||
485 | const char *label, | ||
486 | unsigned int rd_count, | ||
487 | const struct GNUNET_GNSRECORD_Data *rd) | ||
488 | { | ||
489 | struct GNUNET_GNSRECORD_Data **res = cls; | ||
490 | |||
491 | (void) private_key; | ||
492 | GNUNET_assert (0 != seq); | ||
493 | if (0 != strcmp (label, GNUNET_GNS_EMPTY_LABEL_AT)) | ||
494 | { | ||
495 | GNUNET_break (0); | ||
496 | return; | ||
497 | } | ||
498 | for (unsigned int c = 0; c < rd_count; c++) | ||
499 | { | ||
500 | if (GNUNET_GNSRECORD_TYPE_NICK == rd[c].record_type) | ||
501 | { | ||
502 | (*res) = | ||
503 | GNUNET_malloc (rd[c].data_size + sizeof(struct GNUNET_GNSRECORD_Data)); | ||
504 | (*res)->data = &(*res)[1]; | ||
505 | GNUNET_memcpy ((void *) (*res)->data, rd[c].data, rd[c].data_size); | ||
506 | (*res)->data_size = rd[c].data_size; | ||
507 | (*res)->expiration_time = rd[c].expiration_time; | ||
508 | (*res)->flags = rd[c].flags; | ||
509 | (*res)->record_type = GNUNET_GNSRECORD_TYPE_NICK; | ||
510 | return; | ||
511 | } | ||
512 | } | ||
513 | (*res) = NULL; | ||
514 | } | ||
515 | |||
516 | |||
517 | /** | ||
518 | * Add entry to the cache for @a zone and @a nick | ||
519 | * | ||
520 | * @param zone zone key to cache under | ||
521 | * @param nick nick entry to cache | ||
522 | */ | ||
523 | static void | ||
524 | cache_nick (const struct GNUNET_IDENTITY_PrivateKey *zone, | ||
525 | const struct GNUNET_GNSRECORD_Data *nick) | ||
526 | { | ||
527 | struct NickCache *oldest; | ||
528 | |||
529 | oldest = NULL; | ||
530 | for (unsigned int i = 0; i < NC_SIZE; i++) | ||
531 | { | ||
532 | struct NickCache *pos = &nick_cache[i]; | ||
533 | |||
534 | if ((NULL == oldest) || | ||
535 | (oldest->last_used.abs_value_us > pos->last_used.abs_value_us)) | ||
536 | oldest = pos; | ||
537 | if (0 == GNUNET_memcmp (zone, &pos->zone)) | ||
538 | { | ||
539 | oldest = pos; | ||
540 | break; | ||
541 | } | ||
542 | } | ||
543 | GNUNET_free (oldest->rd); | ||
544 | oldest->zone = *zone; | ||
545 | if (NULL != nick) | ||
546 | { | ||
547 | oldest->rd = GNUNET_malloc (sizeof(*nick) + nick->data_size); | ||
548 | *oldest->rd = *nick; | ||
549 | oldest->rd->data = &oldest->rd[1]; | ||
550 | memcpy (&oldest->rd[1], nick->data, nick->data_size); | ||
551 | } | ||
552 | else | ||
553 | { | ||
554 | oldest->rd = NULL; | ||
555 | } | ||
556 | oldest->last_used = GNUNET_TIME_absolute_get (); | ||
557 | } | ||
558 | |||
559 | |||
560 | /** | ||
561 | * Return the NICK record for the zone (if it exists). | ||
562 | * | ||
563 | * @param zone private key for the zone to look for nick | ||
564 | * @return NULL if no NICK record was found | ||
565 | */ | ||
566 | static struct GNUNET_GNSRECORD_Data * | ||
567 | get_nick_record (const struct GNUNET_IDENTITY_PrivateKey *zone) | ||
568 | { | ||
569 | struct GNUNET_IDENTITY_PublicKey pub; | ||
570 | struct GNUNET_GNSRECORD_Data *nick; | ||
571 | int res; | ||
572 | |||
573 | /* check cache first */ | ||
574 | for (unsigned int i = 0; i < NC_SIZE; i++) | ||
575 | { | ||
576 | struct NickCache *pos = &nick_cache[i]; | ||
577 | if ((NULL != pos->rd) && (0 == GNUNET_memcmp (zone, &pos->zone))) | ||
578 | { | ||
579 | if (NULL == pos->rd) | ||
580 | return NULL; | ||
581 | nick = GNUNET_malloc (sizeof(*nick) + pos->rd->data_size); | ||
582 | *nick = *pos->rd; | ||
583 | nick->data = &nick[1]; | ||
584 | memcpy (&nick[1], pos->rd->data, pos->rd->data_size); | ||
585 | pos->last_used = GNUNET_TIME_absolute_get (); | ||
586 | return nick; | ||
587 | } | ||
588 | } | ||
589 | |||
590 | nick = NULL; | ||
591 | res = GSN_database->lookup_records (GSN_database->cls, | ||
592 | zone, | ||
593 | GNUNET_GNS_EMPTY_LABEL_AT, | ||
594 | &lookup_nick_it, | ||
595 | &nick); | ||
596 | if ((GNUNET_OK != res) || (NULL == nick)) | ||
597 | { | ||
598 | #if ! defined(GNUNET_CULL_LOGGING) | ||
599 | static int do_log = GNUNET_LOG_CALL_STATUS; | ||
600 | |||
601 | if (0 == do_log) | ||
602 | do_log = GNUNET_get_log_call_status (GNUNET_ERROR_TYPE_DEBUG, | ||
603 | "namestore", | ||
604 | __FILE__, | ||
605 | __FUNCTION__, | ||
606 | __LINE__); | ||
607 | if (1 == do_log) | ||
608 | { | ||
609 | GNUNET_IDENTITY_key_get_public (zone, &pub); | ||
610 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG | GNUNET_ERROR_TYPE_BULK, | ||
611 | "No nick name set for zone `%s'\n", | ||
612 | GNUNET_GNSRECORD_z2s (&pub)); | ||
613 | } | ||
614 | #endif | ||
615 | /* update cache */ | ||
616 | cache_nick (zone, NULL); | ||
617 | return NULL; | ||
618 | } | ||
619 | |||
620 | /* update cache */ | ||
621 | cache_nick (zone, nick); | ||
622 | return nick; | ||
623 | } | ||
624 | |||
625 | |||
626 | /** | ||
627 | * Merge the nick record @a nick_rd with the rest of the | ||
628 | * record set given in @a rd2. Store the result in @a rdc_res | ||
629 | * and @a rd_res. The @a nick_rd's expiration time is set to | ||
630 | * the maximum expiration time of all of the records in @a rd2. | ||
631 | * | ||
632 | * @param nick_rd the nick record to integrate | ||
633 | * @param rd2_length length of the @a rd2 array | ||
634 | * @param rd2 array of records | ||
635 | * @param rdc_res[out] length of the resulting @a rd_res array | ||
636 | * @param rd_res[out] set to an array of records, | ||
637 | * including @a nick_rd and @a rd2; | ||
638 | * all of the variable-size 'data' fields in @a rd2 are | ||
639 | * allocated in the same chunk of memory! | ||
640 | */ | ||
641 | static void | ||
642 | merge_with_nick_records (const struct GNUNET_GNSRECORD_Data *nick_rd, | ||
643 | unsigned int rd2_length, | ||
644 | const struct GNUNET_GNSRECORD_Data *rd2, | ||
645 | unsigned int *rdc_res, | ||
646 | struct GNUNET_GNSRECORD_Data **rd_res) | ||
647 | { | ||
648 | uint64_t latest_expiration; | ||
649 | size_t req; | ||
650 | char *data; | ||
651 | size_t data_offset; | ||
652 | struct GNUNET_GNSRECORD_Data *target; | ||
653 | |||
654 | (*rdc_res) = 1 + rd2_length; | ||
655 | if (0 == 1 + rd2_length) | ||
656 | { | ||
657 | GNUNET_break (0); | ||
658 | (*rd_res) = NULL; | ||
659 | return; | ||
660 | } | ||
661 | req = sizeof(struct GNUNET_GNSRECORD_Data) + nick_rd->data_size; | ||
662 | for (unsigned int i = 0; i < rd2_length; i++) | ||
663 | { | ||
664 | const struct GNUNET_GNSRECORD_Data *orig = &rd2[i]; | ||
665 | |||
666 | if (req + sizeof(struct GNUNET_GNSRECORD_Data) + orig->data_size < req) | ||
667 | { | ||
668 | GNUNET_break (0); | ||
669 | (*rd_res) = NULL; | ||
670 | return; | ||
671 | } | ||
672 | req += sizeof(struct GNUNET_GNSRECORD_Data) + orig->data_size; | ||
673 | } | ||
674 | target = GNUNET_malloc (req); | ||
675 | (*rd_res) = target; | ||
676 | data = (char *) &target[1 + rd2_length]; | ||
677 | data_offset = 0; | ||
678 | latest_expiration = 0; | ||
679 | for (unsigned int i = 0; i < rd2_length; i++) | ||
680 | { | ||
681 | const struct GNUNET_GNSRECORD_Data *orig = &rd2[i]; | ||
682 | |||
683 | if (0 != (orig->flags & GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION)) | ||
684 | { | ||
685 | if ((GNUNET_TIME_absolute_get ().abs_value_us + orig->expiration_time) > | ||
686 | latest_expiration) | ||
687 | latest_expiration = orig->expiration_time; | ||
688 | } | ||
689 | else if (orig->expiration_time > latest_expiration) | ||
690 | latest_expiration = orig->expiration_time; | ||
691 | target[i] = *orig; | ||
692 | target[i].data = (void *) &data[data_offset]; | ||
693 | GNUNET_memcpy (&data[data_offset], orig->data, orig->data_size); | ||
694 | data_offset += orig->data_size; | ||
695 | } | ||
696 | /* append nick */ | ||
697 | target[rd2_length] = *nick_rd; | ||
698 | /* Mark as supplemental */ | ||
699 | target[rd2_length].flags = nick_rd->flags | GNUNET_GNSRECORD_RF_SUPPLEMENTAL; | ||
700 | target[rd2_length].expiration_time = latest_expiration; | ||
701 | target[rd2_length].data = (void *) &data[data_offset]; | ||
702 | GNUNET_memcpy (&data[data_offset], nick_rd->data, nick_rd->data_size); | ||
703 | data_offset += nick_rd->data_size; | ||
704 | GNUNET_assert (req == (sizeof(struct GNUNET_GNSRECORD_Data)) * (*rdc_res) | ||
705 | + data_offset); | ||
706 | } | ||
707 | |||
708 | |||
709 | /** | ||
710 | * Generate a `struct LookupNameResponseMessage` and send it to the | ||
711 | * given client using the given notification context. | ||
712 | * | ||
713 | * @param nc client to unicast to | ||
714 | * @param request_id request ID to use | ||
715 | * @param zone_key zone key of the zone | ||
716 | * @param name name | ||
717 | * @param rd_count number of records in @a rd | ||
718 | * @param rd array of records | ||
719 | */ | ||
720 | static void | ||
721 | send_lookup_response (struct NamestoreClient *nc, | ||
722 | uint32_t request_id, | ||
723 | const struct GNUNET_IDENTITY_PrivateKey *zone_key, | ||
724 | const char *name, | ||
725 | unsigned int rd_count, | ||
726 | const struct GNUNET_GNSRECORD_Data *rd) | ||
727 | { | ||
728 | struct GNUNET_MQ_Envelope *env; | ||
729 | struct RecordResultMessage *zir_msg; | ||
730 | struct GNUNET_GNSRECORD_Data *nick; | ||
731 | struct GNUNET_GNSRECORD_Data *res; | ||
732 | unsigned int res_count; | ||
733 | size_t name_len; | ||
734 | ssize_t rd_ser_len; | ||
735 | char *name_tmp; | ||
736 | char *rd_ser; | ||
737 | |||
738 | nick = get_nick_record (zone_key); | ||
739 | GNUNET_assert (-1 != GNUNET_GNSRECORD_records_get_size (rd_count, rd)); | ||
740 | |||
741 | if ((NULL != nick) && (0 != strcmp (name, GNUNET_GNS_EMPTY_LABEL_AT))) | ||
742 | { | ||
743 | nick->flags = | ||
744 | (nick->flags | GNUNET_GNSRECORD_RF_PRIVATE) ^ GNUNET_GNSRECORD_RF_PRIVATE; | ||
745 | merge_with_nick_records (nick, rd_count, rd, &res_count, &res); | ||
746 | } | ||
747 | else | ||
748 | { | ||
749 | res_count = rd_count; | ||
750 | res = (struct GNUNET_GNSRECORD_Data *) rd; | ||
751 | } | ||
752 | if (NULL != nick) | ||
753 | GNUNET_free (nick); | ||
754 | |||
755 | GNUNET_assert (-1 != GNUNET_GNSRECORD_records_get_size (res_count, res)); | ||
756 | |||
757 | |||
758 | name_len = strlen (name) + 1; | ||
759 | rd_ser_len = GNUNET_GNSRECORD_records_get_size (res_count, res); | ||
760 | if (rd_ser_len < 0) | ||
761 | { | ||
762 | if (rd != res) | ||
763 | GNUNET_free (res); | ||
764 | GNUNET_break (0); | ||
765 | GNUNET_SERVICE_client_drop (nc->client); | ||
766 | return; | ||
767 | } | ||
768 | if (((size_t) rd_ser_len) >= UINT16_MAX - name_len - sizeof(*zir_msg)) | ||
769 | { | ||
770 | if (rd != res) | ||
771 | GNUNET_free (res); | ||
772 | GNUNET_break (0); | ||
773 | GNUNET_SERVICE_client_drop (nc->client); | ||
774 | return; | ||
775 | } | ||
776 | env = GNUNET_MQ_msg_extra (zir_msg, | ||
777 | name_len + rd_ser_len, | ||
778 | GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_RESULT); | ||
779 | zir_msg->gns_header.r_id = htonl (request_id); | ||
780 | zir_msg->name_len = htons (name_len); | ||
781 | zir_msg->rd_count = htons (res_count); | ||
782 | zir_msg->rd_len = htons ((uint16_t) rd_ser_len); | ||
783 | zir_msg->private_key = *zone_key; | ||
784 | name_tmp = (char *) &zir_msg[1]; | ||
785 | GNUNET_memcpy (name_tmp, name, name_len); | ||
786 | rd_ser = &name_tmp[name_len]; | ||
787 | GNUNET_assert ( | ||
788 | rd_ser_len == | ||
789 | GNUNET_GNSRECORD_records_serialize (res_count, res, rd_ser_len, rd_ser)); | ||
790 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
791 | "Sending RECORD_RESULT message with %u records\n", | ||
792 | res_count); | ||
793 | GNUNET_STATISTICS_update (statistics, | ||
794 | "Record sets sent to clients", | ||
795 | 1, | ||
796 | GNUNET_NO); | ||
797 | GNUNET_MQ_send (nc->mq, env); | ||
798 | if (rd != res) | ||
799 | GNUNET_free (res); | ||
800 | } | ||
801 | |||
802 | |||
803 | /** | ||
804 | * Send response to the store request to the client. | ||
805 | * | ||
806 | * @param client client to talk to | ||
807 | * @param res status of the operation | ||
808 | * @param rid client's request ID | ||
809 | */ | ||
810 | static void | ||
811 | send_store_response (struct NamestoreClient *nc, int res, uint32_t rid) | ||
812 | { | ||
813 | struct GNUNET_MQ_Envelope *env; | ||
814 | struct RecordStoreResponseMessage *rcr_msg; | ||
815 | |||
816 | GNUNET_assert (NULL != nc); | ||
817 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
818 | "Sending RECORD_STORE_RESPONSE message\n"); | ||
819 | GNUNET_STATISTICS_update (statistics, | ||
820 | "Store requests completed", | ||
821 | 1, | ||
822 | GNUNET_NO); | ||
823 | env = GNUNET_MQ_msg (rcr_msg, | ||
824 | GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_STORE_RESPONSE); | ||
825 | rcr_msg->gns_header.r_id = htonl (rid); | ||
826 | rcr_msg->op_result = htonl (res); | ||
827 | GNUNET_MQ_send (nc->mq, env); | ||
828 | } | ||
829 | |||
830 | |||
831 | /** | ||
832 | * Function called once we are done with the zone iteration and | ||
833 | * allow the zone iteration client to send us more messages. | ||
834 | * | ||
835 | * @param zi zone iteration we are processing | ||
836 | */ | ||
837 | static void | ||
838 | zone_iteration_done_client_continue (struct ZoneIteration *zi) | ||
839 | { | ||
840 | struct GNUNET_MQ_Envelope *env; | ||
841 | struct GNUNET_NAMESTORE_Header *em; | ||
842 | |||
843 | GNUNET_SERVICE_client_continue (zi->nc->client); | ||
844 | if (! zi->send_end) | ||
845 | return; | ||
846 | /* send empty response to indicate end of list */ | ||
847 | env = GNUNET_MQ_msg (em, GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_RESULT_END); | ||
848 | em->r_id = htonl (zi->request_id); | ||
849 | GNUNET_MQ_send (zi->nc->mq, env); | ||
850 | |||
851 | GNUNET_CONTAINER_DLL_remove (zi->nc->op_head, zi->nc->op_tail, zi); | ||
852 | GNUNET_free (zi); | ||
853 | } | ||
854 | |||
855 | |||
856 | /** | ||
857 | * Cache operation complete, clean up. | ||
858 | * | ||
859 | * @param cls the `struct CacheOperation` | ||
860 | * @param success success | ||
861 | * @param emsg error messages | ||
862 | */ | ||
863 | static void | ||
864 | finish_cache_operation (void *cls, int32_t success, const char *emsg) | ||
865 | { | ||
866 | struct CacheOperation *cop = cls; | ||
867 | struct ZoneIteration *zi; | ||
868 | |||
869 | if (NULL != emsg) | ||
870 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, | ||
871 | _ ("Failed to replicate block in namecache: %s\n"), | ||
872 | emsg); | ||
873 | else | ||
874 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "CACHE operation completed\n"); | ||
875 | GNUNET_CONTAINER_DLL_remove (cop_head, cop_tail, cop); | ||
876 | if (NULL != cop->nc) | ||
877 | send_store_response (cop->nc, success, cop->rid); | ||
878 | if (NULL != (zi = cop->zi)) | ||
879 | { | ||
880 | zi->cache_ops--; | ||
881 | if (0 == zi->cache_ops) | ||
882 | { | ||
883 | /* unchoke zone iteration, cache has caught up */ | ||
884 | zone_iteration_done_client_continue (zi); | ||
885 | } | ||
886 | } | ||
887 | GNUNET_free (cop); | ||
888 | } | ||
889 | |||
890 | |||
891 | /** | ||
892 | * We just touched the plaintext information about a name in our zone; | ||
893 | * refresh the corresponding (encrypted) block in the namecache. | ||
894 | * | ||
895 | * @param nc client responsible for the request, can be NULL | ||
896 | * @param zi zone iteration response for the request, can be NULL | ||
897 | * @param rid request ID of the client | ||
898 | * @param zone_key private key of the zone | ||
899 | * @param name label for the records | ||
900 | * @param rd_count number of records | ||
901 | * @param rd records stored under the given @a name | ||
902 | */ | ||
903 | static void | ||
904 | refresh_block (struct NamestoreClient *nc, | ||
905 | struct ZoneIteration *zi, | ||
906 | uint32_t rid, | ||
907 | const struct GNUNET_IDENTITY_PrivateKey *zone_key, | ||
908 | const char *name, | ||
909 | unsigned int rd_count, | ||
910 | const struct GNUNET_GNSRECORD_Data *rd) | ||
911 | { | ||
912 | struct GNUNET_GNSRECORD_Block *block; | ||
913 | struct CacheOperation *cop; | ||
914 | struct GNUNET_IDENTITY_PublicKey pkey; | ||
915 | struct GNUNET_GNSRECORD_Data *nick; | ||
916 | struct GNUNET_GNSRECORD_Data *res; | ||
917 | unsigned int res_count; | ||
918 | struct GNUNET_TIME_Absolute exp_time; | ||
919 | |||
920 | nick = get_nick_record (zone_key); | ||
921 | res_count = rd_count; | ||
922 | res = (struct GNUNET_GNSRECORD_Data *) rd; /* fixme: a bit unclean... */ | ||
923 | if ((NULL != nick) && (0 != strcmp (name, GNUNET_GNS_EMPTY_LABEL_AT))) | ||
924 | { | ||
925 | nick->flags = | ||
926 | (nick->flags | GNUNET_GNSRECORD_RF_PRIVATE) ^ GNUNET_GNSRECORD_RF_PRIVATE; | ||
927 | merge_with_nick_records (nick, rd_count, rd, &res_count, &res); | ||
928 | } | ||
929 | if (NULL != nick) | ||
930 | GNUNET_free (nick); | ||
931 | if (0 == res_count) | ||
932 | { | ||
933 | if (NULL != nc) | ||
934 | send_store_response (nc, GNUNET_OK, rid); | ||
935 | if (rd != res) | ||
936 | GNUNET_free (res); | ||
937 | return; /* no data, no need to update cache */ | ||
938 | } | ||
939 | if (GNUNET_YES == disable_namecache) | ||
940 | { | ||
941 | GNUNET_STATISTICS_update (statistics, | ||
942 | "Namecache updates skipped (NC disabled)", | ||
943 | 1, | ||
944 | GNUNET_NO); | ||
945 | if (NULL != nc) | ||
946 | send_store_response (nc, GNUNET_OK, rid); | ||
947 | if (rd != res) | ||
948 | GNUNET_free (res); | ||
949 | return; | ||
950 | } | ||
951 | exp_time = GNUNET_GNSRECORD_record_get_expiration_time (res_count, res); | ||
952 | if (cache_keys) | ||
953 | block = | ||
954 | GNUNET_GNSRECORD_block_create2 (zone_key, exp_time, name, res, res_count); | ||
955 | else | ||
956 | block = | ||
957 | GNUNET_GNSRECORD_block_create (zone_key, exp_time, name, res, res_count); | ||
958 | GNUNET_assert (NULL != block); | ||
959 | GNUNET_IDENTITY_key_get_public (zone_key, &pkey); | ||
960 | GNUNET_log ( | ||
961 | GNUNET_ERROR_TYPE_DEBUG, | ||
962 | "Caching block for label `%s' with %u records and expiration %s in zone `%s' in namecache\n", | ||
963 | name, | ||
964 | res_count, | ||
965 | GNUNET_STRINGS_absolute_time_to_string (exp_time), | ||
966 | GNUNET_GNSRECORD_z2s (&pkey)); | ||
967 | GNUNET_STATISTICS_update (statistics, | ||
968 | "Namecache updates pushed", | ||
969 | 1, | ||
970 | GNUNET_NO); | ||
971 | cop = GNUNET_new (struct CacheOperation); | ||
972 | cop->nc = nc; | ||
973 | cop->zi = zi; | ||
974 | if (NULL != zi) | ||
975 | zi->cache_ops++; | ||
976 | cop->rid = rid; | ||
977 | GNUNET_CONTAINER_DLL_insert (cop_head, cop_tail, cop); | ||
978 | cop->qe = GNUNET_NAMECACHE_block_cache (namecache, | ||
979 | block, | ||
980 | &finish_cache_operation, | ||
981 | cop); | ||
982 | GNUNET_free (block); | ||
983 | if (rd != res) | ||
984 | GNUNET_free (res); | ||
985 | } | ||
986 | |||
987 | |||
988 | /** | ||
989 | * Print a warning that one of our monitors is no longer reacting. | ||
990 | * | ||
991 | * @param cls a `struct ZoneMonitor` to warn about | ||
992 | */ | ||
993 | static void | ||
994 | warn_monitor_slow (void *cls) | ||
995 | { | ||
996 | struct ZoneMonitor *zm = cls; | ||
997 | |||
998 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, | ||
999 | "No response from monitor since %s\n", | ||
1000 | GNUNET_STRINGS_absolute_time_to_string (zm->sa_waiting_start)); | ||
1001 | zm->sa_wait_warning = GNUNET_SCHEDULER_add_delayed (MONITOR_STALL_WARN_DELAY, | ||
1002 | &warn_monitor_slow, | ||
1003 | zm); | ||
1004 | } | ||
1005 | |||
1006 | |||
1007 | /** | ||
1008 | * Continue processing the @a sa. | ||
1009 | * | ||
1010 | * @param sa store activity to process | ||
1011 | */ | ||
1012 | static void | ||
1013 | continue_store_activity (struct StoreActivity *sa) | ||
1014 | { | ||
1015 | const struct RecordStoreMessage *rp_msg = sa->rsm; | ||
1016 | unsigned int rd_count; | ||
1017 | size_t name_len; | ||
1018 | size_t rd_ser_len; | ||
1019 | uint32_t rid; | ||
1020 | const char *name_tmp; | ||
1021 | const char *rd_ser; | ||
1022 | |||
1023 | rid = ntohl (rp_msg->gns_header.r_id); | ||
1024 | name_len = ntohs (rp_msg->name_len); | ||
1025 | rd_count = ntohs (rp_msg->rd_count); | ||
1026 | rd_ser_len = ntohs (rp_msg->rd_len); | ||
1027 | name_tmp = (const char *) &rp_msg[1]; | ||
1028 | rd_ser = &name_tmp[name_len]; | ||
1029 | { | ||
1030 | struct GNUNET_GNSRECORD_Data rd[GNUNET_NZL (rd_count)]; | ||
1031 | |||
1032 | /* We did this before, must succeed again */ | ||
1033 | GNUNET_assert ( | ||
1034 | GNUNET_OK == | ||
1035 | GNUNET_GNSRECORD_records_deserialize (rd_ser_len, rd_ser, rd_count, rd)); | ||
1036 | |||
1037 | for (struct ZoneMonitor *zm = sa->zm_pos; NULL != zm; zm = sa->zm_pos) | ||
1038 | { | ||
1039 | if ((0 != GNUNET_memcmp (&rp_msg->private_key, &zm->zone)) && | ||
1040 | (0 != GNUNET_memcmp (&zm->zone, &zero))) | ||
1041 | { | ||
1042 | sa->zm_pos = zm->next; /* not interesting to this monitor */ | ||
1043 | continue; | ||
1044 | } | ||
1045 | if (zm->limit == zm->iteration_cnt) | ||
1046 | { | ||
1047 | zm->sa_waiting = GNUNET_YES; | ||
1048 | zm->sa_waiting_start = GNUNET_TIME_absolute_get (); | ||
1049 | if (NULL != zm->sa_wait_warning) | ||
1050 | GNUNET_SCHEDULER_cancel (zm->sa_wait_warning); | ||
1051 | zm->sa_wait_warning = | ||
1052 | GNUNET_SCHEDULER_add_delayed (MONITOR_STALL_WARN_DELAY, | ||
1053 | &warn_monitor_slow, | ||
1054 | zm); | ||
1055 | return; /* blocked on zone monitor */ | ||
1056 | } | ||
1057 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
1058 | "Notifying monitor about changes under label `%s'\n", | ||
1059 | sa->conv_name); | ||
1060 | zm->limit--; | ||
1061 | send_lookup_response (zm->nc, | ||
1062 | 0, | ||
1063 | &rp_msg->private_key, | ||
1064 | sa->conv_name, | ||
1065 | rd_count, | ||
1066 | rd); | ||
1067 | sa->zm_pos = zm->next; | ||
1068 | } | ||
1069 | /* great, done with the monitors, unpack (again) for refresh_block operation */ | ||
1070 | refresh_block (sa->nc, | ||
1071 | NULL, | ||
1072 | rid, | ||
1073 | &rp_msg->private_key, | ||
1074 | sa->conv_name, | ||
1075 | rd_count, | ||
1076 | rd); | ||
1077 | } | ||
1078 | GNUNET_SERVICE_client_continue (sa->nc->client); | ||
1079 | free_store_activity (sa); | ||
1080 | } | ||
1081 | |||
1082 | |||
1083 | /** | ||
1084 | * Called whenever a client is disconnected. | ||
1085 | * Frees our resources associated with that client. | ||
1086 | * | ||
1087 | * @param cls closure | ||
1088 | * @param client identification of the client | ||
1089 | * @param app_ctx the `struct NamestoreClient` of @a client | ||
1090 | */ | ||
1091 | static void | ||
1092 | client_disconnect_cb (void *cls, | ||
1093 | struct GNUNET_SERVICE_Client *client, | ||
1094 | void *app_ctx) | ||
1095 | { | ||
1096 | struct NamestoreClient *nc = app_ctx; | ||
1097 | struct ZoneIteration *no; | ||
1098 | struct CacheOperation *cop; | ||
1099 | |||
1100 | (void) cls; | ||
1101 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Client %p disconnected\n", client); | ||
1102 | for (struct ZoneMonitor *zm = monitor_head; NULL != zm; zm = zm->next) | ||
1103 | { | ||
1104 | struct StoreActivity *san; | ||
1105 | |||
1106 | if (nc != zm->nc) | ||
1107 | continue; | ||
1108 | GNUNET_CONTAINER_DLL_remove (monitor_head, monitor_tail, zm); | ||
1109 | if (NULL != zm->task) | ||
1110 | { | ||
1111 | GNUNET_SCHEDULER_cancel (zm->task); | ||
1112 | zm->task = NULL; | ||
1113 | } | ||
1114 | if (NULL != zm->sa_wait_warning) | ||
1115 | { | ||
1116 | GNUNET_SCHEDULER_cancel (zm->sa_wait_warning); | ||
1117 | zm->sa_wait_warning = NULL; | ||
1118 | } | ||
1119 | for (struct StoreActivity *sa = sa_head; NULL != sa; sa = san) | ||
1120 | { | ||
1121 | san = sa->next; | ||
1122 | if (zm == sa->zm_pos) | ||
1123 | { | ||
1124 | sa->zm_pos = zm->next; | ||
1125 | /* this may free sa */ | ||
1126 | continue_store_activity (sa); | ||
1127 | } | ||
1128 | } | ||
1129 | GNUNET_free (zm); | ||
1130 | break; | ||
1131 | } | ||
1132 | for (struct StoreActivity *sa = sa_head; NULL != sa; sa = sa->next) | ||
1133 | { | ||
1134 | if (sa->nc == nc) | ||
1135 | { | ||
1136 | /* this may free sa */ | ||
1137 | free_store_activity (sa); | ||
1138 | break; /* there can only be one per nc */ | ||
1139 | } | ||
1140 | } | ||
1141 | while (NULL != (no = nc->op_head)) | ||
1142 | { | ||
1143 | GNUNET_CONTAINER_DLL_remove (nc->op_head, nc->op_tail, no); | ||
1144 | GNUNET_free (no); | ||
1145 | } | ||
1146 | for (cop = cop_head; NULL != cop; cop = cop->next) | ||
1147 | if (nc == cop->nc) | ||
1148 | cop->nc = NULL; | ||
1149 | GNUNET_free (nc); | ||
1150 | } | ||
1151 | |||
1152 | |||
1153 | /** | ||
1154 | * Add a client to our list of active clients. | ||
1155 | * | ||
1156 | * @param cls NULL | ||
1157 | * @param client client to add | ||
1158 | * @param mq message queue for @a client | ||
1159 | * @return internal namestore client structure for this client | ||
1160 | */ | ||
1161 | static void * | ||
1162 | client_connect_cb (void *cls, | ||
1163 | struct GNUNET_SERVICE_Client *client, | ||
1164 | struct GNUNET_MQ_Handle *mq) | ||
1165 | { | ||
1166 | struct NamestoreClient *nc; | ||
1167 | |||
1168 | (void) cls; | ||
1169 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Client %p connected\n", client); | ||
1170 | nc = GNUNET_new (struct NamestoreClient); | ||
1171 | nc->client = client; | ||
1172 | nc->mq = mq; | ||
1173 | return nc; | ||
1174 | } | ||
1175 | |||
1176 | |||
1177 | /** | ||
1178 | * Closure for #lookup_it(). | ||
1179 | */ | ||
1180 | struct RecordLookupContext | ||
1181 | { | ||
1182 | /** | ||
1183 | * FIXME. | ||
1184 | */ | ||
1185 | const char *label; | ||
1186 | |||
1187 | /** | ||
1188 | * FIXME. | ||
1189 | */ | ||
1190 | char *res_rd; | ||
1191 | |||
1192 | /** | ||
1193 | * FIXME. | ||
1194 | */ | ||
1195 | struct GNUNET_GNSRECORD_Data *nick; | ||
1196 | |||
1197 | /** | ||
1198 | * FIXME. | ||
1199 | */ | ||
1200 | int found; | ||
1201 | |||
1202 | /** | ||
1203 | * FIXME. | ||
1204 | */ | ||
1205 | unsigned int res_rd_count; | ||
1206 | |||
1207 | /** | ||
1208 | * FIXME. | ||
1209 | */ | ||
1210 | ssize_t rd_ser_len; | ||
1211 | }; | ||
1212 | |||
1213 | |||
1214 | /** | ||
1215 | * Function called by the namestore plugin when we are trying to lookup | ||
1216 | * a record as part of #handle_record_lookup(). Merges all results into | ||
1217 | * the context. | ||
1218 | * | ||
1219 | * @param cls closure with a `struct RecordLookupContext` | ||
1220 | * @param seq unique serial number of the record, MUST NOT BE ZERO | ||
1221 | * @param zone_key private key of the zone | ||
1222 | * @param label name that is being mapped (at most 255 characters long) | ||
1223 | * @param rd_count number of entries in @a rd array | ||
1224 | * @param rd array of records with data to store | ||
1225 | */ | ||
1226 | static void | ||
1227 | lookup_it (void *cls, | ||
1228 | uint64_t seq, | ||
1229 | const struct GNUNET_IDENTITY_PrivateKey *private_key, | ||
1230 | const char *label, | ||
1231 | unsigned int rd_count, | ||
1232 | const struct GNUNET_GNSRECORD_Data *rd) | ||
1233 | { | ||
1234 | struct RecordLookupContext *rlc = cls; | ||
1235 | |||
1236 | (void) private_key; | ||
1237 | GNUNET_assert (0 != seq); | ||
1238 | if (0 != strcmp (label, rlc->label)) | ||
1239 | return; | ||
1240 | rlc->found = GNUNET_YES; | ||
1241 | if (0 == rd_count) | ||
1242 | { | ||
1243 | rlc->rd_ser_len = 0; | ||
1244 | rlc->res_rd_count = 0; | ||
1245 | rlc->res_rd = NULL; | ||
1246 | return; | ||
1247 | } | ||
1248 | if ((NULL != rlc->nick) && (0 != strcmp (label, GNUNET_GNS_EMPTY_LABEL_AT))) | ||
1249 | { | ||
1250 | /* Merge */ | ||
1251 | struct GNUNET_GNSRECORD_Data *rd_res; | ||
1252 | unsigned int rdc_res; | ||
1253 | |||
1254 | rd_res = NULL; | ||
1255 | rdc_res = 0; | ||
1256 | rlc->nick->flags = (rlc->nick->flags | GNUNET_GNSRECORD_RF_PRIVATE) | ||
1257 | ^ GNUNET_GNSRECORD_RF_PRIVATE; | ||
1258 | merge_with_nick_records (rlc->nick, rd_count, rd, &rdc_res, &rd_res); | ||
1259 | rlc->rd_ser_len = GNUNET_GNSRECORD_records_get_size (rdc_res, rd_res); | ||
1260 | if (rlc->rd_ser_len < 0) | ||
1261 | { | ||
1262 | GNUNET_break (0); | ||
1263 | GNUNET_free (rd_res); | ||
1264 | rlc->found = GNUNET_NO; | ||
1265 | rlc->rd_ser_len = 0; | ||
1266 | return; | ||
1267 | } | ||
1268 | rlc->res_rd_count = rdc_res; | ||
1269 | rlc->res_rd = GNUNET_malloc (rlc->rd_ser_len); | ||
1270 | if (rlc->rd_ser_len != GNUNET_GNSRECORD_records_serialize (rdc_res, | ||
1271 | rd_res, | ||
1272 | rlc->rd_ser_len, | ||
1273 | rlc->res_rd)) | ||
1274 | { | ||
1275 | GNUNET_break (0); | ||
1276 | GNUNET_free (rlc->res_rd); | ||
1277 | rlc->res_rd = NULL; | ||
1278 | rlc->res_rd_count = 0; | ||
1279 | rlc->rd_ser_len = 0; | ||
1280 | GNUNET_free (rd_res); | ||
1281 | rlc->found = GNUNET_NO; | ||
1282 | return; | ||
1283 | } | ||
1284 | GNUNET_free (rd_res); | ||
1285 | GNUNET_free (rlc->nick); | ||
1286 | rlc->nick = NULL; | ||
1287 | } | ||
1288 | else | ||
1289 | { | ||
1290 | rlc->rd_ser_len = GNUNET_GNSRECORD_records_get_size (rd_count, rd); | ||
1291 | if (rlc->rd_ser_len < 0) | ||
1292 | { | ||
1293 | GNUNET_break (0); | ||
1294 | rlc->found = GNUNET_NO; | ||
1295 | rlc->rd_ser_len = 0; | ||
1296 | return; | ||
1297 | } | ||
1298 | rlc->res_rd_count = rd_count; | ||
1299 | rlc->res_rd = GNUNET_malloc (rlc->rd_ser_len); | ||
1300 | if (rlc->rd_ser_len != GNUNET_GNSRECORD_records_serialize (rd_count, | ||
1301 | rd, | ||
1302 | rlc->rd_ser_len, | ||
1303 | rlc->res_rd)) | ||
1304 | { | ||
1305 | GNUNET_break (0); | ||
1306 | GNUNET_free (rlc->res_rd); | ||
1307 | rlc->res_rd = NULL; | ||
1308 | rlc->res_rd_count = 0; | ||
1309 | rlc->rd_ser_len = 0; | ||
1310 | rlc->found = GNUNET_NO; | ||
1311 | return; | ||
1312 | } | ||
1313 | } | ||
1314 | } | ||
1315 | |||
1316 | |||
1317 | /** | ||
1318 | * Handles a #GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_LOOKUP message | ||
1319 | * | ||
1320 | * @param cls client sending the message | ||
1321 | * @param ll_msg message of type `struct LabelLookupMessage` | ||
1322 | * @return #GNUNET_OK if @a ll_msg is well-formed | ||
1323 | */ | ||
1324 | static int | ||
1325 | check_record_lookup (void *cls, const struct LabelLookupMessage *ll_msg) | ||
1326 | { | ||
1327 | uint32_t name_len; | ||
1328 | size_t src_size; | ||
1329 | |||
1330 | (void) cls; | ||
1331 | name_len = ntohl (ll_msg->label_len); | ||
1332 | src_size = ntohs (ll_msg->gns_header.header.size); | ||
1333 | if (name_len != src_size - sizeof(struct LabelLookupMessage)) | ||
1334 | { | ||
1335 | GNUNET_break (0); | ||
1336 | return GNUNET_SYSERR; | ||
1337 | } | ||
1338 | GNUNET_MQ_check_zero_termination (ll_msg); | ||
1339 | return GNUNET_OK; | ||
1340 | } | ||
1341 | |||
1342 | |||
1343 | /** | ||
1344 | * Handles a #GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_LOOKUP message | ||
1345 | * | ||
1346 | * @param cls client sending the message | ||
1347 | * @param ll_msg message of type `struct LabelLookupMessage` | ||
1348 | */ | ||
1349 | static void | ||
1350 | handle_record_lookup (void *cls, const struct LabelLookupMessage *ll_msg) | ||
1351 | { | ||
1352 | struct NamestoreClient *nc = cls; | ||
1353 | struct GNUNET_MQ_Envelope *env; | ||
1354 | struct LabelLookupResponseMessage *llr_msg; | ||
1355 | struct RecordLookupContext rlc; | ||
1356 | const char *name_tmp; | ||
1357 | char *res_name; | ||
1358 | char *conv_name; | ||
1359 | uint32_t name_len; | ||
1360 | int res; | ||
1361 | |||
1362 | name_len = ntohl (ll_msg->label_len); | ||
1363 | name_tmp = (const char *) &ll_msg[1]; | ||
1364 | GNUNET_SERVICE_client_continue (nc->client); | ||
1365 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
1366 | "Received NAMESTORE_RECORD_LOOKUP message for name `%s'\n", | ||
1367 | name_tmp); | ||
1368 | |||
1369 | conv_name = GNUNET_GNSRECORD_string_to_lowercase (name_tmp); | ||
1370 | if (NULL == conv_name) | ||
1371 | { | ||
1372 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
1373 | "Error converting name `%s'\n", | ||
1374 | name_tmp); | ||
1375 | GNUNET_SERVICE_client_drop (nc->client); | ||
1376 | return; | ||
1377 | } | ||
1378 | rlc.label = conv_name; | ||
1379 | rlc.found = GNUNET_NO; | ||
1380 | rlc.res_rd_count = 0; | ||
1381 | rlc.res_rd = NULL; | ||
1382 | rlc.rd_ser_len = 0; | ||
1383 | rlc.nick = get_nick_record (&ll_msg->zone); | ||
1384 | res = GSN_database->lookup_records (GSN_database->cls, | ||
1385 | &ll_msg->zone, | ||
1386 | conv_name, | ||
1387 | &lookup_it, | ||
1388 | &rlc); | ||
1389 | GNUNET_free (conv_name); | ||
1390 | env = | ||
1391 | GNUNET_MQ_msg_extra (llr_msg, | ||
1392 | name_len + rlc.rd_ser_len, | ||
1393 | GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_LOOKUP_RESPONSE); | ||
1394 | llr_msg->gns_header.r_id = ll_msg->gns_header.r_id; | ||
1395 | llr_msg->private_key = ll_msg->zone; | ||
1396 | llr_msg->name_len = htons (name_len); | ||
1397 | llr_msg->rd_count = htons (rlc.res_rd_count); | ||
1398 | llr_msg->rd_len = htons (rlc.rd_ser_len); | ||
1399 | res_name = (char *) &llr_msg[1]; | ||
1400 | if ((GNUNET_YES == rlc.found) && (GNUNET_OK == res)) | ||
1401 | llr_msg->found = ntohs (GNUNET_YES); | ||
1402 | else | ||
1403 | llr_msg->found = ntohs (GNUNET_NO); | ||
1404 | GNUNET_memcpy (&llr_msg[1], name_tmp, name_len); | ||
1405 | GNUNET_memcpy (&res_name[name_len], rlc.res_rd, rlc.rd_ser_len); | ||
1406 | GNUNET_MQ_send (nc->mq, env); | ||
1407 | GNUNET_free (rlc.res_rd); | ||
1408 | } | ||
1409 | |||
1410 | |||
1411 | /** | ||
1412 | * Checks a #GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_STORE message | ||
1413 | * | ||
1414 | * @param cls client sending the message | ||
1415 | * @param rp_msg message of type `struct RecordStoreMessage` | ||
1416 | * @return #GNUNET_OK if @a rp_msg is well-formed | ||
1417 | */ | ||
1418 | static int | ||
1419 | check_record_store (void *cls, const struct RecordStoreMessage *rp_msg) | ||
1420 | { | ||
1421 | size_t name_len; | ||
1422 | size_t msg_size; | ||
1423 | size_t msg_size_exp; | ||
1424 | size_t rd_ser_len; | ||
1425 | const char *name_tmp; | ||
1426 | |||
1427 | (void) cls; | ||
1428 | name_len = ntohs (rp_msg->name_len); | ||
1429 | msg_size = ntohs (rp_msg->gns_header.header.size); | ||
1430 | rd_ser_len = ntohs (rp_msg->rd_len); | ||
1431 | msg_size_exp = sizeof(struct RecordStoreMessage) + name_len + rd_ser_len; | ||
1432 | if (msg_size != msg_size_exp) | ||
1433 | { | ||
1434 | GNUNET_break (0); | ||
1435 | return GNUNET_SYSERR; | ||
1436 | } | ||
1437 | if ((0 == name_len) || (name_len > MAX_NAME_LEN)) | ||
1438 | { | ||
1439 | GNUNET_break (0); | ||
1440 | return GNUNET_SYSERR; | ||
1441 | } | ||
1442 | name_tmp = (const char *) &rp_msg[1]; | ||
1443 | if ('\0' != name_tmp[name_len - 1]) | ||
1444 | { | ||
1445 | GNUNET_break (0); | ||
1446 | return GNUNET_SYSERR; | ||
1447 | } | ||
1448 | return GNUNET_OK; | ||
1449 | } | ||
1450 | |||
1451 | |||
1452 | /** | ||
1453 | * Handles a #GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_STORE message | ||
1454 | * | ||
1455 | * @param cls client sending the message | ||
1456 | * @param rp_msg message of type `struct RecordStoreMessage` | ||
1457 | */ | ||
1458 | static void | ||
1459 | handle_record_store (void *cls, const struct RecordStoreMessage *rp_msg) | ||
1460 | { | ||
1461 | struct NamestoreClient *nc = cls; | ||
1462 | size_t name_len; | ||
1463 | size_t rd_ser_len; | ||
1464 | uint32_t rid; | ||
1465 | const char *name_tmp; | ||
1466 | char *conv_name; | ||
1467 | const char *rd_ser; | ||
1468 | unsigned int rd_count; | ||
1469 | int res; | ||
1470 | struct StoreActivity *sa; | ||
1471 | |||
1472 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
1473 | "Received NAMESTORE_RECORD_STORE message\n"); | ||
1474 | rid = ntohl (rp_msg->gns_header.r_id); | ||
1475 | name_len = ntohs (rp_msg->name_len); | ||
1476 | rd_count = ntohs (rp_msg->rd_count); | ||
1477 | rd_ser_len = ntohs (rp_msg->rd_len); | ||
1478 | GNUNET_break (0 == ntohs (rp_msg->reserved)); | ||
1479 | name_tmp = (const char *) &rp_msg[1]; | ||
1480 | rd_ser = &name_tmp[name_len]; | ||
1481 | { | ||
1482 | struct GNUNET_GNSRECORD_Data rd[GNUNET_NZL (rd_count)]; | ||
1483 | |||
1484 | if (GNUNET_OK != | ||
1485 | GNUNET_GNSRECORD_records_deserialize (rd_ser_len, rd_ser, rd_count, rd)) | ||
1486 | { | ||
1487 | GNUNET_break (0); | ||
1488 | GNUNET_SERVICE_client_drop (nc->client); | ||
1489 | return; | ||
1490 | } | ||
1491 | |||
1492 | /* Extracting and converting private key */ | ||
1493 | conv_name = GNUNET_GNSRECORD_string_to_lowercase (name_tmp); | ||
1494 | if (NULL == conv_name) | ||
1495 | { | ||
1496 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
1497 | "Error converting name `%s'\n", | ||
1498 | name_tmp); | ||
1499 | GNUNET_SERVICE_client_drop (nc->client); | ||
1500 | return; | ||
1501 | } | ||
1502 | GNUNET_STATISTICS_update (statistics, | ||
1503 | "Well-formed store requests received", | ||
1504 | 1, | ||
1505 | GNUNET_NO); | ||
1506 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
1507 | "Creating %u records for name `%s'\n", | ||
1508 | (unsigned int) rd_count, | ||
1509 | conv_name); | ||
1510 | if ((0 == rd_count) && | ||
1511 | (GNUNET_NO == GSN_database->lookup_records (GSN_database->cls, | ||
1512 | &rp_msg->private_key, | ||
1513 | conv_name, | ||
1514 | NULL, | ||
1515 | 0))) | ||
1516 | { | ||
1517 | /* This name does not exist, so cannot be removed */ | ||
1518 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
1519 | "Name `%s' does not exist, no deletion required\n", | ||
1520 | conv_name); | ||
1521 | res = GNUNET_NO; | ||
1522 | } | ||
1523 | else | ||
1524 | { | ||
1525 | /* remove "NICK" records, unless this is for the | ||
1526 | #GNUNET_GNS_EMPTY_LABEL_AT label */ | ||
1527 | struct GNUNET_GNSRECORD_Data rd_clean[GNUNET_NZL (rd_count)]; | ||
1528 | unsigned int rd_clean_off; | ||
1529 | int have_nick; | ||
1530 | |||
1531 | rd_clean_off = 0; | ||
1532 | have_nick = GNUNET_NO; | ||
1533 | for (unsigned int i = 0; i < rd_count; i++) | ||
1534 | { | ||
1535 | rd_clean[rd_clean_off] = rd[i]; | ||
1536 | if ((0 == strcmp (GNUNET_GNS_EMPTY_LABEL_AT, conv_name)) || | ||
1537 | (GNUNET_GNSRECORD_TYPE_NICK != rd[i].record_type)) | ||
1538 | rd_clean_off++; | ||
1539 | |||
1540 | if ((0 == strcmp (GNUNET_GNS_EMPTY_LABEL_AT, conv_name)) && | ||
1541 | (GNUNET_GNSRECORD_TYPE_NICK == rd[i].record_type)) | ||
1542 | { | ||
1543 | cache_nick (&rp_msg->private_key, &rd[i]); | ||
1544 | have_nick = GNUNET_YES; | ||
1545 | } | ||
1546 | } | ||
1547 | if ((0 == strcmp (GNUNET_GNS_EMPTY_LABEL_AT, conv_name)) && | ||
1548 | (GNUNET_NO == have_nick)) | ||
1549 | { | ||
1550 | /* remove nick record from cache, in case we have one there */ | ||
1551 | cache_nick (&rp_msg->private_key, NULL); | ||
1552 | } | ||
1553 | res = GSN_database->store_records (GSN_database->cls, | ||
1554 | &rp_msg->private_key, | ||
1555 | conv_name, | ||
1556 | rd_clean_off, | ||
1557 | rd_clean); | ||
1558 | } | ||
1559 | |||
1560 | if (GNUNET_OK != res) | ||
1561 | { | ||
1562 | /* store not successful, not need to tell monitors */ | ||
1563 | send_store_response (nc, res, rid); | ||
1564 | GNUNET_SERVICE_client_continue (nc->client); | ||
1565 | GNUNET_free (conv_name); | ||
1566 | return; | ||
1567 | } | ||
1568 | |||
1569 | sa = GNUNET_malloc (sizeof(struct StoreActivity) | ||
1570 | + ntohs (rp_msg->gns_header.header.size)); | ||
1571 | GNUNET_CONTAINER_DLL_insert (sa_head, sa_tail, sa); | ||
1572 | sa->nc = nc; | ||
1573 | sa->rsm = (const struct RecordStoreMessage *) &sa[1]; | ||
1574 | GNUNET_memcpy (&sa[1], rp_msg, ntohs (rp_msg->gns_header.header.size)); | ||
1575 | sa->zm_pos = monitor_head; | ||
1576 | sa->conv_name = conv_name; | ||
1577 | continue_store_activity (sa); | ||
1578 | } | ||
1579 | } | ||
1580 | |||
1581 | |||
1582 | /** | ||
1583 | * Context for record remove operations passed from #handle_zone_to_name to | ||
1584 | * #handle_zone_to_name_it as closure | ||
1585 | */ | ||
1586 | struct ZoneToNameCtx | ||
1587 | { | ||
1588 | /** | ||
1589 | * Namestore client | ||
1590 | */ | ||
1591 | struct NamestoreClient *nc; | ||
1592 | |||
1593 | /** | ||
1594 | * Request id (to be used in the response to the client). | ||
1595 | */ | ||
1596 | uint32_t rid; | ||
1597 | |||
1598 | /** | ||
1599 | * Set to #GNUNET_OK on success, #GNUNET_SYSERR on error. Note that | ||
1600 | * not finding a name for the zone still counts as a 'success' here, | ||
1601 | * as this field is about the success of executing the IPC protocol. | ||
1602 | */ | ||
1603 | int success; | ||
1604 | }; | ||
1605 | |||
1606 | |||
1607 | /** | ||
1608 | * Zone to name iterator | ||
1609 | * | ||
1610 | * @param cls struct ZoneToNameCtx * | ||
1611 | * @param seq sequence number of the record, MUST NOT BE ZERO | ||
1612 | * @param zone_key the zone key | ||
1613 | * @param name name | ||
1614 | * @param rd_count number of records in @a rd | ||
1615 | * @param rd record data | ||
1616 | */ | ||
1617 | static void | ||
1618 | handle_zone_to_name_it (void *cls, | ||
1619 | uint64_t seq, | ||
1620 | const struct GNUNET_IDENTITY_PrivateKey *zone_key, | ||
1621 | const char *name, | ||
1622 | unsigned int rd_count, | ||
1623 | const struct GNUNET_GNSRECORD_Data *rd) | ||
1624 | { | ||
1625 | struct ZoneToNameCtx *ztn_ctx = cls; | ||
1626 | struct GNUNET_MQ_Envelope *env; | ||
1627 | struct ZoneToNameResponseMessage *ztnr_msg; | ||
1628 | int16_t res; | ||
1629 | size_t name_len; | ||
1630 | ssize_t rd_ser_len; | ||
1631 | size_t msg_size; | ||
1632 | char *name_tmp; | ||
1633 | char *rd_tmp; | ||
1634 | |||
1635 | GNUNET_assert (0 != seq); | ||
1636 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
1637 | "Found result for zone-to-name lookup: `%s'\n", | ||
1638 | name); | ||
1639 | res = GNUNET_YES; | ||
1640 | name_len = (NULL == name) ? 0 : strlen (name) + 1; | ||
1641 | rd_ser_len = GNUNET_GNSRECORD_records_get_size (rd_count, rd); | ||
1642 | if (rd_ser_len < 0) | ||
1643 | { | ||
1644 | GNUNET_break (0); | ||
1645 | ztn_ctx->success = GNUNET_SYSERR; | ||
1646 | return; | ||
1647 | } | ||
1648 | msg_size = sizeof(struct ZoneToNameResponseMessage) + name_len + rd_ser_len; | ||
1649 | if (msg_size >= GNUNET_MAX_MESSAGE_SIZE) | ||
1650 | { | ||
1651 | GNUNET_break (0); | ||
1652 | ztn_ctx->success = GNUNET_SYSERR; | ||
1653 | return; | ||
1654 | } | ||
1655 | env = | ||
1656 | GNUNET_MQ_msg_extra (ztnr_msg, | ||
1657 | name_len + rd_ser_len, | ||
1658 | GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_TO_NAME_RESPONSE); | ||
1659 | ztnr_msg->gns_header.header.size = htons (msg_size); | ||
1660 | ztnr_msg->gns_header.r_id = htonl (ztn_ctx->rid); | ||
1661 | ztnr_msg->res = htons (res); | ||
1662 | ztnr_msg->rd_len = htons (rd_ser_len); | ||
1663 | ztnr_msg->rd_count = htons (rd_count); | ||
1664 | ztnr_msg->name_len = htons (name_len); | ||
1665 | ztnr_msg->zone = *zone_key; | ||
1666 | name_tmp = (char *) &ztnr_msg[1]; | ||
1667 | GNUNET_memcpy (name_tmp, name, name_len); | ||
1668 | rd_tmp = &name_tmp[name_len]; | ||
1669 | GNUNET_assert ( | ||
1670 | rd_ser_len == | ||
1671 | GNUNET_GNSRECORD_records_serialize (rd_count, rd, rd_ser_len, rd_tmp)); | ||
1672 | ztn_ctx->success = GNUNET_OK; | ||
1673 | GNUNET_MQ_send (ztn_ctx->nc->mq, env); | ||
1674 | } | ||
1675 | |||
1676 | |||
1677 | /** | ||
1678 | * Handles a #GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_TO_NAME message | ||
1679 | * | ||
1680 | * @param cls client client sending the message | ||
1681 | * @param ztn_msg message of type 'struct ZoneToNameMessage' | ||
1682 | */ | ||
1683 | static void | ||
1684 | handle_zone_to_name (void *cls, const struct ZoneToNameMessage *ztn_msg) | ||
1685 | { | ||
1686 | struct NamestoreClient *nc = cls; | ||
1687 | struct ZoneToNameCtx ztn_ctx; | ||
1688 | struct GNUNET_MQ_Envelope *env; | ||
1689 | struct ZoneToNameResponseMessage *ztnr_msg; | ||
1690 | |||
1691 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received ZONE_TO_NAME message\n"); | ||
1692 | ztn_ctx.rid = ntohl (ztn_msg->gns_header.r_id); | ||
1693 | ztn_ctx.nc = nc; | ||
1694 | ztn_ctx.success = GNUNET_NO; | ||
1695 | if (GNUNET_SYSERR == GSN_database->zone_to_name (GSN_database->cls, | ||
1696 | &ztn_msg->zone, | ||
1697 | &ztn_msg->value_zone, | ||
1698 | &handle_zone_to_name_it, | ||
1699 | &ztn_ctx)) | ||
1700 | { | ||
1701 | /* internal error, hang up instead of signalling something | ||
1702 | that might be wrong */ | ||
1703 | GNUNET_break (0); | ||
1704 | GNUNET_SERVICE_client_drop (nc->client); | ||
1705 | return; | ||
1706 | } | ||
1707 | if (GNUNET_NO == ztn_ctx.success) | ||
1708 | { | ||
1709 | /* no result found, send empty response */ | ||
1710 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
1711 | "Found no result for zone-to-name lookup.\n"); | ||
1712 | env = GNUNET_MQ_msg (ztnr_msg, | ||
1713 | GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_TO_NAME_RESPONSE); | ||
1714 | ztnr_msg->gns_header.r_id = ztn_msg->gns_header.r_id; | ||
1715 | ztnr_msg->res = htons (GNUNET_NO); | ||
1716 | GNUNET_MQ_send (nc->mq, env); | ||
1717 | } | ||
1718 | GNUNET_SERVICE_client_continue (nc->client); | ||
1719 | } | ||
1720 | |||
1721 | |||
1722 | /** | ||
1723 | * Context for record remove operations passed from | ||
1724 | * #run_zone_iteration_round to #zone_iterate_proc as closure | ||
1725 | */ | ||
1726 | struct ZoneIterationProcResult | ||
1727 | { | ||
1728 | /** | ||
1729 | * The zone iteration handle | ||
1730 | */ | ||
1731 | struct ZoneIteration *zi; | ||
1732 | |||
1733 | /** | ||
1734 | * Number of results left to be returned in this iteration. | ||
1735 | */ | ||
1736 | uint64_t limit; | ||
1737 | }; | ||
1738 | |||
1739 | |||
1740 | /** | ||
1741 | * Process results for zone iteration from database | ||
1742 | * | ||
1743 | * @param cls struct ZoneIterationProcResult | ||
1744 | * @param seq sequence number of the record, MUST NOT BE ZERO | ||
1745 | * @param zone_key the zone key | ||
1746 | * @param name name | ||
1747 | * @param rd_count number of records for this name | ||
1748 | * @param rd record data | ||
1749 | */ | ||
1750 | static void | ||
1751 | zone_iterate_proc (void *cls, | ||
1752 | uint64_t seq, | ||
1753 | const struct GNUNET_IDENTITY_PrivateKey *zone_key, | ||
1754 | const char *name, | ||
1755 | unsigned int rd_count, | ||
1756 | const struct GNUNET_GNSRECORD_Data *rd) | ||
1757 | { | ||
1758 | struct ZoneIterationProcResult *proc = cls; | ||
1759 | int do_refresh_block; | ||
1760 | |||
1761 | GNUNET_assert (0 != seq); | ||
1762 | if ((NULL == zone_key) && (NULL == name)) | ||
1763 | { | ||
1764 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Iteration done\n"); | ||
1765 | return; | ||
1766 | } | ||
1767 | if ((NULL == zone_key) || (NULL == name)) | ||
1768 | { | ||
1769 | /* what is this!? should never happen */ | ||
1770 | GNUNET_break (0); | ||
1771 | return; | ||
1772 | } | ||
1773 | if (0 == proc->limit) | ||
1774 | { | ||
1775 | /* what is this!? should never happen */ | ||
1776 | GNUNET_break (0); | ||
1777 | return; | ||
1778 | } | ||
1779 | proc->limit--; | ||
1780 | proc->zi->seq = seq; | ||
1781 | send_lookup_response (proc->zi->nc, | ||
1782 | proc->zi->request_id, | ||
1783 | zone_key, | ||
1784 | name, | ||
1785 | rd_count, | ||
1786 | rd); | ||
1787 | |||
1788 | |||
1789 | do_refresh_block = GNUNET_NO; | ||
1790 | for (unsigned int i = 0; i < rd_count; i++) | ||
1791 | if (0 != (rd[i].flags & GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION)) | ||
1792 | { | ||
1793 | do_refresh_block = GNUNET_YES; | ||
1794 | break; | ||
1795 | } | ||
1796 | if (GNUNET_YES == do_refresh_block) | ||
1797 | refresh_block (NULL, proc->zi, 0, zone_key, name, rd_count, rd); | ||
1798 | } | ||
1799 | |||
1800 | |||
1801 | /** | ||
1802 | * Perform the next round of the zone iteration. | ||
1803 | * | ||
1804 | * @param zi zone iterator to process | ||
1805 | * @param limit number of results to return in one pass | ||
1806 | */ | ||
1807 | static void | ||
1808 | run_zone_iteration_round (struct ZoneIteration *zi, uint64_t limit) | ||
1809 | { | ||
1810 | struct ZoneIterationProcResult proc; | ||
1811 | struct GNUNET_TIME_Absolute start; | ||
1812 | struct GNUNET_TIME_Relative duration; | ||
1813 | |||
1814 | memset (&proc, 0, sizeof(proc)); | ||
1815 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
1816 | "Asked to return up to %llu records at position %llu\n", | ||
1817 | (unsigned long long) limit, | ||
1818 | (unsigned long long) zi->seq); | ||
1819 | proc.zi = zi; | ||
1820 | proc.limit = limit; | ||
1821 | start = GNUNET_TIME_absolute_get (); | ||
1822 | GNUNET_break (GNUNET_SYSERR != | ||
1823 | GSN_database->iterate_records (GSN_database->cls, | ||
1824 | (GNUNET_YES == GNUNET_is_zero ( | ||
1825 | &zi->zone)) | ||
1826 | ? NULL | ||
1827 | : &zi->zone, | ||
1828 | zi->seq, | ||
1829 | limit, | ||
1830 | &zone_iterate_proc, | ||
1831 | &proc)); | ||
1832 | duration = GNUNET_TIME_absolute_get_duration (start); | ||
1833 | duration = GNUNET_TIME_relative_divide (duration, limit - proc.limit); | ||
1834 | GNUNET_STATISTICS_set (statistics, | ||
1835 | "NAMESTORE iteration delay (μs/record)", | ||
1836 | duration.rel_value_us, | ||
1837 | GNUNET_NO); | ||
1838 | if (0 == proc.limit) | ||
1839 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
1840 | "Returned %llu results, more results available\n", | ||
1841 | (unsigned long long) limit); | ||
1842 | zi->send_end = (0 != proc.limit); | ||
1843 | if (0 == zi->cache_ops) | ||
1844 | zone_iteration_done_client_continue (zi); | ||
1845 | } | ||
1846 | |||
1847 | |||
1848 | /** | ||
1849 | * Handles a #GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_ITERATION_START message | ||
1850 | * | ||
1851 | * @param cls the client sending the message | ||
1852 | * @param zis_msg message from the client | ||
1853 | */ | ||
1854 | static void | ||
1855 | handle_iteration_start (void *cls, | ||
1856 | const struct ZoneIterationStartMessage *zis_msg) | ||
1857 | { | ||
1858 | struct NamestoreClient *nc = cls; | ||
1859 | struct ZoneIteration *zi; | ||
1860 | |||
1861 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
1862 | "Received ZONE_ITERATION_START message\n"); | ||
1863 | zi = GNUNET_new (struct ZoneIteration); | ||
1864 | zi->request_id = ntohl (zis_msg->gns_header.r_id); | ||
1865 | zi->offset = 0; | ||
1866 | zi->nc = nc; | ||
1867 | zi->zone = zis_msg->zone; | ||
1868 | |||
1869 | GNUNET_CONTAINER_DLL_insert (nc->op_head, nc->op_tail, zi); | ||
1870 | run_zone_iteration_round (zi, 1); | ||
1871 | } | ||
1872 | |||
1873 | |||
1874 | /** | ||
1875 | * Handles a #GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_ITERATION_STOP message | ||
1876 | * | ||
1877 | * @param cls the client sending the message | ||
1878 | * @param zis_msg message from the client | ||
1879 | */ | ||
1880 | static void | ||
1881 | handle_iteration_stop (void *cls, | ||
1882 | const struct ZoneIterationStopMessage *zis_msg) | ||
1883 | { | ||
1884 | struct NamestoreClient *nc = cls; | ||
1885 | struct ZoneIteration *zi; | ||
1886 | uint32_t rid; | ||
1887 | |||
1888 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
1889 | "Received ZONE_ITERATION_STOP message\n"); | ||
1890 | rid = ntohl (zis_msg->gns_header.r_id); | ||
1891 | for (zi = nc->op_head; NULL != zi; zi = zi->next) | ||
1892 | if (zi->request_id == rid) | ||
1893 | break; | ||
1894 | if (NULL == zi) | ||
1895 | { | ||
1896 | GNUNET_break (0); | ||
1897 | GNUNET_SERVICE_client_drop (nc->client); | ||
1898 | return; | ||
1899 | } | ||
1900 | GNUNET_CONTAINER_DLL_remove (nc->op_head, nc->op_tail, zi); | ||
1901 | GNUNET_free (zi); | ||
1902 | GNUNET_SERVICE_client_continue (nc->client); | ||
1903 | } | ||
1904 | |||
1905 | |||
1906 | /** | ||
1907 | * Handles a #GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_ITERATION_NEXT message | ||
1908 | * | ||
1909 | * @param cls the client sending the message | ||
1910 | * @param message message from the client | ||
1911 | */ | ||
1912 | static void | ||
1913 | handle_iteration_next (void *cls, | ||
1914 | const struct ZoneIterationNextMessage *zis_msg) | ||
1915 | { | ||
1916 | struct NamestoreClient *nc = cls; | ||
1917 | struct ZoneIteration *zi; | ||
1918 | uint32_t rid; | ||
1919 | uint64_t limit; | ||
1920 | |||
1921 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
1922 | "Received ZONE_ITERATION_NEXT message\n"); | ||
1923 | GNUNET_STATISTICS_update (statistics, | ||
1924 | "Iteration NEXT messages received", | ||
1925 | 1, | ||
1926 | GNUNET_NO); | ||
1927 | rid = ntohl (zis_msg->gns_header.r_id); | ||
1928 | limit = GNUNET_ntohll (zis_msg->limit); | ||
1929 | for (zi = nc->op_head; NULL != zi; zi = zi->next) | ||
1930 | if (zi->request_id == rid) | ||
1931 | break; | ||
1932 | if (NULL == zi) | ||
1933 | { | ||
1934 | GNUNET_break (0); | ||
1935 | GNUNET_SERVICE_client_drop (nc->client); | ||
1936 | return; | ||
1937 | } | ||
1938 | run_zone_iteration_round (zi, limit); | ||
1939 | } | ||
1940 | |||
1941 | |||
1942 | /** | ||
1943 | * Function called when the monitor is ready for more data, and we | ||
1944 | * should thus unblock PUT operations that were blocked on the | ||
1945 | * monitor not being ready. | ||
1946 | */ | ||
1947 | static void | ||
1948 | monitor_unblock (struct ZoneMonitor *zm) | ||
1949 | { | ||
1950 | struct StoreActivity *sa = sa_head; | ||
1951 | |||
1952 | while ((NULL != sa) && (zm->limit > zm->iteration_cnt)) | ||
1953 | { | ||
1954 | struct StoreActivity *sn = sa->next; | ||
1955 | |||
1956 | if (sa->zm_pos == zm) | ||
1957 | continue_store_activity (sa); | ||
1958 | sa = sn; | ||
1959 | } | ||
1960 | if (zm->limit > zm->iteration_cnt) | ||
1961 | { | ||
1962 | zm->sa_waiting = GNUNET_NO; | ||
1963 | if (NULL != zm->sa_wait_warning) | ||
1964 | { | ||
1965 | GNUNET_SCHEDULER_cancel (zm->sa_wait_warning); | ||
1966 | zm->sa_wait_warning = NULL; | ||
1967 | } | ||
1968 | } | ||
1969 | else if (GNUNET_YES == zm->sa_waiting) | ||
1970 | { | ||
1971 | zm->sa_waiting_start = GNUNET_TIME_absolute_get (); | ||
1972 | if (NULL != zm->sa_wait_warning) | ||
1973 | GNUNET_SCHEDULER_cancel (zm->sa_wait_warning); | ||
1974 | zm->sa_wait_warning = | ||
1975 | GNUNET_SCHEDULER_add_delayed (MONITOR_STALL_WARN_DELAY, | ||
1976 | &warn_monitor_slow, | ||
1977 | zm); | ||
1978 | } | ||
1979 | } | ||
1980 | |||
1981 | |||
1982 | /** | ||
1983 | * Send 'sync' message to zone monitor, we're now in sync. | ||
1984 | * | ||
1985 | * @param zm monitor that is now in sync | ||
1986 | */ | ||
1987 | static void | ||
1988 | monitor_sync (struct ZoneMonitor *zm) | ||
1989 | { | ||
1990 | struct GNUNET_MQ_Envelope *env; | ||
1991 | struct GNUNET_MessageHeader *sync; | ||
1992 | |||
1993 | env = GNUNET_MQ_msg (sync, GNUNET_MESSAGE_TYPE_NAMESTORE_MONITOR_SYNC); | ||
1994 | GNUNET_MQ_send (zm->nc->mq, env); | ||
1995 | /* mark iteration done */ | ||
1996 | zm->in_first_iteration = GNUNET_NO; | ||
1997 | zm->iteration_cnt = 0; | ||
1998 | if ((zm->limit > 0) && (zm->sa_waiting)) | ||
1999 | monitor_unblock (zm); | ||
2000 | } | ||
2001 | |||
2002 | |||
2003 | /** | ||
2004 | * Obtain the next datum during the zone monitor's zone initial iteration. | ||
2005 | * | ||
2006 | * @param cls zone monitor that does its initial iteration | ||
2007 | */ | ||
2008 | static void | ||
2009 | monitor_iteration_next (void *cls); | ||
2010 | |||
2011 | |||
2012 | /** | ||
2013 | * A #GNUNET_NAMESTORE_RecordIterator for monitors. | ||
2014 | * | ||
2015 | * @param cls a 'struct ZoneMonitor *' with information about the monitor | ||
2016 | * @param seq sequence number of the record, MUST NOT BE ZERO | ||
2017 | * @param zone_key zone key of the zone | ||
2018 | * @param name name | ||
2019 | * @param rd_count number of records in @a rd | ||
2020 | * @param rd array of records | ||
2021 | */ | ||
2022 | static void | ||
2023 | monitor_iterate_cb (void *cls, | ||
2024 | uint64_t seq, | ||
2025 | const struct GNUNET_IDENTITY_PrivateKey *zone_key, | ||
2026 | const char *name, | ||
2027 | unsigned int rd_count, | ||
2028 | const struct GNUNET_GNSRECORD_Data *rd) | ||
2029 | { | ||
2030 | struct ZoneMonitor *zm = cls; | ||
2031 | |||
2032 | GNUNET_assert (0 != seq); | ||
2033 | zm->seq = seq; | ||
2034 | GNUNET_assert (NULL != name); | ||
2035 | GNUNET_STATISTICS_update (statistics, | ||
2036 | "Monitor notifications sent", | ||
2037 | 1, | ||
2038 | GNUNET_NO); | ||
2039 | zm->limit--; | ||
2040 | zm->iteration_cnt--; | ||
2041 | send_lookup_response (zm->nc, 0, zone_key, name, rd_count, rd); | ||
2042 | if ((0 == zm->iteration_cnt) && (0 != zm->limit)) | ||
2043 | { | ||
2044 | /* We are done with the current iteration batch, AND the | ||
2045 | client would right now accept more, so go again! */ | ||
2046 | GNUNET_assert (NULL == zm->task); | ||
2047 | zm->task = GNUNET_SCHEDULER_add_now (&monitor_iteration_next, zm); | ||
2048 | } | ||
2049 | } | ||
2050 | |||
2051 | |||
2052 | /** | ||
2053 | * Handles a #GNUNET_MESSAGE_TYPE_NAMESTORE_MONITOR_START message | ||
2054 | * | ||
2055 | * @param cls the client sending the message | ||
2056 | * @param zis_msg message from the client | ||
2057 | */ | ||
2058 | static void | ||
2059 | handle_monitor_start (void *cls, const struct ZoneMonitorStartMessage *zis_msg) | ||
2060 | { | ||
2061 | struct NamestoreClient *nc = cls; | ||
2062 | struct ZoneMonitor *zm; | ||
2063 | |||
2064 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received ZONE_MONITOR_START message\n"); | ||
2065 | zm = GNUNET_new (struct ZoneMonitor); | ||
2066 | zm->nc = nc; | ||
2067 | zm->zone = zis_msg->zone; | ||
2068 | zm->limit = 1; | ||
2069 | zm->in_first_iteration = (GNUNET_YES == ntohl (zis_msg->iterate_first)); | ||
2070 | GNUNET_CONTAINER_DLL_insert (monitor_head, monitor_tail, zm); | ||
2071 | GNUNET_SERVICE_client_mark_monitor (nc->client); | ||
2072 | GNUNET_SERVICE_client_continue (nc->client); | ||
2073 | GNUNET_notification_context_add (monitor_nc, nc->mq); | ||
2074 | if (zm->in_first_iteration) | ||
2075 | zm->task = GNUNET_SCHEDULER_add_now (&monitor_iteration_next, zm); | ||
2076 | else | ||
2077 | monitor_sync (zm); | ||
2078 | } | ||
2079 | |||
2080 | |||
2081 | /** | ||
2082 | * Obtain the next datum during the zone monitor's zone initial iteration. | ||
2083 | * | ||
2084 | * @param cls zone monitor that does its initial iteration | ||
2085 | */ | ||
2086 | static void | ||
2087 | monitor_iteration_next (void *cls) | ||
2088 | { | ||
2089 | struct ZoneMonitor *zm = cls; | ||
2090 | int ret; | ||
2091 | |||
2092 | zm->task = NULL; | ||
2093 | GNUNET_assert (0 == zm->iteration_cnt); | ||
2094 | if (zm->limit > 16) | ||
2095 | zm->iteration_cnt = zm->limit / 2; /* leave half for monitor events */ | ||
2096 | else | ||
2097 | zm->iteration_cnt = zm->limit; /* use it all */ | ||
2098 | ret = GSN_database->iterate_records (GSN_database->cls, | ||
2099 | (GNUNET_YES == GNUNET_is_zero ( | ||
2100 | &zm->zone)) | ||
2101 | ? NULL | ||
2102 | : &zm->zone, | ||
2103 | zm->seq, | ||
2104 | zm->iteration_cnt, | ||
2105 | &monitor_iterate_cb, | ||
2106 | zm); | ||
2107 | if (GNUNET_SYSERR == ret) | ||
2108 | { | ||
2109 | GNUNET_SERVICE_client_drop (zm->nc->client); | ||
2110 | return; | ||
2111 | } | ||
2112 | if (GNUNET_NO == ret) | ||
2113 | { | ||
2114 | /* empty zone */ | ||
2115 | monitor_sync (zm); | ||
2116 | return; | ||
2117 | } | ||
2118 | } | ||
2119 | |||
2120 | |||
2121 | /** | ||
2122 | * Handles a #GNUNET_MESSAGE_TYPE_NAMESTORE_MONITOR_NEXT message | ||
2123 | * | ||
2124 | * @param cls the client sending the message | ||
2125 | * @param nm message from the client | ||
2126 | */ | ||
2127 | static void | ||
2128 | handle_monitor_next (void *cls, const struct ZoneMonitorNextMessage *nm) | ||
2129 | { | ||
2130 | struct NamestoreClient *nc = cls; | ||
2131 | struct ZoneMonitor *zm; | ||
2132 | uint64_t inc; | ||
2133 | |||
2134 | inc = GNUNET_ntohll (nm->limit); | ||
2135 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
2136 | "Received ZONE_MONITOR_NEXT message with limit %llu\n", | ||
2137 | (unsigned long long) inc); | ||
2138 | for (zm = monitor_head; NULL != zm; zm = zm->next) | ||
2139 | if (zm->nc == nc) | ||
2140 | break; | ||
2141 | if (NULL == zm) | ||
2142 | { | ||
2143 | GNUNET_break (0); | ||
2144 | GNUNET_SERVICE_client_drop (nc->client); | ||
2145 | return; | ||
2146 | } | ||
2147 | GNUNET_SERVICE_client_continue (nc->client); | ||
2148 | if (zm->limit + inc < zm->limit) | ||
2149 | { | ||
2150 | GNUNET_break (0); | ||
2151 | GNUNET_SERVICE_client_drop (nc->client); | ||
2152 | return; | ||
2153 | } | ||
2154 | zm->limit += inc; | ||
2155 | if ((zm->in_first_iteration) && (zm->limit == inc)) | ||
2156 | { | ||
2157 | /* We are still iterating, and the previous iteration must | ||
2158 | have stopped due to the client's limit, so continue it! */ | ||
2159 | GNUNET_assert (NULL == zm->task); | ||
2160 | zm->task = GNUNET_SCHEDULER_add_now (&monitor_iteration_next, zm); | ||
2161 | } | ||
2162 | GNUNET_assert (zm->iteration_cnt <= zm->limit); | ||
2163 | if ((zm->limit > zm->iteration_cnt) && (zm->sa_waiting)) | ||
2164 | { | ||
2165 | monitor_unblock (zm); | ||
2166 | } | ||
2167 | else if (GNUNET_YES == zm->sa_waiting) | ||
2168 | { | ||
2169 | if (NULL != zm->sa_wait_warning) | ||
2170 | GNUNET_SCHEDULER_cancel (zm->sa_wait_warning); | ||
2171 | zm->sa_waiting_start = GNUNET_TIME_absolute_get (); | ||
2172 | zm->sa_wait_warning = | ||
2173 | GNUNET_SCHEDULER_add_delayed (MONITOR_STALL_WARN_DELAY, | ||
2174 | &warn_monitor_slow, | ||
2175 | zm); | ||
2176 | } | ||
2177 | } | ||
2178 | |||
2179 | |||
2180 | /** | ||
2181 | * Process namestore requests. | ||
2182 | * | ||
2183 | * @param cls closure | ||
2184 | * @param cfg configuration to use | ||
2185 | * @param service the initialized service | ||
2186 | */ | ||
2187 | static void | ||
2188 | run (void *cls, | ||
2189 | const struct GNUNET_CONFIGURATION_Handle *cfg, | ||
2190 | struct GNUNET_SERVICE_Handle *service) | ||
2191 | { | ||
2192 | char *database; | ||
2193 | |||
2194 | (void) cls; | ||
2195 | (void) service; | ||
2196 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Starting namestore service\n"); | ||
2197 | cache_keys = | ||
2198 | GNUNET_CONFIGURATION_get_value_yesno (cfg, "namestore", "CACHE_KEYS"); | ||
2199 | disable_namecache = | ||
2200 | GNUNET_CONFIGURATION_get_value_yesno (cfg, "namecache", "DISABLE"); | ||
2201 | GSN_cfg = cfg; | ||
2202 | monitor_nc = GNUNET_notification_context_create (1); | ||
2203 | if (GNUNET_YES != disable_namecache) | ||
2204 | { | ||
2205 | namecache = GNUNET_NAMECACHE_connect (cfg); | ||
2206 | GNUNET_assert (NULL != namecache); | ||
2207 | } | ||
2208 | /* Loading database plugin */ | ||
2209 | if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_string (cfg, | ||
2210 | "namestore", | ||
2211 | "database", | ||
2212 | &database)) | ||
2213 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "No database backend configured\n"); | ||
2214 | |||
2215 | GNUNET_asprintf (&db_lib_name, "libgnunet_plugin_namestore_%s", database); | ||
2216 | GSN_database = GNUNET_PLUGIN_load (db_lib_name, (void *) GSN_cfg); | ||
2217 | GNUNET_free (database); | ||
2218 | statistics = GNUNET_STATISTICS_create ("namestore", cfg); | ||
2219 | GNUNET_SCHEDULER_add_shutdown (&cleanup_task, NULL); | ||
2220 | if (NULL == GSN_database) | ||
2221 | { | ||
2222 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
2223 | "Could not load database backend `%s'\n", | ||
2224 | db_lib_name); | ||
2225 | GNUNET_SCHEDULER_shutdown (); | ||
2226 | return; | ||
2227 | } | ||
2228 | } | ||
2229 | |||
2230 | |||
2231 | /** | ||
2232 | * Define "main" method using service macro. | ||
2233 | */ | ||
2234 | GNUNET_SERVICE_MAIN ( | ||
2235 | "namestore", | ||
2236 | GNUNET_SERVICE_OPTION_NONE, | ||
2237 | &run, | ||
2238 | &client_connect_cb, | ||
2239 | &client_disconnect_cb, | ||
2240 | NULL, | ||
2241 | GNUNET_MQ_hd_var_size (record_store, | ||
2242 | GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_STORE, | ||
2243 | struct RecordStoreMessage, | ||
2244 | NULL), | ||
2245 | GNUNET_MQ_hd_var_size (record_lookup, | ||
2246 | GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_LOOKUP, | ||
2247 | struct LabelLookupMessage, | ||
2248 | NULL), | ||
2249 | GNUNET_MQ_hd_fixed_size (zone_to_name, | ||
2250 | GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_TO_NAME, | ||
2251 | struct ZoneToNameMessage, | ||
2252 | NULL), | ||
2253 | GNUNET_MQ_hd_fixed_size (iteration_start, | ||
2254 | GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_ITERATION_START, | ||
2255 | struct ZoneIterationStartMessage, | ||
2256 | NULL), | ||
2257 | GNUNET_MQ_hd_fixed_size (iteration_next, | ||
2258 | GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_ITERATION_NEXT, | ||
2259 | struct ZoneIterationNextMessage, | ||
2260 | NULL), | ||
2261 | GNUNET_MQ_hd_fixed_size (iteration_stop, | ||
2262 | GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_ITERATION_STOP, | ||
2263 | struct ZoneIterationStopMessage, | ||
2264 | NULL), | ||
2265 | GNUNET_MQ_hd_fixed_size (monitor_start, | ||
2266 | GNUNET_MESSAGE_TYPE_NAMESTORE_MONITOR_START, | ||
2267 | struct ZoneMonitorStartMessage, | ||
2268 | NULL), | ||
2269 | GNUNET_MQ_hd_fixed_size (monitor_next, | ||
2270 | GNUNET_MESSAGE_TYPE_NAMESTORE_MONITOR_NEXT, | ||
2271 | struct ZoneMonitorNextMessage, | ||
2272 | NULL), | ||
2273 | GNUNET_MQ_handler_end ()); | ||
2274 | |||
2275 | |||
2276 | /* end of gnunet-service-namestore.c */ | ||
diff --git a/src/namestore/gnunet-zoneimport.c b/src/namestore/gnunet-zoneimport.c deleted file mode 100644 index 68b43a016..000000000 --- a/src/namestore/gnunet-zoneimport.c +++ /dev/null | |||
@@ -1,1884 +0,0 @@ | |||
1 | /* | ||
2 | This file is part of GNUnet | ||
3 | Copyright (C) 2018 GNUnet e.V. | ||
4 | |||
5 | GNUnet is free software: you can redistribute it and/or modify it | ||
6 | under the terms of the GNU Affero General Public License as published | ||
7 | by the Free Software Foundation, either version 3 of the License, | ||
8 | or (at your option) any later version. | ||
9 | |||
10 | GNUnet is distributed in the hope that it will be useful, but | ||
11 | WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
13 | Affero General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU Affero General Public License | ||
16 | along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
17 | |||
18 | SPDX-License-Identifier: AGPL3.0-or-later | ||
19 | */ | ||
20 | /** | ||
21 | * @file src/namestore/gnunet-zoneimport.c | ||
22 | * @brief import a DNS zone for publication in GNS, incremental | ||
23 | * @author Christian Grothoff | ||
24 | */ | ||
25 | #include "platform.h" | ||
26 | #include <gnunet_util_lib.h> | ||
27 | #include <gnunet_dnsstub_lib.h> | ||
28 | #include <gnunet_dnsparser_lib.h> | ||
29 | #include <gnunet_gnsrecord_lib.h> | ||
30 | #include <gnunet_namestore_service.h> | ||
31 | #include <gnunet_statistics_service.h> | ||
32 | #include <gnunet_identity_service.h> | ||
33 | |||
34 | |||
35 | /** | ||
36 | * Maximum number of queries pending at the same time. | ||
37 | */ | ||
38 | #define THRESH 100 | ||
39 | |||
40 | /** | ||
41 | * TIME_THRESH is in usecs. How quickly do we submit fresh queries. | ||
42 | * Used as an additional throttle. | ||
43 | */ | ||
44 | #define TIME_THRESH 10 | ||
45 | |||
46 | /** | ||
47 | * How often do we retry a query before giving up for good? | ||
48 | */ | ||
49 | #define MAX_RETRIES 5 | ||
50 | |||
51 | /** | ||
52 | * How many DNS requests do we at most issue in rapid series? | ||
53 | */ | ||
54 | #define MAX_SERIES 10 | ||
55 | |||
56 | /** | ||
57 | * How long do we wait at least between series of requests? | ||
58 | */ | ||
59 | #define SERIES_DELAY \ | ||
60 | GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MICROSECONDS, 10) | ||
61 | |||
62 | /** | ||
63 | * How long do DNS records have to last at least after being imported? | ||
64 | */ | ||
65 | static struct GNUNET_TIME_Relative minimum_expiration_time; | ||
66 | |||
67 | /** | ||
68 | * How many requests do we request from NAMESTORE in one batch | ||
69 | * during our initial iteration? | ||
70 | */ | ||
71 | #define NS_BATCH_SIZE 1024 | ||
72 | |||
73 | /** | ||
74 | * Some zones may include authoritative records for other | ||
75 | * zones, such as foo.com.uk or bar.com.fr. As for GNS | ||
76 | * each dot represents a zone cut, we then need to create a | ||
77 | * zone on-the-fly to capture those records properly. | ||
78 | */ | ||
79 | struct Zone | ||
80 | { | ||
81 | /** | ||
82 | * Kept in a DLL. | ||
83 | */ | ||
84 | struct Zone *next; | ||
85 | |||
86 | /** | ||
87 | * Kept in a DLL. | ||
88 | */ | ||
89 | struct Zone *prev; | ||
90 | |||
91 | /** | ||
92 | * Domain of the zone (i.e. "fr" or "com.fr") | ||
93 | */ | ||
94 | char *domain; | ||
95 | |||
96 | /** | ||
97 | * Private key of the zone. | ||
98 | */ | ||
99 | struct GNUNET_IDENTITY_PrivateKey key; | ||
100 | }; | ||
101 | |||
102 | |||
103 | /** | ||
104 | * Record for the request to be stored by GNS. | ||
105 | */ | ||
106 | struct Record | ||
107 | { | ||
108 | /** | ||
109 | * Kept in a DLL. | ||
110 | */ | ||
111 | struct Record *next; | ||
112 | |||
113 | /** | ||
114 | * Kept in a DLL. | ||
115 | */ | ||
116 | struct Record *prev; | ||
117 | |||
118 | /** | ||
119 | * GNS record. | ||
120 | */ | ||
121 | struct GNUNET_GNSRECORD_Data grd; | ||
122 | }; | ||
123 | |||
124 | |||
125 | /** | ||
126 | * Request we should make. We keep this struct in memory per request, | ||
127 | * thus optimizing it is crucial for the overall memory consumption of | ||
128 | * the zone importer. | ||
129 | */ | ||
130 | struct Request | ||
131 | { | ||
132 | /** | ||
133 | * Requests are kept in a heap while waiting to be resolved. | ||
134 | */ | ||
135 | struct GNUNET_CONTAINER_HeapNode *hn; | ||
136 | |||
137 | /** | ||
138 | * Active requests are kept in a DLL. | ||
139 | */ | ||
140 | struct Request *next; | ||
141 | |||
142 | /** | ||
143 | * Active requests are kept in a DLL. | ||
144 | */ | ||
145 | struct Request *prev; | ||
146 | |||
147 | /** | ||
148 | * Head of records that should be published in GNS for | ||
149 | * this hostname. | ||
150 | */ | ||
151 | struct Record *rec_head; | ||
152 | |||
153 | /** | ||
154 | * Tail of records that should be published in GNS for | ||
155 | * this hostname. | ||
156 | */ | ||
157 | struct Record *rec_tail; | ||
158 | |||
159 | /** | ||
160 | * Socket used to make the request, NULL if not active. | ||
161 | */ | ||
162 | struct GNUNET_DNSSTUB_RequestSocket *rs; | ||
163 | |||
164 | /** | ||
165 | * Hostname we are resolving, allocated at the end of | ||
166 | * this struct (optimizing memory consumption by reducing | ||
167 | * total number of allocations). | ||
168 | */ | ||
169 | char *hostname; | ||
170 | |||
171 | /** | ||
172 | * Namestore operation pending for this record. | ||
173 | */ | ||
174 | struct GNUNET_NAMESTORE_QueueEntry *qe; | ||
175 | |||
176 | /** | ||
177 | * Zone responsible for this request. | ||
178 | */ | ||
179 | const struct Zone *zone; | ||
180 | |||
181 | /** | ||
182 | * At what time does the (earliest) of the returned records | ||
183 | * for this name expire? At this point, we need to re-fetch | ||
184 | * the record. | ||
185 | */ | ||
186 | struct GNUNET_TIME_Absolute expires; | ||
187 | |||
188 | /** | ||
189 | * While we are fetching the record, the value is set to the | ||
190 | * starting time of the DNS operation. While doing a | ||
191 | * NAMESTORE store, again set to the start time of the | ||
192 | * NAMESTORE operation. | ||
193 | */ | ||
194 | struct GNUNET_TIME_Absolute op_start_time; | ||
195 | |||
196 | /** | ||
197 | * How often did we issue this query? (And failed, reset | ||
198 | * to zero once we were successful.) | ||
199 | */ | ||
200 | unsigned int issue_num; | ||
201 | |||
202 | /** | ||
203 | * random 16-bit DNS query identifier. | ||
204 | */ | ||
205 | uint16_t id; | ||
206 | }; | ||
207 | |||
208 | |||
209 | /** | ||
210 | * Command-line argument specifying desired size of the hash map with | ||
211 | * all of our pending names. Usually, we use an automatically growing | ||
212 | * map, but this is only OK up to about a million entries. Above that | ||
213 | * number, the user must explicitly specify the size at startup. | ||
214 | */ | ||
215 | static unsigned int map_size = 1024; | ||
216 | |||
217 | /** | ||
218 | * Handle to the identity service. | ||
219 | */ | ||
220 | static struct GNUNET_IDENTITY_Handle *id; | ||
221 | |||
222 | /** | ||
223 | * Namestore handle. | ||
224 | */ | ||
225 | static struct GNUNET_NAMESTORE_Handle *ns; | ||
226 | |||
227 | /** | ||
228 | * Handle to the statistics service. | ||
229 | */ | ||
230 | static struct GNUNET_STATISTICS_Handle *stats; | ||
231 | |||
232 | /** | ||
233 | * Context for DNS resolution. | ||
234 | */ | ||
235 | static struct GNUNET_DNSSTUB_Context *ctx; | ||
236 | |||
237 | /** | ||
238 | * The number of DNS queries that are outstanding | ||
239 | */ | ||
240 | static unsigned int pending; | ||
241 | |||
242 | /** | ||
243 | * The number of NAMESTORE record store operations that are outstanding | ||
244 | */ | ||
245 | static unsigned int pending_rs; | ||
246 | |||
247 | /** | ||
248 | * Number of lookups we performed overall. | ||
249 | */ | ||
250 | static unsigned int lookups; | ||
251 | |||
252 | /** | ||
253 | * Number of records we had cached. | ||
254 | */ | ||
255 | static unsigned int cached; | ||
256 | |||
257 | /** | ||
258 | * How many hostnames did we reject (malformed). | ||
259 | */ | ||
260 | static unsigned int rejects; | ||
261 | |||
262 | /** | ||
263 | * Number of lookups that failed. | ||
264 | */ | ||
265 | static unsigned int failures; | ||
266 | |||
267 | /** | ||
268 | * Number of records we found. | ||
269 | */ | ||
270 | static unsigned int records; | ||
271 | |||
272 | /** | ||
273 | * Number of record sets given to namestore. | ||
274 | */ | ||
275 | static unsigned int record_sets; | ||
276 | |||
277 | /** | ||
278 | * Heap of all requests to perform, sorted by | ||
279 | * the time we should next do the request (i.e. by expires). | ||
280 | */ | ||
281 | static struct GNUNET_CONTAINER_Heap *req_heap; | ||
282 | |||
283 | /** | ||
284 | * Active requests are kept in a DLL. | ||
285 | */ | ||
286 | static struct Request *req_head; | ||
287 | |||
288 | /** | ||
289 | * Active requests are kept in a DLL. | ||
290 | */ | ||
291 | static struct Request *req_tail; | ||
292 | |||
293 | /** | ||
294 | * Main task. | ||
295 | */ | ||
296 | static struct GNUNET_SCHEDULER_Task *t; | ||
297 | |||
298 | /** | ||
299 | * Hash map of requests for which we may still get a response from | ||
300 | * the namestore. Set to NULL once the initial namestore iteration | ||
301 | * is done. | ||
302 | */ | ||
303 | static struct GNUNET_CONTAINER_MultiHashMap *ns_pending; | ||
304 | |||
305 | /** | ||
306 | * Current zone iteration handle. | ||
307 | */ | ||
308 | static struct GNUNET_NAMESTORE_ZoneIterator *zone_it; | ||
309 | |||
310 | /** | ||
311 | * Head of list of zones we are managing. | ||
312 | */ | ||
313 | static struct Zone *zone_head; | ||
314 | |||
315 | /** | ||
316 | * Tail of list of zones we are managing. | ||
317 | */ | ||
318 | static struct Zone *zone_tail; | ||
319 | |||
320 | /** | ||
321 | * After how many more results must #ns_lookup_result_cb() ask | ||
322 | * the namestore for more? | ||
323 | */ | ||
324 | static uint64_t ns_iterator_trigger_next; | ||
325 | |||
326 | /** | ||
327 | * Number of DNS requests counted in latency total. | ||
328 | */ | ||
329 | static uint64_t total_dns_latency_cnt; | ||
330 | |||
331 | /** | ||
332 | * Sum of DNS latencies observed. | ||
333 | */ | ||
334 | static struct GNUNET_TIME_Relative total_dns_latency; | ||
335 | |||
336 | /** | ||
337 | * Number of records processed (DNS lookup, no NAMESTORE) in total. | ||
338 | */ | ||
339 | static uint64_t total_reg_proc_dns; | ||
340 | |||
341 | /** | ||
342 | * Number of records processed (DNS lookup, with NAMESTORE) in total. | ||
343 | */ | ||
344 | static uint64_t total_reg_proc_dns_ns; | ||
345 | |||
346 | /** | ||
347 | * Start time of the regular processing. | ||
348 | */ | ||
349 | static struct GNUNET_TIME_Absolute start_time_reg_proc; | ||
350 | |||
351 | /** | ||
352 | * Last time we worked before going idle. | ||
353 | */ | ||
354 | static struct GNUNET_TIME_Absolute sleep_time_reg_proc; | ||
355 | |||
356 | /** | ||
357 | * Time we slept just waiting for work. | ||
358 | */ | ||
359 | static struct GNUNET_TIME_Relative idle_time; | ||
360 | |||
361 | |||
362 | /** | ||
363 | * Callback for #for_all_records | ||
364 | * | ||
365 | * @param cls closure | ||
366 | * @param rec a DNS record | ||
367 | */ | ||
368 | typedef void (*RecordProcessor) (void *cls, | ||
369 | const struct GNUNET_DNSPARSER_Record *rec); | ||
370 | |||
371 | |||
372 | /** | ||
373 | * Call @a rp for each record in @a p, regardless of | ||
374 | * what response section it is in. | ||
375 | * | ||
376 | * @param p packet from DNS | ||
377 | * @param rp function to call | ||
378 | * @param rp_cls closure for @a rp | ||
379 | */ | ||
380 | static void | ||
381 | for_all_records (const struct GNUNET_DNSPARSER_Packet *p, | ||
382 | RecordProcessor rp, | ||
383 | void *rp_cls) | ||
384 | { | ||
385 | for (unsigned int i = 0; i < p->num_answers; i++) | ||
386 | { | ||
387 | struct GNUNET_DNSPARSER_Record *rs = &p->answers[i]; | ||
388 | |||
389 | rp (rp_cls, rs); | ||
390 | } | ||
391 | for (unsigned int i = 0; i < p->num_authority_records; i++) | ||
392 | { | ||
393 | struct GNUNET_DNSPARSER_Record *rs = &p->authority_records[i]; | ||
394 | |||
395 | rp (rp_cls, rs); | ||
396 | } | ||
397 | for (unsigned int i = 0; i < p->num_additional_records; i++) | ||
398 | { | ||
399 | struct GNUNET_DNSPARSER_Record *rs = &p->additional_records[i]; | ||
400 | |||
401 | rp (rp_cls, rs); | ||
402 | } | ||
403 | } | ||
404 | |||
405 | |||
406 | /** | ||
407 | * Return just the label of the hostname in @a req. | ||
408 | * | ||
409 | * @param req request to process hostname of | ||
410 | * @return statically allocated pointer to the label, | ||
411 | * overwritten upon the next request! | ||
412 | */ | ||
413 | static const char * | ||
414 | get_label (struct Request *req) | ||
415 | { | ||
416 | static char label[64]; | ||
417 | const char *dot; | ||
418 | |||
419 | dot = strchr (req->hostname, (unsigned char) '.'); | ||
420 | if (NULL == dot) | ||
421 | { | ||
422 | GNUNET_break (0); | ||
423 | return NULL; | ||
424 | } | ||
425 | if (((size_t) (dot - req->hostname)) >= sizeof(label)) | ||
426 | { | ||
427 | GNUNET_break (0); | ||
428 | return NULL; | ||
429 | } | ||
430 | GNUNET_memcpy (label, req->hostname, dot - req->hostname); | ||
431 | label[dot - req->hostname] = '\0'; | ||
432 | return label; | ||
433 | } | ||
434 | |||
435 | |||
436 | /** | ||
437 | * Build DNS query for @a hostname. | ||
438 | * | ||
439 | * @param hostname host to build query for | ||
440 | * @param raw_size[out] number of bytes in the query | ||
441 | * @return NULL on error, otherwise pointer to statically (!) | ||
442 | * allocated query buffer | ||
443 | */ | ||
444 | static void * | ||
445 | build_dns_query (struct Request *req, size_t *raw_size) | ||
446 | { | ||
447 | static char raw[512]; | ||
448 | char *rawp; | ||
449 | struct GNUNET_DNSPARSER_Packet p; | ||
450 | struct GNUNET_DNSPARSER_Query q; | ||
451 | int ret; | ||
452 | |||
453 | q.name = (char *) req->hostname; | ||
454 | q.type = GNUNET_DNSPARSER_TYPE_NS; | ||
455 | q.dns_traffic_class = GNUNET_TUN_DNS_CLASS_INTERNET; | ||
456 | |||
457 | memset (&p, 0, sizeof(p)); | ||
458 | p.num_queries = 1; | ||
459 | p.queries = &q; | ||
460 | p.id = req->id; | ||
461 | ret = GNUNET_DNSPARSER_pack (&p, UINT16_MAX, &rawp, raw_size); | ||
462 | if (GNUNET_OK != ret) | ||
463 | { | ||
464 | if (GNUNET_NO == ret) | ||
465 | GNUNET_free (rawp); | ||
466 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
467 | "Failed to pack query for hostname `%s'\n", | ||
468 | req->hostname); | ||
469 | rejects++; | ||
470 | return NULL; | ||
471 | } | ||
472 | if (*raw_size > sizeof(raw)) | ||
473 | { | ||
474 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
475 | "Failed to pack query for hostname `%s'\n", | ||
476 | req->hostname); | ||
477 | rejects++; | ||
478 | GNUNET_break (0); | ||
479 | GNUNET_free (rawp); | ||
480 | return NULL; | ||
481 | } | ||
482 | GNUNET_memcpy (raw, rawp, *raw_size); | ||
483 | GNUNET_free (rawp); | ||
484 | return raw; | ||
485 | } | ||
486 | |||
487 | |||
488 | /** | ||
489 | * Free records associated with @a req. | ||
490 | * | ||
491 | * @param req request to free records of | ||
492 | */ | ||
493 | static void | ||
494 | free_records (struct Request *req) | ||
495 | { | ||
496 | struct Record *rec; | ||
497 | |||
498 | /* Free records */ | ||
499 | while (NULL != (rec = req->rec_head)) | ||
500 | { | ||
501 | GNUNET_CONTAINER_DLL_remove (req->rec_head, req->rec_tail, rec); | ||
502 | GNUNET_free (rec); | ||
503 | } | ||
504 | } | ||
505 | |||
506 | |||
507 | /** | ||
508 | * Free @a req and data structures reachable from it. | ||
509 | * | ||
510 | * @param req request to free | ||
511 | */ | ||
512 | static void | ||
513 | free_request (struct Request *req) | ||
514 | { | ||
515 | free_records (req); | ||
516 | GNUNET_free (req); | ||
517 | } | ||
518 | |||
519 | |||
520 | /** | ||
521 | * Process as many requests as possible from the queue. | ||
522 | * | ||
523 | * @param cls NULL | ||
524 | */ | ||
525 | static void | ||
526 | process_queue (void *cls); | ||
527 | |||
528 | |||
529 | /** | ||
530 | * Insert @a req into DLL sorted by next fetch time. | ||
531 | * | ||
532 | * @param req request to insert into #req_heap | ||
533 | */ | ||
534 | static void | ||
535 | insert_sorted (struct Request *req) | ||
536 | { | ||
537 | req->hn = | ||
538 | GNUNET_CONTAINER_heap_insert (req_heap, req, req->expires.abs_value_us); | ||
539 | if (req == GNUNET_CONTAINER_heap_peek (req_heap)) | ||
540 | { | ||
541 | if (NULL != t) | ||
542 | GNUNET_SCHEDULER_cancel (t); | ||
543 | sleep_time_reg_proc = GNUNET_TIME_absolute_get (); | ||
544 | t = GNUNET_SCHEDULER_add_at (req->expires, &process_queue, NULL); | ||
545 | } | ||
546 | } | ||
547 | |||
548 | |||
549 | /** | ||
550 | * Add record to the GNS record set for @a req. | ||
551 | * | ||
552 | * @param req the request to expand GNS record set for | ||
553 | * @param type type to use | ||
554 | * @param expiration_time when should @a rec expire | ||
555 | * @param data raw data to store | ||
556 | * @param data_len number of bytes in @a data | ||
557 | */ | ||
558 | static void | ||
559 | add_record (struct Request *req, | ||
560 | uint32_t type, | ||
561 | struct GNUNET_TIME_Absolute expiration_time, | ||
562 | const void *data, | ||
563 | size_t data_len) | ||
564 | { | ||
565 | struct Record *rec; | ||
566 | |||
567 | rec = GNUNET_malloc (sizeof(struct Record) + data_len); | ||
568 | rec->grd.data = &rec[1]; | ||
569 | rec->grd.expiration_time = expiration_time.abs_value_us; | ||
570 | rec->grd.data_size = data_len; | ||
571 | rec->grd.record_type = type; | ||
572 | rec->grd.flags = GNUNET_GNSRECORD_RF_NONE; | ||
573 | GNUNET_memcpy (&rec[1], data, data_len); | ||
574 | GNUNET_CONTAINER_DLL_insert (req->rec_head, req->rec_tail, rec); | ||
575 | } | ||
576 | |||
577 | |||
578 | /** | ||
579 | * Closure for #check_for_glue. | ||
580 | */ | ||
581 | struct GlueClosure | ||
582 | { | ||
583 | /** | ||
584 | * Overall request we are processing. | ||
585 | */ | ||
586 | struct Request *req; | ||
587 | |||
588 | /** | ||
589 | * NS name we are looking for glue for. | ||
590 | */ | ||
591 | const char *ns; | ||
592 | |||
593 | /** | ||
594 | * Set to #GNUNET_YES if glue was found. | ||
595 | */ | ||
596 | int found; | ||
597 | }; | ||
598 | |||
599 | |||
600 | /** | ||
601 | * Try to find glue records for a given NS record. | ||
602 | * | ||
603 | * @param cls a `struct GlueClosure *` | ||
604 | * @param rec record that may contain glue information | ||
605 | */ | ||
606 | static void | ||
607 | check_for_glue (void *cls, const struct GNUNET_DNSPARSER_Record *rec) | ||
608 | { | ||
609 | struct GlueClosure *gc = cls; | ||
610 | char dst[65536]; | ||
611 | size_t dst_len; | ||
612 | size_t off; | ||
613 | char ip[INET6_ADDRSTRLEN + 1]; | ||
614 | socklen_t ip_size = (socklen_t) sizeof(ip); | ||
615 | struct GNUNET_TIME_Absolute expiration_time; | ||
616 | struct GNUNET_TIME_Relative left; | ||
617 | |||
618 | if (0 != strcasecmp (rec->name, gc->ns)) | ||
619 | return; | ||
620 | expiration_time = rec->expiration_time; | ||
621 | left = GNUNET_TIME_absolute_get_remaining (expiration_time); | ||
622 | if (0 == left.rel_value_us) | ||
623 | return; /* ignore expired glue records */ | ||
624 | /* if expiration window is too short, bump it to configured minimum */ | ||
625 | if (left.rel_value_us < minimum_expiration_time.rel_value_us) | ||
626 | expiration_time = | ||
627 | GNUNET_TIME_relative_to_absolute (minimum_expiration_time); | ||
628 | dst_len = sizeof(dst); | ||
629 | off = 0; | ||
630 | switch (rec->type) | ||
631 | { | ||
632 | case GNUNET_DNSPARSER_TYPE_A: | ||
633 | if (sizeof(struct in_addr) != rec->data.raw.data_len) | ||
634 | { | ||
635 | GNUNET_break (0); | ||
636 | return; | ||
637 | } | ||
638 | if (NULL == inet_ntop (AF_INET, rec->data.raw.data, ip, ip_size)) | ||
639 | { | ||
640 | GNUNET_break (0); | ||
641 | return; | ||
642 | } | ||
643 | if ((GNUNET_OK == GNUNET_DNSPARSER_builder_add_name (dst, | ||
644 | dst_len, | ||
645 | &off, | ||
646 | gc->req->hostname)) && | ||
647 | (GNUNET_OK == | ||
648 | GNUNET_DNSPARSER_builder_add_name (dst, dst_len, &off, ip))) | ||
649 | { | ||
650 | add_record (gc->req, | ||
651 | GNUNET_GNSRECORD_TYPE_GNS2DNS, | ||
652 | expiration_time, | ||
653 | dst, | ||
654 | off); | ||
655 | gc->found = GNUNET_YES; | ||
656 | } | ||
657 | break; | ||
658 | |||
659 | case GNUNET_DNSPARSER_TYPE_AAAA: | ||
660 | if (sizeof(struct in6_addr) != rec->data.raw.data_len) | ||
661 | { | ||
662 | GNUNET_break (0); | ||
663 | return; | ||
664 | } | ||
665 | if (NULL == inet_ntop (AF_INET6, rec->data.raw.data, ip, ip_size)) | ||
666 | { | ||
667 | GNUNET_break (0); | ||
668 | return; | ||
669 | } | ||
670 | if ((GNUNET_OK == GNUNET_DNSPARSER_builder_add_name (dst, | ||
671 | dst_len, | ||
672 | &off, | ||
673 | gc->req->hostname)) && | ||
674 | (GNUNET_OK == | ||
675 | GNUNET_DNSPARSER_builder_add_name (dst, dst_len, &off, ip))) | ||
676 | { | ||
677 | add_record (gc->req, | ||
678 | GNUNET_GNSRECORD_TYPE_GNS2DNS, | ||
679 | expiration_time, | ||
680 | dst, | ||
681 | off); | ||
682 | gc->found = GNUNET_YES; | ||
683 | } | ||
684 | break; | ||
685 | |||
686 | case GNUNET_DNSPARSER_TYPE_CNAME: | ||
687 | if ((GNUNET_OK == GNUNET_DNSPARSER_builder_add_name (dst, | ||
688 | dst_len, | ||
689 | &off, | ||
690 | gc->req->hostname)) && | ||
691 | (GNUNET_OK == GNUNET_DNSPARSER_builder_add_name (dst, | ||
692 | dst_len, | ||
693 | &off, | ||
694 | rec->data.hostname))) | ||
695 | { | ||
696 | add_record (gc->req, | ||
697 | GNUNET_GNSRECORD_TYPE_GNS2DNS, | ||
698 | expiration_time, | ||
699 | dst, | ||
700 | off); | ||
701 | gc->found = GNUNET_YES; | ||
702 | } | ||
703 | break; | ||
704 | |||
705 | default: | ||
706 | /* useless, do nothing */ | ||
707 | break; | ||
708 | } | ||
709 | } | ||
710 | |||
711 | |||
712 | /** | ||
713 | * Closure for #process_record(). | ||
714 | */ | ||
715 | struct ProcessRecordContext | ||
716 | { | ||
717 | /** | ||
718 | * Answer we got back and are currently parsing, or NULL | ||
719 | * if not active. | ||
720 | */ | ||
721 | struct GNUNET_DNSPARSER_Packet *p; | ||
722 | |||
723 | /** | ||
724 | * Request we are processing. | ||
725 | */ | ||
726 | struct Request *req; | ||
727 | }; | ||
728 | |||
729 | |||
730 | /** | ||
731 | * We received @a rec for @a req. Remember the answer. | ||
732 | * | ||
733 | * @param cls a `struct ProcessRecordContext` | ||
734 | * @param rec response | ||
735 | */ | ||
736 | static void | ||
737 | process_record (void *cls, const struct GNUNET_DNSPARSER_Record *rec) | ||
738 | { | ||
739 | struct ProcessRecordContext *prc = cls; | ||
740 | struct Request *req = prc->req; | ||
741 | char dst[65536]; | ||
742 | size_t dst_len; | ||
743 | size_t off; | ||
744 | struct GNUNET_TIME_Absolute expiration_time; | ||
745 | struct GNUNET_TIME_Relative left; | ||
746 | |||
747 | dst_len = sizeof(dst); | ||
748 | off = 0; | ||
749 | records++; | ||
750 | if (0 != strcasecmp (rec->name, req->hostname)) | ||
751 | { | ||
752 | GNUNET_log ( | ||
753 | GNUNET_ERROR_TYPE_DEBUG, | ||
754 | "DNS returned record from zone `%s' of type %u while resolving `%s'\n", | ||
755 | rec->name, | ||
756 | (unsigned int) rec->type, | ||
757 | req->hostname); | ||
758 | return; /* does not match hostname, might be glue, but | ||
759 | not useful for this pass! */ | ||
760 | } | ||
761 | expiration_time = rec->expiration_time; | ||
762 | left = GNUNET_TIME_absolute_get_remaining (expiration_time); | ||
763 | if (0 == left.rel_value_us) | ||
764 | { | ||
765 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
766 | "DNS returned expired record for `%s'\n", | ||
767 | req->hostname); | ||
768 | GNUNET_STATISTICS_update (stats, | ||
769 | "# expired records obtained from DNS", | ||
770 | 1, | ||
771 | GNUNET_NO); | ||
772 | return; /* record expired */ | ||
773 | } | ||
774 | |||
775 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
776 | "DNS returned record that expires at %s for `%s'\n", | ||
777 | GNUNET_STRINGS_absolute_time_to_string (expiration_time), | ||
778 | req->hostname); | ||
779 | /* if expiration window is too short, bump it to configured minimum */ | ||
780 | if (left.rel_value_us < minimum_expiration_time.rel_value_us) | ||
781 | expiration_time = | ||
782 | GNUNET_TIME_relative_to_absolute (minimum_expiration_time); | ||
783 | switch (rec->type) | ||
784 | { | ||
785 | case GNUNET_DNSPARSER_TYPE_NS: { | ||
786 | struct GlueClosure gc; | ||
787 | |||
788 | /* check for glue */ | ||
789 | gc.req = req; | ||
790 | gc.ns = rec->data.hostname; | ||
791 | gc.found = GNUNET_NO; | ||
792 | for_all_records (prc->p, &check_for_glue, &gc); | ||
793 | if ((GNUNET_NO == gc.found) && | ||
794 | (GNUNET_OK == GNUNET_DNSPARSER_builder_add_name (dst, | ||
795 | dst_len, | ||
796 | &off, | ||
797 | req->hostname)) && | ||
798 | (GNUNET_OK == GNUNET_DNSPARSER_builder_add_name (dst, | ||
799 | dst_len, | ||
800 | &off, | ||
801 | rec->data.hostname))) | ||
802 | { | ||
803 | /* FIXME: actually check if this is out-of-bailiwick, | ||
804 | and if not request explicit resolution... */ | ||
805 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
806 | "Converted OOB (`%s') NS record for `%s'\n", | ||
807 | rec->data.hostname, | ||
808 | rec->name); | ||
809 | add_record (req, | ||
810 | GNUNET_GNSRECORD_TYPE_GNS2DNS, | ||
811 | expiration_time, | ||
812 | dst, | ||
813 | off); | ||
814 | } | ||
815 | else | ||
816 | { | ||
817 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
818 | "Converted NS record for `%s' using glue\n", | ||
819 | rec->name); | ||
820 | } | ||
821 | break; | ||
822 | } | ||
823 | |||
824 | case GNUNET_DNSPARSER_TYPE_CNAME: | ||
825 | if (GNUNET_OK == GNUNET_DNSPARSER_builder_add_name (dst, | ||
826 | dst_len, | ||
827 | &off, | ||
828 | rec->data.hostname)) | ||
829 | { | ||
830 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
831 | "Converting CNAME (`%s') record for `%s'\n", | ||
832 | rec->data.hostname, | ||
833 | rec->name); | ||
834 | add_record (req, rec->type, expiration_time, dst, off); | ||
835 | } | ||
836 | break; | ||
837 | |||
838 | case GNUNET_DNSPARSER_TYPE_DNAME: | ||
839 | /* No support for DNAME in GNS yet! FIXME: support later! */ | ||
840 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, | ||
841 | "FIXME: not supported: %s DNAME %s\n", | ||
842 | rec->name, | ||
843 | rec->data.hostname); | ||
844 | break; | ||
845 | |||
846 | case GNUNET_DNSPARSER_TYPE_MX: | ||
847 | if (GNUNET_OK == | ||
848 | GNUNET_DNSPARSER_builder_add_mx (dst, dst_len, &off, rec->data.mx)) | ||
849 | { | ||
850 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
851 | "Converting MX (`%s') record for `%s'\n", | ||
852 | rec->data.mx->mxhost, | ||
853 | rec->name); | ||
854 | add_record (req, rec->type, expiration_time, dst, off); | ||
855 | } | ||
856 | break; | ||
857 | |||
858 | case GNUNET_DNSPARSER_TYPE_SOA: | ||
859 | if (GNUNET_OK == | ||
860 | GNUNET_DNSPARSER_builder_add_soa (dst, dst_len, &off, rec->data.soa)) | ||
861 | { | ||
862 | /* NOTE: GNS does not really use SOAs */ | ||
863 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
864 | "Converting SOA record for `%s'\n", | ||
865 | rec->name); | ||
866 | add_record (req, rec->type, expiration_time, dst, off); | ||
867 | } | ||
868 | break; | ||
869 | |||
870 | case GNUNET_DNSPARSER_TYPE_SRV: | ||
871 | if (GNUNET_OK == | ||
872 | GNUNET_DNSPARSER_builder_add_srv (dst, dst_len, &off, rec->data.srv)) | ||
873 | { | ||
874 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
875 | "Converting SRV record for `%s'\n", | ||
876 | rec->name); | ||
877 | add_record (req, rec->type, expiration_time, dst, off); | ||
878 | } | ||
879 | break; | ||
880 | |||
881 | case GNUNET_DNSPARSER_TYPE_PTR: | ||
882 | if (GNUNET_OK == GNUNET_DNSPARSER_builder_add_name (dst, | ||
883 | dst_len, | ||
884 | &off, | ||
885 | rec->data.hostname)) | ||
886 | { | ||
887 | /* !?: what does a PTR record do in a regular TLD??? */ | ||
888 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
889 | "Converting PTR record for `%s' (weird)\n", | ||
890 | rec->name); | ||
891 | add_record (req, rec->type, expiration_time, dst, off); | ||
892 | } | ||
893 | break; | ||
894 | |||
895 | case GNUNET_DNSPARSER_TYPE_CERT: | ||
896 | if (GNUNET_OK == | ||
897 | GNUNET_DNSPARSER_builder_add_cert (dst, dst_len, &off, rec->data.cert)) | ||
898 | { | ||
899 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
900 | "Converting CERT record for `%s'\n", | ||
901 | rec->name); | ||
902 | add_record (req, rec->type, expiration_time, dst, off); | ||
903 | } | ||
904 | break; | ||
905 | |||
906 | /* Rest is 'raw' encoded and just needs to be copied IF | ||
907 | the hostname matches the requested name; otherwise we | ||
908 | simply cannot use it. */ | ||
909 | case GNUNET_DNSPARSER_TYPE_A: | ||
910 | case GNUNET_DNSPARSER_TYPE_AAAA: | ||
911 | case GNUNET_DNSPARSER_TYPE_TXT: | ||
912 | default: | ||
913 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
914 | "Converting record of type %u for `%s'\n", | ||
915 | (unsigned int) rec->type, | ||
916 | rec->name); | ||
917 | add_record (req, | ||
918 | rec->type, | ||
919 | expiration_time, | ||
920 | rec->data.raw.data, | ||
921 | rec->data.raw.data_len); | ||
922 | break; | ||
923 | } | ||
924 | } | ||
925 | |||
926 | |||
927 | /** | ||
928 | * Continuation called to notify client about result of the | ||
929 | * operation. | ||
930 | * | ||
931 | * @param cls closure with our `struct Request` | ||
932 | * @param success #GNUNET_SYSERR on failure (including timeout/queue drop/failure to validate) | ||
933 | * #GNUNET_NO if content was already there or not found | ||
934 | * #GNUNET_YES (or other positive value) on success | ||
935 | * @param emsg NULL on success, otherwise an error message | ||
936 | */ | ||
937 | static void | ||
938 | store_completed_cb (void *cls, int32_t success, const char *emsg) | ||
939 | { | ||
940 | static struct GNUNET_TIME_Absolute last; | ||
941 | struct Request *req = cls; | ||
942 | |||
943 | req->qe = NULL; | ||
944 | if (GNUNET_SYSERR == success) | ||
945 | { | ||
946 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
947 | "Failed to store zone data for `%s': %s\n", | ||
948 | req->hostname, | ||
949 | emsg); | ||
950 | } | ||
951 | else | ||
952 | { | ||
953 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
954 | "Stored records under `%s' (%d)\n", | ||
955 | req->hostname, | ||
956 | success); | ||
957 | } | ||
958 | total_reg_proc_dns_ns++; /* finished regular processing */ | ||
959 | pending_rs--; | ||
960 | free_records (req); | ||
961 | /* compute NAMESTORE statistics */ | ||
962 | { | ||
963 | static uint64_t total_ns_latency_cnt; | ||
964 | static struct GNUNET_TIME_Relative total_ns_latency; | ||
965 | struct GNUNET_TIME_Relative ns_latency; | ||
966 | |||
967 | ns_latency = GNUNET_TIME_absolute_get_duration (req->op_start_time); | ||
968 | total_ns_latency = GNUNET_TIME_relative_add (total_ns_latency, ns_latency); | ||
969 | if (0 == total_ns_latency_cnt) | ||
970 | last = GNUNET_TIME_absolute_get (); | ||
971 | total_ns_latency_cnt++; | ||
972 | if (0 == (total_ns_latency_cnt % 1000)) | ||
973 | { | ||
974 | struct GNUNET_TIME_Relative delta; | ||
975 | |||
976 | delta = GNUNET_TIME_absolute_get_duration (last); | ||
977 | last = GNUNET_TIME_absolute_get (); | ||
978 | fprintf (stderr, | ||
979 | "Processed 1000 records in %s\n", | ||
980 | GNUNET_STRINGS_relative_time_to_string (delta, GNUNET_YES)); | ||
981 | GNUNET_STATISTICS_set (stats, | ||
982 | "# average NAMESTORE PUT latency (μs)", | ||
983 | total_ns_latency.rel_value_us | ||
984 | / total_ns_latency_cnt, | ||
985 | GNUNET_NO); | ||
986 | } | ||
987 | } | ||
988 | /* compute and publish overall velocity */ | ||
989 | if (0 == (total_reg_proc_dns_ns % 100)) | ||
990 | { | ||
991 | struct GNUNET_TIME_Relative runtime; | ||
992 | |||
993 | runtime = GNUNET_TIME_absolute_get_duration (start_time_reg_proc); | ||
994 | runtime = GNUNET_TIME_relative_subtract (runtime, idle_time); | ||
995 | runtime = | ||
996 | GNUNET_TIME_relative_divide (runtime, | ||
997 | total_reg_proc_dns + total_reg_proc_dns_ns); | ||
998 | GNUNET_STATISTICS_set (stats, | ||
999 | "# Regular processing completed without NAMESTORE", | ||
1000 | total_reg_proc_dns, | ||
1001 | GNUNET_NO); | ||
1002 | GNUNET_STATISTICS_set (stats, | ||
1003 | "# Regular processing completed with NAMESTORE PUT", | ||
1004 | total_reg_proc_dns_ns, | ||
1005 | GNUNET_NO); | ||
1006 | GNUNET_STATISTICS_set (stats, | ||
1007 | "# average request processing latency (μs)", | ||
1008 | runtime.rel_value_us, | ||
1009 | GNUNET_NO); | ||
1010 | GNUNET_STATISTICS_set (stats, | ||
1011 | "# total time spent idle (μs)", | ||
1012 | idle_time.rel_value_us, | ||
1013 | GNUNET_NO); | ||
1014 | } | ||
1015 | |||
1016 | if (NULL == t) | ||
1017 | { | ||
1018 | sleep_time_reg_proc = GNUNET_TIME_absolute_get (); | ||
1019 | t = GNUNET_SCHEDULER_add_now (&process_queue, NULL); | ||
1020 | } | ||
1021 | } | ||
1022 | |||
1023 | |||
1024 | /** | ||
1025 | * Function called with the result of a DNS resolution. | ||
1026 | * | ||
1027 | * @param cls closure with the `struct Request` | ||
1028 | * @param dns dns response, never NULL | ||
1029 | * @param dns_len number of bytes in @a dns | ||
1030 | */ | ||
1031 | static void | ||
1032 | process_result (void *cls, | ||
1033 | const struct GNUNET_TUN_DnsHeader *dns, | ||
1034 | size_t dns_len) | ||
1035 | { | ||
1036 | struct Request *req = cls; | ||
1037 | struct Record *rec; | ||
1038 | struct GNUNET_DNSPARSER_Packet *p; | ||
1039 | unsigned int rd_count; | ||
1040 | |||
1041 | GNUNET_assert (NULL == req->hn); | ||
1042 | if (NULL == dns) | ||
1043 | { | ||
1044 | /* stub gave up */ | ||
1045 | GNUNET_CONTAINER_DLL_remove (req_head, req_tail, req); | ||
1046 | pending--; | ||
1047 | if (NULL == t) | ||
1048 | { | ||
1049 | sleep_time_reg_proc = GNUNET_TIME_absolute_get (); | ||
1050 | t = GNUNET_SCHEDULER_add_now (&process_queue, NULL); | ||
1051 | } | ||
1052 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
1053 | "Stub gave up on DNS reply for `%s'\n", | ||
1054 | req->hostname); | ||
1055 | GNUNET_STATISTICS_update (stats, "# DNS lookups timed out", 1, GNUNET_NO); | ||
1056 | if (req->issue_num > MAX_RETRIES) | ||
1057 | { | ||
1058 | failures++; | ||
1059 | free_request (req); | ||
1060 | GNUNET_STATISTICS_update (stats, "# requests given up on", 1, GNUNET_NO); | ||
1061 | return; | ||
1062 | } | ||
1063 | total_reg_proc_dns++; | ||
1064 | req->rs = NULL; | ||
1065 | insert_sorted (req); | ||
1066 | return; | ||
1067 | } | ||
1068 | if (req->id != dns->id) | ||
1069 | { | ||
1070 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
1071 | "DNS ID did not match request, ignoring reply\n"); | ||
1072 | GNUNET_STATISTICS_update (stats, "# DNS ID mismatches", 1, GNUNET_NO); | ||
1073 | return; | ||
1074 | } | ||
1075 | GNUNET_CONTAINER_DLL_remove (req_head, req_tail, req); | ||
1076 | GNUNET_DNSSTUB_resolve_cancel (req->rs); | ||
1077 | req->rs = NULL; | ||
1078 | pending--; | ||
1079 | p = GNUNET_DNSPARSER_parse ((const char *) dns, dns_len); | ||
1080 | if (NULL == p) | ||
1081 | { | ||
1082 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
1083 | "Failed to parse DNS reply for `%s'\n", | ||
1084 | req->hostname); | ||
1085 | GNUNET_STATISTICS_update (stats, "# DNS parser errors", 1, GNUNET_NO); | ||
1086 | if (NULL == t) | ||
1087 | { | ||
1088 | sleep_time_reg_proc = GNUNET_TIME_absolute_get (); | ||
1089 | t = GNUNET_SCHEDULER_add_now (&process_queue, NULL); | ||
1090 | } | ||
1091 | if (req->issue_num > MAX_RETRIES) | ||
1092 | { | ||
1093 | failures++; | ||
1094 | free_request (req); | ||
1095 | GNUNET_STATISTICS_update (stats, "# requests given up on", 1, GNUNET_NO); | ||
1096 | return; | ||
1097 | } | ||
1098 | insert_sorted (req); | ||
1099 | return; | ||
1100 | } | ||
1101 | /* import new records */ | ||
1102 | req->issue_num = 0; /* success, reset counter! */ | ||
1103 | { | ||
1104 | struct ProcessRecordContext prc = { .req = req, .p = p }; | ||
1105 | |||
1106 | for_all_records (p, &process_record, &prc); | ||
1107 | } | ||
1108 | GNUNET_DNSPARSER_free_packet (p); | ||
1109 | /* count records found, determine minimum expiration time */ | ||
1110 | req->expires = GNUNET_TIME_UNIT_FOREVER_ABS; | ||
1111 | { | ||
1112 | struct GNUNET_TIME_Relative dns_latency; | ||
1113 | |||
1114 | dns_latency = GNUNET_TIME_absolute_get_duration (req->op_start_time); | ||
1115 | total_dns_latency = | ||
1116 | GNUNET_TIME_relative_add (total_dns_latency, dns_latency); | ||
1117 | total_dns_latency_cnt++; | ||
1118 | if (0 == (total_dns_latency_cnt % 1000)) | ||
1119 | { | ||
1120 | GNUNET_STATISTICS_set (stats, | ||
1121 | "# average DNS lookup latency (μs)", | ||
1122 | total_dns_latency.rel_value_us | ||
1123 | / total_dns_latency_cnt, | ||
1124 | GNUNET_NO); | ||
1125 | } | ||
1126 | } | ||
1127 | rd_count = 0; | ||
1128 | for (rec = req->rec_head; NULL != rec; rec = rec->next) | ||
1129 | { | ||
1130 | struct GNUNET_TIME_Absolute at; | ||
1131 | |||
1132 | at.abs_value_us = rec->grd.expiration_time; | ||
1133 | req->expires = GNUNET_TIME_absolute_min (req->expires, at); | ||
1134 | rd_count++; | ||
1135 | } | ||
1136 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, | ||
1137 | "Obtained %u records for `%s'\n", | ||
1138 | rd_count, | ||
1139 | req->hostname); | ||
1140 | /* Instead of going for SOA, simplified for now to look each | ||
1141 | day in case we got an empty response */ | ||
1142 | if (0 == rd_count) | ||
1143 | { | ||
1144 | req->expires = GNUNET_TIME_relative_to_absolute (GNUNET_TIME_UNIT_DAYS); | ||
1145 | GNUNET_STATISTICS_update (stats, | ||
1146 | "# empty DNS replies (usually NXDOMAIN)", | ||
1147 | 1, | ||
1148 | GNUNET_NO); | ||
1149 | } | ||
1150 | else | ||
1151 | { | ||
1152 | record_sets++; | ||
1153 | } | ||
1154 | /* convert records to namestore import format */ | ||
1155 | { | ||
1156 | struct GNUNET_GNSRECORD_Data rd[GNUNET_NZL (rd_count)]; | ||
1157 | unsigned int off = 0; | ||
1158 | |||
1159 | /* convert linked list into array */ | ||
1160 | for (rec = req->rec_head; NULL != rec; rec = rec->next) | ||
1161 | rd[off++] = rec->grd; | ||
1162 | pending_rs++; | ||
1163 | req->op_start_time = GNUNET_TIME_absolute_get (); | ||
1164 | req->qe = GNUNET_NAMESTORE_records_store (ns, | ||
1165 | &req->zone->key, | ||
1166 | get_label (req), | ||
1167 | rd_count, | ||
1168 | rd, | ||
1169 | &store_completed_cb, | ||
1170 | req); | ||
1171 | GNUNET_assert (NULL != req->qe); | ||
1172 | } | ||
1173 | insert_sorted (req); | ||
1174 | } | ||
1175 | |||
1176 | |||
1177 | /** | ||
1178 | * Process as many requests as possible from the queue. | ||
1179 | * | ||
1180 | * @param cls NULL | ||
1181 | */ | ||
1182 | static void | ||
1183 | process_queue (void *cls) | ||
1184 | { | ||
1185 | struct Request *req; | ||
1186 | unsigned int series; | ||
1187 | void *raw; | ||
1188 | size_t raw_size; | ||
1189 | struct GNUNET_TIME_Relative delay; | ||
1190 | |||
1191 | (void) cls; | ||
1192 | delay = GNUNET_TIME_absolute_get_duration (sleep_time_reg_proc); | ||
1193 | idle_time = GNUNET_TIME_relative_add (idle_time, delay); | ||
1194 | series = 0; | ||
1195 | t = NULL; | ||
1196 | while (pending + pending_rs < THRESH) | ||
1197 | { | ||
1198 | req = GNUNET_CONTAINER_heap_peek (req_heap); | ||
1199 | if (NULL == req) | ||
1200 | break; | ||
1201 | if (NULL != req->qe) | ||
1202 | return; /* namestore op still pending */ | ||
1203 | if (NULL != req->rs) | ||
1204 | { | ||
1205 | GNUNET_break (0); | ||
1206 | return; /* already submitted */ | ||
1207 | } | ||
1208 | if (GNUNET_TIME_absolute_get_remaining (req->expires).rel_value_us > 0) | ||
1209 | break; | ||
1210 | GNUNET_assert (req == GNUNET_CONTAINER_heap_remove_root (req_heap)); | ||
1211 | req->hn = NULL; | ||
1212 | GNUNET_CONTAINER_DLL_insert (req_head, req_tail, req); | ||
1213 | GNUNET_assert (NULL == req->rs); | ||
1214 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, | ||
1215 | "Requesting resolution for `%s'\n", | ||
1216 | req->hostname); | ||
1217 | raw = build_dns_query (req, &raw_size); | ||
1218 | if (NULL == raw) | ||
1219 | { | ||
1220 | GNUNET_break (0); | ||
1221 | free_request (req); | ||
1222 | continue; | ||
1223 | } | ||
1224 | req->op_start_time = GNUNET_TIME_absolute_get (); | ||
1225 | req->rs = GNUNET_DNSSTUB_resolve (ctx, raw, raw_size, &process_result, req); | ||
1226 | GNUNET_assert (NULL != req->rs); | ||
1227 | req->issue_num++; | ||
1228 | lookups++; | ||
1229 | pending++; | ||
1230 | series++; | ||
1231 | if (series > MAX_SERIES) | ||
1232 | break; | ||
1233 | } | ||
1234 | if (pending + pending_rs >= THRESH) | ||
1235 | { | ||
1236 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
1237 | "Stopped processing queue (%u+%u/%u)]\n", | ||
1238 | pending, | ||
1239 | pending_rs, | ||
1240 | THRESH); | ||
1241 | return; /* wait for replies */ | ||
1242 | } | ||
1243 | req = GNUNET_CONTAINER_heap_peek (req_heap); | ||
1244 | if (NULL == req) | ||
1245 | { | ||
1246 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
1247 | "Stopped processing queue: empty queue\n"); | ||
1248 | return; | ||
1249 | } | ||
1250 | if (GNUNET_TIME_absolute_get_remaining (req->expires).rel_value_us > 0) | ||
1251 | { | ||
1252 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, | ||
1253 | "Waiting until %s for next record (`%s') to expire\n", | ||
1254 | GNUNET_STRINGS_absolute_time_to_string (req->expires), | ||
1255 | req->hostname); | ||
1256 | if (NULL != t) | ||
1257 | GNUNET_SCHEDULER_cancel (t); | ||
1258 | sleep_time_reg_proc = GNUNET_TIME_absolute_get (); | ||
1259 | t = GNUNET_SCHEDULER_add_at (req->expires, &process_queue, NULL); | ||
1260 | return; | ||
1261 | } | ||
1262 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Throttling\n"); | ||
1263 | if (NULL != t) | ||
1264 | GNUNET_SCHEDULER_cancel (t); | ||
1265 | sleep_time_reg_proc = GNUNET_TIME_absolute_get (); | ||
1266 | t = GNUNET_SCHEDULER_add_delayed (SERIES_DELAY, &process_queue, NULL); | ||
1267 | } | ||
1268 | |||
1269 | |||
1270 | /** | ||
1271 | * Iterator called during #do_shutdown() to free requests in | ||
1272 | * the #ns_pending map. | ||
1273 | * | ||
1274 | * @param cls NULL | ||
1275 | * @param key unused | ||
1276 | * @param value the `struct Request` to free | ||
1277 | * @return #GNUNET_OK | ||
1278 | */ | ||
1279 | static int | ||
1280 | free_request_it (void *cls, const struct GNUNET_HashCode *key, void *value) | ||
1281 | { | ||
1282 | struct Request *req = value; | ||
1283 | |||
1284 | (void) cls; | ||
1285 | (void) key; | ||
1286 | free_request (req); | ||
1287 | return GNUNET_OK; | ||
1288 | } | ||
1289 | |||
1290 | |||
1291 | /** | ||
1292 | * Clean up and terminate the process. | ||
1293 | * | ||
1294 | * @param cls NULL | ||
1295 | */ | ||
1296 | static void | ||
1297 | do_shutdown (void *cls) | ||
1298 | { | ||
1299 | struct Request *req; | ||
1300 | struct Zone *zone; | ||
1301 | |||
1302 | (void) cls; | ||
1303 | if (NULL != id) | ||
1304 | { | ||
1305 | GNUNET_IDENTITY_disconnect (id); | ||
1306 | id = NULL; | ||
1307 | } | ||
1308 | if (NULL != t) | ||
1309 | { | ||
1310 | GNUNET_SCHEDULER_cancel (t); | ||
1311 | t = NULL; | ||
1312 | } | ||
1313 | while (NULL != (req = req_head)) | ||
1314 | { | ||
1315 | GNUNET_CONTAINER_DLL_remove (req_head, req_tail, req); | ||
1316 | if (NULL != req->qe) | ||
1317 | GNUNET_NAMESTORE_cancel (req->qe); | ||
1318 | free_request (req); | ||
1319 | } | ||
1320 | while (NULL != (req = GNUNET_CONTAINER_heap_remove_root (req_heap))) | ||
1321 | { | ||
1322 | req->hn = NULL; | ||
1323 | if (NULL != req->qe) | ||
1324 | GNUNET_NAMESTORE_cancel (req->qe); | ||
1325 | free_request (req); | ||
1326 | } | ||
1327 | if (NULL != zone_it) | ||
1328 | { | ||
1329 | GNUNET_NAMESTORE_zone_iteration_stop (zone_it); | ||
1330 | zone_it = NULL; | ||
1331 | } | ||
1332 | if (NULL != ns) | ||
1333 | { | ||
1334 | GNUNET_NAMESTORE_disconnect (ns); | ||
1335 | ns = NULL; | ||
1336 | } | ||
1337 | if (NULL != ctx) | ||
1338 | { | ||
1339 | GNUNET_DNSSTUB_stop (ctx); | ||
1340 | ctx = NULL; | ||
1341 | } | ||
1342 | if (NULL != req_heap) | ||
1343 | { | ||
1344 | GNUNET_CONTAINER_heap_destroy (req_heap); | ||
1345 | req_heap = NULL; | ||
1346 | } | ||
1347 | if (NULL != ns_pending) | ||
1348 | { | ||
1349 | GNUNET_CONTAINER_multihashmap_iterate (ns_pending, &free_request_it, NULL); | ||
1350 | GNUNET_CONTAINER_multihashmap_destroy (ns_pending); | ||
1351 | ns_pending = NULL; | ||
1352 | } | ||
1353 | while (NULL != (zone = zone_head)) | ||
1354 | { | ||
1355 | GNUNET_CONTAINER_DLL_remove (zone_head, zone_tail, zone); | ||
1356 | GNUNET_free (zone->domain); | ||
1357 | GNUNET_free (zone); | ||
1358 | } | ||
1359 | if (NULL != stats) | ||
1360 | { | ||
1361 | GNUNET_STATISTICS_destroy (stats, GNUNET_NO); | ||
1362 | stats = NULL; | ||
1363 | } | ||
1364 | } | ||
1365 | |||
1366 | |||
1367 | /** | ||
1368 | * Iterate over all of the zones we care about and see which records | ||
1369 | * we may need to re-fetch when. | ||
1370 | * | ||
1371 | * @param cls NULL | ||
1372 | */ | ||
1373 | static void | ||
1374 | iterate_zones (void *cls); | ||
1375 | |||
1376 | |||
1377 | /** | ||
1378 | * Function called if #GNUNET_NAMESTORE_records_lookup() failed. | ||
1379 | * Just logs an error. | ||
1380 | * | ||
1381 | * @param cls a `struct Zone` | ||
1382 | */ | ||
1383 | static void | ||
1384 | ns_lookup_error_cb (void *cls) | ||
1385 | { | ||
1386 | struct Zone *zone = cls; | ||
1387 | |||
1388 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, | ||
1389 | "Failed to load data from namestore for zone `%s'\n", | ||
1390 | zone->domain); | ||
1391 | zone_it = NULL; | ||
1392 | ns_iterator_trigger_next = 0; | ||
1393 | iterate_zones (NULL); | ||
1394 | } | ||
1395 | |||
1396 | |||
1397 | /** | ||
1398 | * Process a record that was stored in the namestore. | ||
1399 | * | ||
1400 | * @param cls a `struct Zone *` | ||
1401 | * @param key private key of the zone | ||
1402 | * @param label label of the records | ||
1403 | * @param rd_count number of entries in @a rd array, 0 if label was deleted | ||
1404 | * @param rd array of records with data to store | ||
1405 | */ | ||
1406 | static void | ||
1407 | ns_lookup_result_cb (void *cls, | ||
1408 | const struct GNUNET_IDENTITY_PrivateKey *key, | ||
1409 | const char *label, | ||
1410 | unsigned int rd_count, | ||
1411 | const struct GNUNET_GNSRECORD_Data *rd) | ||
1412 | { | ||
1413 | struct Zone *zone = cls; | ||
1414 | struct Request *req; | ||
1415 | struct GNUNET_HashCode hc; | ||
1416 | char *fqdn; | ||
1417 | |||
1418 | ns_iterator_trigger_next--; | ||
1419 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
1420 | "Obtained NAMESTORE reply, %llu left in round\n", | ||
1421 | (unsigned long long) ns_iterator_trigger_next); | ||
1422 | if (0 == ns_iterator_trigger_next) | ||
1423 | { | ||
1424 | ns_iterator_trigger_next = NS_BATCH_SIZE; | ||
1425 | GNUNET_STATISTICS_update (stats, | ||
1426 | "# NAMESTORE records requested from cache", | ||
1427 | ns_iterator_trigger_next, | ||
1428 | GNUNET_NO); | ||
1429 | GNUNET_NAMESTORE_zone_iterator_next (zone_it, ns_iterator_trigger_next); | ||
1430 | } | ||
1431 | GNUNET_asprintf (&fqdn, "%s.%s", label, zone->domain); | ||
1432 | GNUNET_CRYPTO_hash (fqdn, strlen (fqdn) + 1, &hc); | ||
1433 | GNUNET_free (fqdn); | ||
1434 | req = GNUNET_CONTAINER_multihashmap_get (ns_pending, &hc); | ||
1435 | if (NULL == req) | ||
1436 | { | ||
1437 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, | ||
1438 | "Ignoring record `%s' in zone `%s': not on my list!\n", | ||
1439 | label, | ||
1440 | zone->domain); | ||
1441 | return; | ||
1442 | } | ||
1443 | GNUNET_assert (GNUNET_OK == | ||
1444 | GNUNET_CONTAINER_multihashmap_remove (ns_pending, &hc, req)); | ||
1445 | GNUNET_break (0 == GNUNET_memcmp (key, &req->zone->key)); | ||
1446 | GNUNET_break (0 == strcasecmp (label, get_label (req))); | ||
1447 | for (unsigned int i = 0; i < rd_count; i++) | ||
1448 | { | ||
1449 | struct GNUNET_TIME_Absolute at; | ||
1450 | |||
1451 | if (0 != (rd->flags & GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION)) | ||
1452 | { | ||
1453 | struct GNUNET_TIME_Relative rel; | ||
1454 | |||
1455 | rel.rel_value_us = rd->expiration_time; | ||
1456 | at = GNUNET_TIME_relative_to_absolute (rel); | ||
1457 | } | ||
1458 | else | ||
1459 | { | ||
1460 | at.abs_value_us = rd->expiration_time; | ||
1461 | } | ||
1462 | add_record (req, rd->record_type, at, rd->data, rd->data_size); | ||
1463 | } | ||
1464 | if (0 == rd_count) | ||
1465 | { | ||
1466 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, | ||
1467 | "Empty record set in namestore for `%s'\n", | ||
1468 | req->hostname); | ||
1469 | } | ||
1470 | else | ||
1471 | { | ||
1472 | unsigned int pos = 0; | ||
1473 | |||
1474 | cached++; | ||
1475 | req->expires = GNUNET_TIME_UNIT_FOREVER_ABS; | ||
1476 | for (struct Record *rec = req->rec_head; NULL != rec; rec = rec->next) | ||
1477 | { | ||
1478 | struct GNUNET_TIME_Absolute at; | ||
1479 | |||
1480 | at.abs_value_us = rec->grd.expiration_time; | ||
1481 | req->expires = GNUNET_TIME_absolute_min (req->expires, at); | ||
1482 | pos++; | ||
1483 | } | ||
1484 | if (0 == pos) | ||
1485 | req->expires = GNUNET_TIME_UNIT_ZERO_ABS; | ||
1486 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, | ||
1487 | "Hot-start with %u existing records for `%s'\n", | ||
1488 | pos, | ||
1489 | req->hostname); | ||
1490 | } | ||
1491 | free_records (req); | ||
1492 | |||
1493 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
1494 | "Adding `%s' to worklist to start at %s\n", | ||
1495 | req->hostname, | ||
1496 | GNUNET_STRINGS_absolute_time_to_string (req->expires)); | ||
1497 | insert_sorted (req); | ||
1498 | } | ||
1499 | |||
1500 | |||
1501 | /** | ||
1502 | * Add @a hostname to the list of requests to be made. | ||
1503 | * | ||
1504 | * @param hostname name to resolve | ||
1505 | */ | ||
1506 | static void | ||
1507 | queue (const char *hostname) | ||
1508 | { | ||
1509 | struct Request *req; | ||
1510 | const char *dot; | ||
1511 | struct Zone *zone; | ||
1512 | size_t hlen; | ||
1513 | struct GNUNET_HashCode hc; | ||
1514 | |||
1515 | if (GNUNET_OK != GNUNET_DNSPARSER_check_name (hostname)) | ||
1516 | { | ||
1517 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
1518 | "Refusing invalid hostname `%s'\n", | ||
1519 | hostname); | ||
1520 | rejects++; | ||
1521 | return; | ||
1522 | } | ||
1523 | dot = strchr (hostname, (unsigned char) '.'); | ||
1524 | if (NULL == dot) | ||
1525 | { | ||
1526 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
1527 | "Refusing invalid hostname `%s' (lacks '.')\n", | ||
1528 | hostname); | ||
1529 | rejects++; | ||
1530 | return; | ||
1531 | } | ||
1532 | for (zone = zone_head; NULL != zone; zone = zone->next) | ||
1533 | if (0 == strcmp (zone->domain, dot + 1)) | ||
1534 | break; | ||
1535 | if (NULL == zone) | ||
1536 | { | ||
1537 | rejects++; | ||
1538 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
1539 | "Domain name `%s' not in ego list!\n", | ||
1540 | dot + 1); | ||
1541 | return; | ||
1542 | } | ||
1543 | |||
1544 | hlen = strlen (hostname) + 1; | ||
1545 | req = GNUNET_malloc (sizeof(struct Request) + hlen); | ||
1546 | req->zone = zone; | ||
1547 | req->hostname = (char *) &req[1]; | ||
1548 | GNUNET_memcpy (req->hostname, hostname, hlen); | ||
1549 | req->id = (uint16_t) GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_NONCE, | ||
1550 | UINT16_MAX); | ||
1551 | GNUNET_CRYPTO_hash (req->hostname, hlen, &hc); | ||
1552 | if (GNUNET_OK != GNUNET_CONTAINER_multihashmap_put ( | ||
1553 | ns_pending, | ||
1554 | &hc, | ||
1555 | req, | ||
1556 | GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY)) | ||
1557 | { | ||
1558 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, | ||
1559 | "Duplicate hostname `%s' ignored\n", | ||
1560 | hostname); | ||
1561 | GNUNET_free (req); | ||
1562 | return; | ||
1563 | } | ||
1564 | } | ||
1565 | |||
1566 | |||
1567 | /** | ||
1568 | * We have completed the initial iteration over the namestore's database. | ||
1569 | * This function is called on each of the remaining records in | ||
1570 | * #move_to_queue to #queue() them, as we will simply not find existing | ||
1571 | * records for them any longer. | ||
1572 | * | ||
1573 | * @param cls NULL | ||
1574 | * @param key unused | ||
1575 | * @param value a `struct Request` | ||
1576 | * @return #GNUNET_OK (continue to iterate) | ||
1577 | */ | ||
1578 | static int | ||
1579 | move_to_queue (void *cls, const struct GNUNET_HashCode *key, void *value) | ||
1580 | { | ||
1581 | struct Request *req = value; | ||
1582 | |||
1583 | (void) cls; | ||
1584 | (void) key; | ||
1585 | insert_sorted (req); | ||
1586 | return GNUNET_OK; | ||
1587 | } | ||
1588 | |||
1589 | |||
1590 | /** | ||
1591 | * Iterate over all of the zones we care about and see which records | ||
1592 | * we may need to re-fetch when. | ||
1593 | * | ||
1594 | * @param cls NULL | ||
1595 | */ | ||
1596 | static void | ||
1597 | iterate_zones (void *cls) | ||
1598 | { | ||
1599 | static struct Zone *last; | ||
1600 | |||
1601 | (void) cls; | ||
1602 | if (NULL != zone_it) | ||
1603 | { | ||
1604 | zone_it = NULL; | ||
1605 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
1606 | "Finished iteration over zone `%s'!\n", | ||
1607 | last->domain); | ||
1608 | /* subtract left-overs from previous iteration */ | ||
1609 | GNUNET_STATISTICS_update (stats, | ||
1610 | "# NAMESTORE records requested from cache", | ||
1611 | (long long) (-ns_iterator_trigger_next), | ||
1612 | GNUNET_NO); | ||
1613 | ns_iterator_trigger_next = 0; | ||
1614 | } | ||
1615 | GNUNET_assert (NULL != zone_tail); | ||
1616 | if (zone_tail == last) | ||
1617 | { | ||
1618 | /* Done iterating over relevant zones in NAMESTORE, move | ||
1619 | rest of hash map to work queue as well. */ | ||
1620 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
1621 | "Finished all NAMESTORE iterations!\n"); | ||
1622 | GNUNET_STATISTICS_set (stats, | ||
1623 | "# Domain names without cached reply", | ||
1624 | GNUNET_CONTAINER_multihashmap_size (ns_pending), | ||
1625 | GNUNET_NO); | ||
1626 | GNUNET_CONTAINER_multihashmap_iterate (ns_pending, &move_to_queue, NULL); | ||
1627 | GNUNET_CONTAINER_multihashmap_destroy (ns_pending); | ||
1628 | ns_pending = NULL; | ||
1629 | start_time_reg_proc = GNUNET_TIME_absolute_get (); | ||
1630 | total_reg_proc_dns = 0; | ||
1631 | total_reg_proc_dns_ns = 0; | ||
1632 | return; | ||
1633 | } | ||
1634 | if (NULL == last) | ||
1635 | last = zone_head; | ||
1636 | else | ||
1637 | last = last->next; | ||
1638 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
1639 | "Starting iteration over zone `%s'!\n", | ||
1640 | last->domain); | ||
1641 | /* subtract left-overs from previous iteration */ | ||
1642 | GNUNET_STATISTICS_update (stats, | ||
1643 | "# NAMESTORE records requested from cache", | ||
1644 | 1, | ||
1645 | GNUNET_NO); | ||
1646 | ns_iterator_trigger_next = 1; | ||
1647 | GNUNET_STATISTICS_update (stats, "# zones iterated", 1, GNUNET_NO); | ||
1648 | zone_it = GNUNET_NAMESTORE_zone_iteration_start (ns, | ||
1649 | &last->key, | ||
1650 | &ns_lookup_error_cb, | ||
1651 | NULL, | ||
1652 | &ns_lookup_result_cb, | ||
1653 | last, | ||
1654 | &iterate_zones, | ||
1655 | NULL); | ||
1656 | } | ||
1657 | |||
1658 | |||
1659 | /** | ||
1660 | * Begin processing hostnames from stdin. | ||
1661 | * | ||
1662 | * @param cls NULL | ||
1663 | */ | ||
1664 | static void | ||
1665 | process_stdin (void *cls) | ||
1666 | { | ||
1667 | static struct GNUNET_TIME_Absolute last; | ||
1668 | static uint64_t idot; | ||
1669 | char hn[256]; | ||
1670 | |||
1671 | (void) cls; | ||
1672 | t = NULL; | ||
1673 | if (NULL != id) | ||
1674 | { | ||
1675 | GNUNET_IDENTITY_disconnect (id); | ||
1676 | id = NULL; | ||
1677 | } | ||
1678 | while (NULL != fgets (hn, sizeof(hn), stdin)) | ||
1679 | { | ||
1680 | if (strlen (hn) > 0) | ||
1681 | hn[strlen (hn) - 1] = '\0'; /* eat newline */ | ||
1682 | if (0 == idot) | ||
1683 | last = GNUNET_TIME_absolute_get (); | ||
1684 | idot++; | ||
1685 | if (0 == idot % 100000) | ||
1686 | { | ||
1687 | struct GNUNET_TIME_Relative delta; | ||
1688 | |||
1689 | delta = GNUNET_TIME_absolute_get_duration (last); | ||
1690 | last = GNUNET_TIME_absolute_get (); | ||
1691 | fprintf (stderr, | ||
1692 | "Read 100000 domain names in %s\n", | ||
1693 | GNUNET_STRINGS_relative_time_to_string (delta, GNUNET_YES)); | ||
1694 | GNUNET_STATISTICS_set (stats, "# domain names provided", idot, GNUNET_NO); | ||
1695 | } | ||
1696 | queue (hn); | ||
1697 | } | ||
1698 | fprintf (stderr, | ||
1699 | "Done reading %llu domain names\n", | ||
1700 | (unsigned long long) idot); | ||
1701 | GNUNET_STATISTICS_set (stats, "# domain names provided", idot, GNUNET_NO); | ||
1702 | iterate_zones (NULL); | ||
1703 | } | ||
1704 | |||
1705 | |||
1706 | /** | ||
1707 | * Method called to inform about the egos of this peer. | ||
1708 | * | ||
1709 | * When used with #GNUNET_IDENTITY_connect, this function is | ||
1710 | * initially called for all egos and then again whenever a | ||
1711 | * ego's name changes or if it is deleted. At the end of | ||
1712 | * the initial pass over all egos, the function is once called | ||
1713 | * with 'NULL' for @a ego. That does NOT mean that the callback won't | ||
1714 | * be invoked in the future or that there was an error. | ||
1715 | * | ||
1716 | * When used with #GNUNET_IDENTITY_create or #GNUNET_IDENTITY_get, this | ||
1717 | * function is only called ONCE, and 'NULL' being passed in @a ego does | ||
1718 | * indicate an error (for example because name is taken or no default value is | ||
1719 | * known). If @a ego is non-NULL and if '*ctx' is set in those callbacks, the | ||
1720 | * value WILL be passed to a subsequent call to the identity callback of | ||
1721 | * #GNUNET_IDENTITY_connect (if that one was not NULL). | ||
1722 | * | ||
1723 | * When an identity is renamed, this function is called with the | ||
1724 | * (known) @a ego but the NEW @a name. | ||
1725 | * | ||
1726 | * When an identity is deleted, this function is called with the | ||
1727 | * (known) ego and "NULL" for the @a name. In this case, | ||
1728 | * the @a ego is henceforth invalid (and the @a ctx should also be | ||
1729 | * cleaned up). | ||
1730 | * | ||
1731 | * @param cls closure | ||
1732 | * @param ego ego handle, NULL for end of list | ||
1733 | * @param ctx context for application to store data for this ego | ||
1734 | * (during the lifetime of this process, initially NULL) | ||
1735 | * @param name name assigned by the user for this ego, | ||
1736 | * NULL if the user just deleted the ego and it | ||
1737 | * must thus no longer be used | ||
1738 | */ | ||
1739 | static void | ||
1740 | identity_cb (void *cls, | ||
1741 | struct GNUNET_IDENTITY_Ego *ego, | ||
1742 | void **ctx, | ||
1743 | const char *name) | ||
1744 | { | ||
1745 | (void) cls; | ||
1746 | (void) ctx; | ||
1747 | |||
1748 | if (NULL == ego) | ||
1749 | { | ||
1750 | /* end of iteration */ | ||
1751 | if (NULL == zone_head) | ||
1752 | { | ||
1753 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "No zone found\n"); | ||
1754 | GNUNET_SCHEDULER_shutdown (); | ||
1755 | return; | ||
1756 | } | ||
1757 | /* zone_head non-null, process hostnames from stdin */ | ||
1758 | t = GNUNET_SCHEDULER_add_now (&process_stdin, NULL); | ||
1759 | return; | ||
1760 | } | ||
1761 | if (NULL != name) | ||
1762 | { | ||
1763 | struct Zone *zone; | ||
1764 | |||
1765 | zone = GNUNET_new (struct Zone); | ||
1766 | zone->key = *GNUNET_IDENTITY_ego_get_private_key (ego); | ||
1767 | zone->domain = GNUNET_strdup (name); | ||
1768 | GNUNET_CONTAINER_DLL_insert (zone_head, zone_tail, zone); | ||
1769 | } | ||
1770 | } | ||
1771 | |||
1772 | |||
1773 | /** | ||
1774 | * Process requests from the queue, then if the queue is | ||
1775 | * not empty, try again. | ||
1776 | * | ||
1777 | * @param cls NULL | ||
1778 | * @param args remaining command-line arguments | ||
1779 | * @param cfgfile name of the configuration file used (for saving, can be NULL!) | ||
1780 | * @param cfg configuration | ||
1781 | */ | ||
1782 | static void | ||
1783 | run (void *cls, | ||
1784 | char *const *args, | ||
1785 | const char *cfgfile, | ||
1786 | const struct GNUNET_CONFIGURATION_Handle *cfg) | ||
1787 | { | ||
1788 | (void) cls; | ||
1789 | (void) args; | ||
1790 | (void) cfgfile; | ||
1791 | stats = GNUNET_STATISTICS_create ("zoneimport", cfg); | ||
1792 | req_heap = GNUNET_CONTAINER_heap_create (GNUNET_CONTAINER_HEAP_ORDER_MIN); | ||
1793 | ns_pending = GNUNET_CONTAINER_multihashmap_create (map_size, GNUNET_NO); | ||
1794 | if (NULL == ns_pending) | ||
1795 | { | ||
1796 | fprintf (stderr, "Failed to allocate memory for main hash map\n"); | ||
1797 | return; | ||
1798 | } | ||
1799 | ctx = GNUNET_DNSSTUB_start (256); | ||
1800 | if (NULL == ctx) | ||
1801 | { | ||
1802 | fprintf (stderr, "Failed to initialize GNUnet DNS STUB\n"); | ||
1803 | return; | ||
1804 | } | ||
1805 | if (NULL == args[0]) | ||
1806 | { | ||
1807 | fprintf (stderr, | ||
1808 | "You must provide a list of DNS resolvers on the command line\n"); | ||
1809 | return; | ||
1810 | } | ||
1811 | for (unsigned int i = 0; NULL != args[i]; i++) | ||
1812 | { | ||
1813 | if (GNUNET_OK != GNUNET_DNSSTUB_add_dns_ip (ctx, args[i])) | ||
1814 | { | ||
1815 | fprintf (stderr, "Failed to use `%s' for DNS resolver\n", args[i]); | ||
1816 | return; | ||
1817 | } | ||
1818 | } | ||
1819 | |||
1820 | |||
1821 | GNUNET_SCHEDULER_add_shutdown (&do_shutdown, NULL); | ||
1822 | ns = GNUNET_NAMESTORE_connect (cfg); | ||
1823 | if (NULL == ns) | ||
1824 | { | ||
1825 | GNUNET_SCHEDULER_shutdown (); | ||
1826 | return; | ||
1827 | } | ||
1828 | id = GNUNET_IDENTITY_connect (cfg, &identity_cb, NULL); | ||
1829 | } | ||
1830 | |||
1831 | |||
1832 | /** | ||
1833 | * Call with IP address of resolver to query. | ||
1834 | * | ||
1835 | * @param argc should be 2 | ||
1836 | * @param argv[1] should contain IP address | ||
1837 | * @return 0 on success | ||
1838 | */ | ||
1839 | int | ||
1840 | main (int argc, char *const *argv) | ||
1841 | { | ||
1842 | struct GNUNET_GETOPT_CommandLineOption options[] = | ||
1843 | { GNUNET_GETOPT_option_uint ('s', | ||
1844 | "size", | ||
1845 | "MAPSIZE", | ||
1846 | gettext_noop ( | ||
1847 | "size to use for the main hash map"), | ||
1848 | &map_size), | ||
1849 | GNUNET_GETOPT_option_relative_time ( | ||
1850 | 'm', | ||
1851 | "minimum-expiration", | ||
1852 | "RELATIVETIME", | ||
1853 | gettext_noop ("minimum expiration time we assume for imported records"), | ||
1854 | &minimum_expiration_time), | ||
1855 | GNUNET_GETOPT_OPTION_END }; | ||
1856 | int ret; | ||
1857 | |||
1858 | if (GNUNET_OK != GNUNET_STRINGS_get_utf8_args (argc, argv, &argc, &argv)) | ||
1859 | return 2; | ||
1860 | if (GNUNET_OK != (ret = GNUNET_PROGRAM_run (argc, | ||
1861 | argv, | ||
1862 | "gnunet-zoneimport", | ||
1863 | "import DNS zone into namestore", | ||
1864 | options, | ||
1865 | &run, | ||
1866 | NULL))) | ||
1867 | return ret; | ||
1868 | GNUNET_free_nz ((void *) argv); | ||
1869 | fprintf (stderr, | ||
1870 | "Rejected %u names, had %u cached, did %u lookups, stored %u record sets\n" | ||
1871 | "Found %u records, %u lookups failed, %u/%u pending on shutdown\n", | ||
1872 | rejects, | ||
1873 | cached, | ||
1874 | lookups, | ||
1875 | record_sets, | ||
1876 | records, | ||
1877 | failures, | ||
1878 | pending, | ||
1879 | pending_rs); | ||
1880 | return 0; | ||
1881 | } | ||
1882 | |||
1883 | |||
1884 | /* end of gnunet-zoneimport.c */ | ||
diff --git a/src/namestore/namestore.conf.in b/src/namestore/namestore.conf.in deleted file mode 100644 index 733e4e2f8..000000000 --- a/src/namestore/namestore.conf.in +++ /dev/null | |||
@@ -1,49 +0,0 @@ | |||
1 | [namestore] | ||
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 | FILENAME = $GNUNET_DATA_HOME/namestore/sqlite.db | ||
25 | |||
26 | [namestore-heap] | ||
27 | FILENAME = $GNUNET_DATA_HOME/namestore/heap.db | ||
28 | |||
29 | |||
30 | [namestore-postgres] | ||
31 | # How to connect to the database | ||
32 | CONFIG = postgres:///gnunet | ||
33 | # Use temporary tables | ||
34 | TEMPORARY_TABLE = NO | ||
35 | # Use asynchronous commit (SET synchronous_commit TO OFF). | ||
36 | ASYNC_COMMIT = NO | ||
37 | |||
38 | [uri] | ||
39 | gns = gnunet-namestore -e 1a -u | ||
40 | |||
41 | |||
42 | [fcfsd] | ||
43 | # Name of the fcfs registration service binary (for ARM) | ||
44 | BINARY = gnunet-namestore-fcfsd | ||
45 | START_ON_DEMAND = NO | ||
46 | UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-service-fcfsd.sock | ||
47 | |||
48 | # On what port does the FCFS daemon listen for HTTP clients? | ||
49 | HTTPPORT = 18080 | ||
diff --git a/src/namestore/namestore.h b/src/namestore/namestore.h deleted file mode 100644 index fd9a8ed47..000000000 --- a/src/namestore/namestore.h +++ /dev/null | |||
@@ -1,394 +0,0 @@ | |||
1 | /* | ||
2 | This file is part of GNUnet. | ||
3 | Copyright (C) 2011-2013 GNUnet e.V. | ||
4 | |||
5 | GNUnet is free software: you can redistribute it and/or modify it | ||
6 | under the terms of the GNU Affero General Public License as published | ||
7 | by the Free Software Foundation, either version 3 of the License, | ||
8 | or (at your option) any later version. | ||
9 | |||
10 | GNUnet is distributed in the hope that it will be useful, but | ||
11 | WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
13 | Affero General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU Affero General Public License | ||
16 | along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
17 | |||
18 | SPDX-License-Identifier: AGPL3.0-or-later | ||
19 | */ | ||
20 | |||
21 | /** | ||
22 | * @file namestore/namestore.h | ||
23 | * @brief common internal definitions for namestore service | ||
24 | * @author Matthias Wachs | ||
25 | * @author Christian Grothoff | ||
26 | */ | ||
27 | #ifndef NAMESTORE_H | ||
28 | #define NAMESTORE_H | ||
29 | |||
30 | /** | ||
31 | * Maximum length of any name, including 0-termination. | ||
32 | */ | ||
33 | #define MAX_NAME_LEN 256 | ||
34 | |||
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 | |||
55 | /** | ||
56 | * Store a record to the namestore (as authority). | ||
57 | */ | ||
58 | struct RecordStoreMessage | ||
59 | { | ||
60 | /** | ||
61 | * Type will be #GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_STORE | ||
62 | */ | ||
63 | struct GNUNET_NAMESTORE_Header gns_header; | ||
64 | |||
65 | /** | ||
66 | * Expiration time | ||
67 | */ | ||
68 | struct GNUNET_TIME_AbsoluteNBO expire; | ||
69 | |||
70 | /** | ||
71 | * Name length | ||
72 | */ | ||
73 | uint16_t name_len GNUNET_PACKED; | ||
74 | |||
75 | /** | ||
76 | * Length of serialized record data | ||
77 | */ | ||
78 | uint16_t rd_len GNUNET_PACKED; | ||
79 | |||
80 | /** | ||
81 | * Number of records contained | ||
82 | */ | ||
83 | uint16_t rd_count GNUNET_PACKED; | ||
84 | |||
85 | /** | ||
86 | * always zero (for alignment) | ||
87 | */ | ||
88 | uint16_t reserved GNUNET_PACKED; | ||
89 | |||
90 | /** | ||
91 | * The private key of the authority. | ||
92 | */ | ||
93 | struct GNUNET_IDENTITY_PrivateKey private_key; | ||
94 | |||
95 | /* followed by: | ||
96 | * name with length name_len | ||
97 | * serialized record data with rd_count records | ||
98 | */ | ||
99 | }; | ||
100 | |||
101 | |||
102 | /** | ||
103 | * Response to a record storage request. | ||
104 | */ | ||
105 | struct RecordStoreResponseMessage | ||
106 | { | ||
107 | /** | ||
108 | * Type will be #GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_STORE_RESPONSE | ||
109 | */ | ||
110 | struct GNUNET_NAMESTORE_Header gns_header; | ||
111 | |||
112 | /** | ||
113 | * #GNUNET_SYSERR on failure, #GNUNET_OK on success | ||
114 | */ | ||
115 | int32_t op_result GNUNET_PACKED; | ||
116 | }; | ||
117 | |||
118 | |||
119 | /** | ||
120 | * Lookup a label | ||
121 | */ | ||
122 | struct LabelLookupMessage | ||
123 | { | ||
124 | /** | ||
125 | * Type will be #GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_LOOKUP | ||
126 | */ | ||
127 | struct GNUNET_NAMESTORE_Header gns_header; | ||
128 | |||
129 | /** | ||
130 | * Length of the name | ||
131 | */ | ||
132 | uint32_t label_len GNUNET_PACKED; | ||
133 | |||
134 | /** | ||
135 | * The private key of the zone to look up in | ||
136 | */ | ||
137 | struct GNUNET_IDENTITY_PrivateKey zone; | ||
138 | |||
139 | /* followed by: | ||
140 | * name with length name_len | ||
141 | */ | ||
142 | }; | ||
143 | |||
144 | |||
145 | /** | ||
146 | * Lookup a label | ||
147 | */ | ||
148 | struct LabelLookupResponseMessage | ||
149 | { | ||
150 | /** | ||
151 | * Type will be #GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_LOOKUP_RESPONSE | ||
152 | */ | ||
153 | struct GNUNET_NAMESTORE_Header gns_header; | ||
154 | |||
155 | /** | ||
156 | * Name length | ||
157 | */ | ||
158 | uint16_t name_len GNUNET_PACKED; | ||
159 | |||
160 | /** | ||
161 | * Length of serialized record data | ||
162 | */ | ||
163 | uint16_t rd_len GNUNET_PACKED; | ||
164 | |||
165 | /** | ||
166 | * Number of records contained | ||
167 | */ | ||
168 | uint16_t rd_count GNUNET_PACKED; | ||
169 | |||
170 | /** | ||
171 | * Was the label found in the database?? | ||
172 | * #GNUNET_YES or #GNUNET_NO | ||
173 | */ | ||
174 | uint16_t found GNUNET_PACKED; | ||
175 | |||
176 | /** | ||
177 | * The private key of the authority. | ||
178 | */ | ||
179 | struct GNUNET_IDENTITY_PrivateKey private_key; | ||
180 | |||
181 | /* followed by: | ||
182 | * name with length name_len | ||
183 | * serialized record data with rd_count records | ||
184 | */ | ||
185 | }; | ||
186 | |||
187 | |||
188 | /** | ||
189 | * Lookup a name for a zone hash | ||
190 | */ | ||
191 | struct ZoneToNameMessage | ||
192 | { | ||
193 | /** | ||
194 | * Type will be #GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_TO_NAME | ||
195 | */ | ||
196 | struct GNUNET_NAMESTORE_Header gns_header; | ||
197 | |||
198 | /** | ||
199 | * The private key of the zone to look up in | ||
200 | */ | ||
201 | struct GNUNET_IDENTITY_PrivateKey zone; | ||
202 | |||
203 | /** | ||
204 | * The public key of the target zone | ||
205 | */ | ||
206 | struct GNUNET_IDENTITY_PublicKey value_zone; | ||
207 | }; | ||
208 | |||
209 | |||
210 | /** | ||
211 | * Respone for zone to name lookup | ||
212 | */ | ||
213 | struct ZoneToNameResponseMessage | ||
214 | { | ||
215 | /** | ||
216 | * Type will be #GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_TO_NAME_RESPONSE | ||
217 | */ | ||
218 | struct GNUNET_NAMESTORE_Header gns_header; | ||
219 | |||
220 | /** | ||
221 | * Length of the name | ||
222 | */ | ||
223 | uint16_t name_len GNUNET_PACKED; | ||
224 | |||
225 | /** | ||
226 | * Length of serialized record data | ||
227 | */ | ||
228 | uint16_t rd_len GNUNET_PACKED; | ||
229 | |||
230 | /** | ||
231 | * Number of records contained | ||
232 | */ | ||
233 | uint16_t rd_count GNUNET_PACKED; | ||
234 | |||
235 | /** | ||
236 | * result in NBO: #GNUNET_OK on success, #GNUNET_NO if there were no | ||
237 | * results, #GNUNET_SYSERR on error | ||
238 | */ | ||
239 | int16_t res GNUNET_PACKED; | ||
240 | |||
241 | /** | ||
242 | * The private key of the zone that contained the name. | ||
243 | */ | ||
244 | struct GNUNET_IDENTITY_PrivateKey zone; | ||
245 | |||
246 | /* followed by: | ||
247 | * name with length name_len | ||
248 | * serialized record data with rd_count records | ||
249 | */ | ||
250 | }; | ||
251 | |||
252 | |||
253 | /** | ||
254 | * Record is returned from the namestore (as authority). | ||
255 | */ | ||
256 | struct RecordResultMessage | ||
257 | { | ||
258 | /** | ||
259 | * Type will be #GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_RESULT | ||
260 | */ | ||
261 | struct GNUNET_NAMESTORE_Header gns_header; | ||
262 | |||
263 | /** | ||
264 | * Name length | ||
265 | */ | ||
266 | uint16_t name_len GNUNET_PACKED; | ||
267 | |||
268 | /** | ||
269 | * Length of serialized record data | ||
270 | */ | ||
271 | uint16_t rd_len GNUNET_PACKED; | ||
272 | |||
273 | /** | ||
274 | * Number of records contained | ||
275 | */ | ||
276 | uint16_t rd_count GNUNET_PACKED; | ||
277 | |||
278 | /** | ||
279 | * always zero (for alignment) | ||
280 | */ | ||
281 | uint16_t reserved GNUNET_PACKED; | ||
282 | |||
283 | /** | ||
284 | * The private key of the authority. | ||
285 | */ | ||
286 | struct GNUNET_IDENTITY_PrivateKey private_key; | ||
287 | |||
288 | /* followed by: | ||
289 | * name with length name_len | ||
290 | * serialized record data with rd_count records | ||
291 | */ | ||
292 | }; | ||
293 | |||
294 | |||
295 | /** | ||
296 | * Start monitoring a zone. | ||
297 | */ | ||
298 | struct ZoneMonitorStartMessage | ||
299 | { | ||
300 | /** | ||
301 | * Type will be #GNUNET_MESSAGE_TYPE_NAMESTORE_MONITOR_START | ||
302 | */ | ||
303 | struct GNUNET_MessageHeader header; | ||
304 | |||
305 | /** | ||
306 | * #GNUNET_YES to first iterate over all records, | ||
307 | * #GNUNET_NO to only monitor changes.o | ||
308 | */ | ||
309 | uint32_t iterate_first GNUNET_PACKED; | ||
310 | |||
311 | /** | ||
312 | * Zone key. | ||
313 | */ | ||
314 | struct GNUNET_IDENTITY_PrivateKey zone; | ||
315 | }; | ||
316 | |||
317 | |||
318 | /** | ||
319 | * Ask for next result of zone iteration for the given operation | ||
320 | */ | ||
321 | struct ZoneMonitorNextMessage | ||
322 | { | ||
323 | /** | ||
324 | * Type will be #GNUNET_MESSAGE_TYPE_NAMESTORE_MONITOR_NEXT | ||
325 | */ | ||
326 | struct GNUNET_MessageHeader header; | ||
327 | |||
328 | /** | ||
329 | * Always zero. | ||
330 | */ | ||
331 | uint32_t reserved; | ||
332 | |||
333 | /** | ||
334 | * Number of records to return to the iterator in one shot | ||
335 | * (before #GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_MONITOR_NEXT | ||
336 | * should be send again). In NBO. | ||
337 | */ | ||
338 | uint64_t limit; | ||
339 | }; | ||
340 | |||
341 | |||
342 | /** | ||
343 | * Start a zone iteration for the given zone | ||
344 | */ | ||
345 | struct ZoneIterationStartMessage | ||
346 | { | ||
347 | /** | ||
348 | * Type will be #GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_ITERATION_START | ||
349 | */ | ||
350 | struct GNUNET_NAMESTORE_Header gns_header; | ||
351 | |||
352 | /** | ||
353 | * Zone key. All zeros for "all zones". | ||
354 | */ | ||
355 | struct GNUNET_IDENTITY_PrivateKey zone; | ||
356 | }; | ||
357 | |||
358 | |||
359 | /** | ||
360 | * Ask for next result of zone iteration for the given operation | ||
361 | */ | ||
362 | struct ZoneIterationNextMessage | ||
363 | { | ||
364 | /** | ||
365 | * Type will be #GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_ITERATION_NEXT | ||
366 | */ | ||
367 | struct GNUNET_NAMESTORE_Header gns_header; | ||
368 | |||
369 | /** | ||
370 | * Number of records to return to the iterator in one shot | ||
371 | * (before #GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_ITERATION_NEXT | ||
372 | * should be send again). In NBO. | ||
373 | */ | ||
374 | uint64_t limit; | ||
375 | }; | ||
376 | |||
377 | |||
378 | /** | ||
379 | * Stop zone iteration for the given operation | ||
380 | */ | ||
381 | struct ZoneIterationStopMessage | ||
382 | { | ||
383 | /** | ||
384 | * Type will be #GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_ITERATION_STOP | ||
385 | */ | ||
386 | struct GNUNET_NAMESTORE_Header gns_header; | ||
387 | }; | ||
388 | |||
389 | |||
390 | GNUNET_NETWORK_STRUCT_END | ||
391 | |||
392 | |||
393 | /* end of namestore.h */ | ||
394 | #endif | ||
diff --git a/src/namestore/namestore_api.c b/src/namestore/namestore_api.c deleted file mode 100644 index b24db9b26..000000000 --- a/src/namestore/namestore_api.c +++ /dev/null | |||
@@ -1,1307 +0,0 @@ | |||
1 | /* | ||
2 | This file is part of GNUnet. | ||
3 | Copyright (C) 2010-2013, 2016 GNUnet e.V. | ||
4 | |||
5 | GNUnet is free software: you can redistribute it and/or modify it | ||
6 | under the terms of the GNU Affero General Public License as published | ||
7 | by the Free Software Foundation, either version 3 of the License, | ||
8 | or (at your option) any later version. | ||
9 | |||
10 | GNUnet is distributed in the hope that it will be useful, but | ||
11 | WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
13 | Affero General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU Affero General Public License | ||
16 | along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
17 | |||
18 | SPDX-License-Identifier: AGPL3.0-or-later | ||
19 | */ | ||
20 | |||
21 | /** | ||
22 | * @file namestore/namestore_api.c | ||
23 | * @brief API to access the NAMESTORE service | ||
24 | * @author Martin Schanzenbach | ||
25 | * @author Matthias Wachs | ||
26 | * @author Christian Grothoff | ||
27 | */ | ||
28 | |||
29 | #include "platform.h" | ||
30 | #include "gnunet_util_lib.h" | ||
31 | #include "gnunet_crypto_lib.h" | ||
32 | #include "gnunet_constants.h" | ||
33 | #include "gnunet_dnsparser_lib.h" | ||
34 | #include "gnunet_arm_service.h" | ||
35 | #include "gnunet_signatures.h" | ||
36 | #include "gnunet_gns_service.h" | ||
37 | #include "gnunet_namestore_service.h" | ||
38 | #include "namestore.h" | ||
39 | |||
40 | |||
41 | #define LOG(kind, ...) GNUNET_log_from (kind, "namestore-api", __VA_ARGS__) | ||
42 | |||
43 | /** | ||
44 | * We grant the namestore up to 1 minute of latency, if it is slower than | ||
45 | * that, store queries will fail. | ||
46 | */ | ||
47 | #define NAMESTORE_DELAY_TOLERANCE GNUNET_TIME_UNIT_MINUTES | ||
48 | |||
49 | /** | ||
50 | * An QueueEntry used to store information for a pending | ||
51 | * NAMESTORE record operation | ||
52 | */ | ||
53 | struct GNUNET_NAMESTORE_QueueEntry | ||
54 | { | ||
55 | /** | ||
56 | * Kept in a DLL. | ||
57 | */ | ||
58 | struct GNUNET_NAMESTORE_QueueEntry *next; | ||
59 | |||
60 | /** | ||
61 | * Kept in a DLL. | ||
62 | */ | ||
63 | struct GNUNET_NAMESTORE_QueueEntry *prev; | ||
64 | |||
65 | /** | ||
66 | * Main handle to access the namestore. | ||
67 | */ | ||
68 | struct GNUNET_NAMESTORE_Handle *h; | ||
69 | |||
70 | /** | ||
71 | * Continuation to call | ||
72 | */ | ||
73 | GNUNET_NAMESTORE_ContinuationWithStatus cont; | ||
74 | |||
75 | /** | ||
76 | * Closure for @e cont. | ||
77 | */ | ||
78 | void *cont_cls; | ||
79 | |||
80 | /** | ||
81 | * Function to call with the records we get back; or NULL. | ||
82 | */ | ||
83 | GNUNET_NAMESTORE_RecordMonitor proc; | ||
84 | |||
85 | /** | ||
86 | * Closure for @e proc. | ||
87 | */ | ||
88 | void *proc_cls; | ||
89 | |||
90 | /** | ||
91 | * Function to call on errors. | ||
92 | */ | ||
93 | GNUNET_SCHEDULER_TaskCallback error_cb; | ||
94 | |||
95 | /** | ||
96 | * Closure for @e error_cb. | ||
97 | */ | ||
98 | void *error_cb_cls; | ||
99 | |||
100 | /** | ||
101 | * Envelope of the message to send to the service, if not yet | ||
102 | * sent. | ||
103 | */ | ||
104 | struct GNUNET_MQ_Envelope *env; | ||
105 | |||
106 | /** | ||
107 | * Task scheduled to warn us if the namestore is way too slow. | ||
108 | */ | ||
109 | struct GNUNET_SCHEDULER_Task *timeout_task; | ||
110 | |||
111 | /** | ||
112 | * The operation id this zone iteration operation has | ||
113 | */ | ||
114 | uint32_t op_id; | ||
115 | }; | ||
116 | |||
117 | |||
118 | /** | ||
119 | * Handle for a zone iterator operation | ||
120 | */ | ||
121 | struct GNUNET_NAMESTORE_ZoneIterator | ||
122 | { | ||
123 | /** | ||
124 | * Kept in a DLL. | ||
125 | */ | ||
126 | struct GNUNET_NAMESTORE_ZoneIterator *next; | ||
127 | |||
128 | /** | ||
129 | * Kept in a DLL. | ||
130 | */ | ||
131 | struct GNUNET_NAMESTORE_ZoneIterator *prev; | ||
132 | |||
133 | /** | ||
134 | * Main handle to access the namestore. | ||
135 | */ | ||
136 | struct GNUNET_NAMESTORE_Handle *h; | ||
137 | |||
138 | /** | ||
139 | * Function to call on completion. | ||
140 | */ | ||
141 | GNUNET_SCHEDULER_TaskCallback finish_cb; | ||
142 | |||
143 | /** | ||
144 | * Closure for @e error_cb. | ||
145 | */ | ||
146 | void *finish_cb_cls; | ||
147 | |||
148 | /** | ||
149 | * The continuation to call with the results | ||
150 | */ | ||
151 | GNUNET_NAMESTORE_RecordMonitor proc; | ||
152 | |||
153 | /** | ||
154 | * Closure for @e proc. | ||
155 | */ | ||
156 | void *proc_cls; | ||
157 | |||
158 | /** | ||
159 | * Function to call on errors. | ||
160 | */ | ||
161 | GNUNET_SCHEDULER_TaskCallback error_cb; | ||
162 | |||
163 | /** | ||
164 | * Closure for @e error_cb. | ||
165 | */ | ||
166 | void *error_cb_cls; | ||
167 | |||
168 | /** | ||
169 | * Envelope of the message to send to the service, if not yet | ||
170 | * sent. | ||
171 | */ | ||
172 | struct GNUNET_MQ_Envelope *env; | ||
173 | |||
174 | /** | ||
175 | * Private key of the zone. | ||
176 | */ | ||
177 | struct GNUNET_IDENTITY_PrivateKey zone; | ||
178 | |||
179 | /** | ||
180 | * The operation id this zone iteration operation has | ||
181 | */ | ||
182 | uint32_t op_id; | ||
183 | }; | ||
184 | |||
185 | |||
186 | /** | ||
187 | * Connection to the NAMESTORE service. | ||
188 | */ | ||
189 | struct GNUNET_NAMESTORE_Handle | ||
190 | { | ||
191 | /** | ||
192 | * Configuration to use. | ||
193 | */ | ||
194 | const struct GNUNET_CONFIGURATION_Handle *cfg; | ||
195 | |||
196 | /** | ||
197 | * Connection to the service (if available). | ||
198 | */ | ||
199 | struct GNUNET_MQ_Handle *mq; | ||
200 | |||
201 | /** | ||
202 | * Head of pending namestore queue entries | ||
203 | */ | ||
204 | struct GNUNET_NAMESTORE_QueueEntry *op_head; | ||
205 | |||
206 | /** | ||
207 | * Tail of pending namestore queue entries | ||
208 | */ | ||
209 | struct GNUNET_NAMESTORE_QueueEntry *op_tail; | ||
210 | |||
211 | /** | ||
212 | * Head of pending namestore zone iterator entries | ||
213 | */ | ||
214 | struct GNUNET_NAMESTORE_ZoneIterator *z_head; | ||
215 | |||
216 | /** | ||
217 | * Tail of pending namestore zone iterator entries | ||
218 | */ | ||
219 | struct GNUNET_NAMESTORE_ZoneIterator *z_tail; | ||
220 | |||
221 | /** | ||
222 | * Reconnect task | ||
223 | */ | ||
224 | struct GNUNET_SCHEDULER_Task *reconnect_task; | ||
225 | |||
226 | /** | ||
227 | * Delay introduced before we reconnect. | ||
228 | */ | ||
229 | struct GNUNET_TIME_Relative reconnect_delay; | ||
230 | |||
231 | /** | ||
232 | * Should we reconnect to service due to some serious error? | ||
233 | */ | ||
234 | int reconnect; | ||
235 | |||
236 | /** | ||
237 | * The last operation id used for a NAMESTORE operation | ||
238 | */ | ||
239 | uint32_t last_op_id_used; | ||
240 | }; | ||
241 | |||
242 | |||
243 | /** | ||
244 | * Disconnect from service and then reconnect. | ||
245 | * | ||
246 | * @param h our handle | ||
247 | */ | ||
248 | static void | ||
249 | force_reconnect (struct GNUNET_NAMESTORE_Handle *h); | ||
250 | |||
251 | |||
252 | /** | ||
253 | * Find the queue entry that matches the @a rid | ||
254 | * | ||
255 | * @param h namestore handle | ||
256 | * @param rid id to look up | ||
257 | * @return NULL if @a rid was not found | ||
258 | */ | ||
259 | static struct GNUNET_NAMESTORE_QueueEntry * | ||
260 | find_qe (struct GNUNET_NAMESTORE_Handle *h, uint32_t rid) | ||
261 | { | ||
262 | struct GNUNET_NAMESTORE_QueueEntry *qe; | ||
263 | |||
264 | for (qe = h->op_head; qe != NULL; qe = qe->next) | ||
265 | if (qe->op_id == rid) | ||
266 | return qe; | ||
267 | return NULL; | ||
268 | } | ||
269 | |||
270 | |||
271 | /** | ||
272 | * Find the zone iteration entry that matches the @a rid | ||
273 | * | ||
274 | * @param h namestore handle | ||
275 | * @param rid id to look up | ||
276 | * @return NULL if @a rid was not found | ||
277 | */ | ||
278 | static struct GNUNET_NAMESTORE_ZoneIterator * | ||
279 | find_zi (struct GNUNET_NAMESTORE_Handle *h, uint32_t rid) | ||
280 | { | ||
281 | struct GNUNET_NAMESTORE_ZoneIterator *ze; | ||
282 | |||
283 | for (ze = h->z_head; ze != NULL; ze = ze->next) | ||
284 | if (ze->op_id == rid) | ||
285 | return ze; | ||
286 | return NULL; | ||
287 | } | ||
288 | |||
289 | |||
290 | /** | ||
291 | * Free @a qe. | ||
292 | * | ||
293 | * @param qe entry to free | ||
294 | */ | ||
295 | static void | ||
296 | free_qe (struct GNUNET_NAMESTORE_QueueEntry *qe) | ||
297 | { | ||
298 | struct GNUNET_NAMESTORE_Handle *h = qe->h; | ||
299 | |||
300 | GNUNET_CONTAINER_DLL_remove (h->op_head, h->op_tail, qe); | ||
301 | if (NULL != qe->env) | ||
302 | GNUNET_MQ_discard (qe->env); | ||
303 | if (NULL != qe->timeout_task) | ||
304 | GNUNET_SCHEDULER_cancel (qe->timeout_task); | ||
305 | GNUNET_free (qe); | ||
306 | } | ||
307 | |||
308 | |||
309 | /** | ||
310 | * Free @a ze. | ||
311 | * | ||
312 | * @param ze entry to free | ||
313 | */ | ||
314 | static void | ||
315 | free_ze (struct GNUNET_NAMESTORE_ZoneIterator *ze) | ||
316 | { | ||
317 | struct GNUNET_NAMESTORE_Handle *h = ze->h; | ||
318 | |||
319 | GNUNET_CONTAINER_DLL_remove (h->z_head, h->z_tail, ze); | ||
320 | if (NULL != ze->env) | ||
321 | GNUNET_MQ_discard (ze->env); | ||
322 | GNUNET_free (ze); | ||
323 | } | ||
324 | |||
325 | |||
326 | /** | ||
327 | * Check that @a rd_buf of length @a rd_len contains | ||
328 | * @a rd_count records. | ||
329 | * | ||
330 | * @param rd_len length of @a rd_buf | ||
331 | * @param rd_buf buffer with serialized records | ||
332 | * @param rd_count number of records expected | ||
333 | * @return #GNUNET_OK if @a rd_buf is well-formed | ||
334 | */ | ||
335 | static int | ||
336 | check_rd (size_t rd_len, const void *rd_buf, unsigned int rd_count) | ||
337 | { | ||
338 | struct GNUNET_GNSRECORD_Data rd[rd_count]; | ||
339 | |||
340 | if (GNUNET_OK != | ||
341 | GNUNET_GNSRECORD_records_deserialize (rd_len, rd_buf, rd_count, rd)) | ||
342 | { | ||
343 | GNUNET_break (0); | ||
344 | return GNUNET_SYSERR; | ||
345 | } | ||
346 | return GNUNET_OK; | ||
347 | } | ||
348 | |||
349 | |||
350 | /** | ||
351 | * Handle an incoming message of type | ||
352 | * #GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_STORE_RESPONSE | ||
353 | * | ||
354 | * @param cls | ||
355 | * @param msg the message we received | ||
356 | */ | ||
357 | static void | ||
358 | handle_record_store_response (void *cls, | ||
359 | const struct RecordStoreResponseMessage *msg) | ||
360 | { | ||
361 | struct GNUNET_NAMESTORE_Handle *h = cls; | ||
362 | struct GNUNET_NAMESTORE_QueueEntry *qe; | ||
363 | int res; | ||
364 | const char *emsg; | ||
365 | |||
366 | qe = find_qe (h, ntohl (msg->gns_header.r_id)); | ||
367 | res = ntohl (msg->op_result); | ||
368 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
369 | "Received RECORD_STORE_RESPONSE with result %d\n", | ||
370 | res); | ||
371 | /* TODO: add actual error message from namestore to response... */ | ||
372 | if (GNUNET_SYSERR == res) | ||
373 | emsg = _ ("Namestore failed to store record\n"); | ||
374 | else | ||
375 | emsg = NULL; | ||
376 | if (NULL == qe) | ||
377 | return; | ||
378 | if (NULL != qe->cont) | ||
379 | qe->cont (qe->cont_cls, res, emsg); | ||
380 | free_qe (qe); | ||
381 | } | ||
382 | |||
383 | |||
384 | /** | ||
385 | * Check validity of an incoming message of type | ||
386 | * #GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_LOOKUP_RESPONSE | ||
387 | * | ||
388 | * @param cls | ||
389 | * @param msg the message we received | ||
390 | * @return #GNUNET_OK on success, #GNUNET_SYSERR on error | ||
391 | */ | ||
392 | static int | ||
393 | check_lookup_result (void *cls, const struct LabelLookupResponseMessage *msg) | ||
394 | { | ||
395 | const char *name; | ||
396 | size_t exp_msg_len; | ||
397 | size_t msg_len; | ||
398 | size_t name_len; | ||
399 | size_t rd_len; | ||
400 | |||
401 | (void) cls; | ||
402 | rd_len = ntohs (msg->rd_len); | ||
403 | msg_len = ntohs (msg->gns_header.header.size); | ||
404 | name_len = ntohs (msg->name_len); | ||
405 | exp_msg_len = sizeof(*msg) + name_len + rd_len; | ||
406 | if (msg_len != exp_msg_len) | ||
407 | { | ||
408 | GNUNET_break (0); | ||
409 | return GNUNET_SYSERR; | ||
410 | } | ||
411 | name = (const char *) &msg[1]; | ||
412 | if ((name_len > 0) && ('\0' != name[name_len - 1])) | ||
413 | { | ||
414 | GNUNET_break (0); | ||
415 | return GNUNET_SYSERR; | ||
416 | } | ||
417 | if (GNUNET_NO == ntohs (msg->found)) | ||
418 | { | ||
419 | if (0 != ntohs (msg->rd_count)) | ||
420 | { | ||
421 | GNUNET_break (0); | ||
422 | return GNUNET_SYSERR; | ||
423 | } | ||
424 | return GNUNET_OK; | ||
425 | } | ||
426 | return check_rd (rd_len, &name[name_len], ntohs (msg->rd_count)); | ||
427 | } | ||
428 | |||
429 | |||
430 | /** | ||
431 | * Handle an incoming message of type | ||
432 | * #GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_LOOKUP_RESPONSE | ||
433 | * | ||
434 | * @param cls | ||
435 | * @param msg the message we received | ||
436 | */ | ||
437 | static void | ||
438 | handle_lookup_result (void *cls, const struct LabelLookupResponseMessage *msg) | ||
439 | { | ||
440 | struct GNUNET_NAMESTORE_Handle *h = cls; | ||
441 | struct GNUNET_NAMESTORE_QueueEntry *qe; | ||
442 | const char *name; | ||
443 | const char *rd_tmp; | ||
444 | size_t name_len; | ||
445 | size_t rd_len; | ||
446 | unsigned int rd_count; | ||
447 | |||
448 | LOG (GNUNET_ERROR_TYPE_DEBUG, "Received RECORD_LOOKUP_RESULT\n"); | ||
449 | qe = find_qe (h, ntohl (msg->gns_header.r_id)); | ||
450 | if (NULL == qe) | ||
451 | return; | ||
452 | rd_len = ntohs (msg->rd_len); | ||
453 | rd_count = ntohs (msg->rd_count); | ||
454 | name_len = ntohs (msg->name_len); | ||
455 | name = (const char *) &msg[1]; | ||
456 | if (GNUNET_NO == ntohs (msg->found)) | ||
457 | { | ||
458 | /* label was not in namestore */ | ||
459 | if (NULL != qe->proc) | ||
460 | qe->proc (qe->proc_cls, &msg->private_key, name, 0, NULL); | ||
461 | free_qe (qe); | ||
462 | return; | ||
463 | } | ||
464 | |||
465 | rd_tmp = &name[name_len]; | ||
466 | { | ||
467 | struct GNUNET_GNSRECORD_Data rd[rd_count]; | ||
468 | |||
469 | GNUNET_assert ( | ||
470 | GNUNET_OK == | ||
471 | GNUNET_GNSRECORD_records_deserialize (rd_len, rd_tmp, rd_count, rd)); | ||
472 | if (0 == name_len) | ||
473 | name = NULL; | ||
474 | if (NULL != qe->proc) | ||
475 | qe->proc (qe->proc_cls, | ||
476 | &msg->private_key, | ||
477 | name, | ||
478 | rd_count, | ||
479 | (rd_count > 0) ? rd : NULL); | ||
480 | } | ||
481 | free_qe (qe); | ||
482 | } | ||
483 | |||
484 | |||
485 | /** | ||
486 | * Handle an incoming message of type | ||
487 | * #GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_RESULT | ||
488 | * | ||
489 | * @param cls | ||
490 | * @param msg the message we received | ||
491 | * @return #GNUNET_OK on success, #GNUNET_SYSERR on error | ||
492 | */ | ||
493 | static int | ||
494 | check_record_result (void *cls, const struct RecordResultMessage *msg) | ||
495 | { | ||
496 | static struct GNUNET_IDENTITY_PrivateKey priv_dummy; | ||
497 | const char *name; | ||
498 | size_t msg_len; | ||
499 | size_t name_len; | ||
500 | size_t rd_len; | ||
501 | |||
502 | (void) cls; | ||
503 | rd_len = ntohs (msg->rd_len); | ||
504 | msg_len = ntohs (msg->gns_header.header.size); | ||
505 | name_len = ntohs (msg->name_len); | ||
506 | if (0 != ntohs (msg->reserved)) | ||
507 | { | ||
508 | GNUNET_break (0); | ||
509 | return GNUNET_SYSERR; | ||
510 | } | ||
511 | if (msg_len != sizeof(struct RecordResultMessage) + name_len + rd_len) | ||
512 | { | ||
513 | GNUNET_break (0); | ||
514 | return GNUNET_SYSERR; | ||
515 | } | ||
516 | name = (const char *) &msg[1]; | ||
517 | if ((0 == name_len) || ('\0' != name[name_len - 1])) | ||
518 | { | ||
519 | GNUNET_break (0); | ||
520 | return GNUNET_SYSERR; | ||
521 | } | ||
522 | if (0 == GNUNET_memcmp (&msg->private_key, &priv_dummy)) | ||
523 | { | ||
524 | GNUNET_break (0); | ||
525 | return GNUNET_SYSERR; | ||
526 | } | ||
527 | return check_rd (rd_len, &name[name_len], ntohs (msg->rd_count)); | ||
528 | } | ||
529 | |||
530 | |||
531 | /** | ||
532 | * Handle an incoming message of type | ||
533 | * #GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_RESULT | ||
534 | * | ||
535 | * @param cls | ||
536 | * @param msg the message we received | ||
537 | */ | ||
538 | static void | ||
539 | handle_record_result (void *cls, const struct RecordResultMessage *msg) | ||
540 | { | ||
541 | struct GNUNET_NAMESTORE_Handle *h = cls; | ||
542 | struct GNUNET_NAMESTORE_QueueEntry *qe; | ||
543 | struct GNUNET_NAMESTORE_ZoneIterator *ze; | ||
544 | const char *name; | ||
545 | const char *rd_tmp; | ||
546 | size_t name_len; | ||
547 | size_t rd_len; | ||
548 | unsigned int rd_count; | ||
549 | |||
550 | LOG (GNUNET_ERROR_TYPE_DEBUG, "Received RECORD_RESULT\n"); | ||
551 | rd_len = ntohs (msg->rd_len); | ||
552 | rd_count = ntohs (msg->rd_count); | ||
553 | name_len = ntohs (msg->name_len); | ||
554 | ze = find_zi (h, ntohl (msg->gns_header.r_id)); | ||
555 | qe = find_qe (h, ntohl (msg->gns_header.r_id)); | ||
556 | if ((NULL == ze) && (NULL == qe)) | ||
557 | return; /* rid not found */ | ||
558 | if ((NULL != ze) && (NULL != qe)) | ||
559 | { | ||
560 | GNUNET_break (0); /* rid ambiguous */ | ||
561 | force_reconnect (h); | ||
562 | return; | ||
563 | } | ||
564 | name = (const char *) &msg[1]; | ||
565 | rd_tmp = &name[name_len]; | ||
566 | { | ||
567 | struct GNUNET_GNSRECORD_Data rd[rd_count]; | ||
568 | |||
569 | GNUNET_assert ( | ||
570 | GNUNET_OK == | ||
571 | GNUNET_GNSRECORD_records_deserialize (rd_len, rd_tmp, rd_count, rd)); | ||
572 | if (0 == name_len) | ||
573 | name = NULL; | ||
574 | if (NULL != qe) | ||
575 | { | ||
576 | if (NULL != qe->proc) | ||
577 | qe->proc (qe->proc_cls, | ||
578 | &msg->private_key, | ||
579 | name, | ||
580 | rd_count, | ||
581 | (rd_count > 0) ? rd : NULL); | ||
582 | free_qe (qe); | ||
583 | return; | ||
584 | } | ||
585 | if (NULL != ze) | ||
586 | { | ||
587 | if (NULL != ze->proc) | ||
588 | ze->proc (ze->proc_cls, &msg->private_key, name, rd_count, rd); | ||
589 | return; | ||
590 | } | ||
591 | } | ||
592 | GNUNET_assert (0); | ||
593 | } | ||
594 | |||
595 | |||
596 | /** | ||
597 | * Handle an incoming message of type | ||
598 | * #GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_RESULT_END | ||
599 | * | ||
600 | * @param cls | ||
601 | * @param msg the message we received | ||
602 | */ | ||
603 | static void | ||
604 | handle_record_result_end (void *cls, const struct GNUNET_NAMESTORE_Header *msg) | ||
605 | { | ||
606 | struct GNUNET_NAMESTORE_Handle *h = cls; | ||
607 | struct GNUNET_NAMESTORE_QueueEntry *qe; | ||
608 | struct GNUNET_NAMESTORE_ZoneIterator *ze; | ||
609 | |||
610 | LOG (GNUNET_ERROR_TYPE_DEBUG, "Received RECORD_RESULT_END\n"); | ||
611 | ze = find_zi (h, ntohl (msg->r_id)); | ||
612 | qe = find_qe (h, ntohl (msg->r_id)); | ||
613 | if ((NULL == ze) && (NULL == qe)) | ||
614 | return; /* rid not found */ | ||
615 | if ((NULL != ze) && (NULL != qe)) | ||
616 | { | ||
617 | GNUNET_break (0); /* rid ambiguous */ | ||
618 | force_reconnect (h); | ||
619 | return; | ||
620 | } | ||
621 | LOG (GNUNET_ERROR_TYPE_DEBUG, "Zone iteration completed!\n"); | ||
622 | if (NULL == ze) | ||
623 | { | ||
624 | GNUNET_break (0); | ||
625 | force_reconnect (h); | ||
626 | return; | ||
627 | } | ||
628 | if (NULL != ze->finish_cb) | ||
629 | ze->finish_cb (ze->finish_cb_cls); | ||
630 | free_ze (ze); | ||
631 | } | ||
632 | |||
633 | |||
634 | /** | ||
635 | * Handle an incoming message of type | ||
636 | * #GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_TO_NAME_RESPONSE. | ||
637 | * | ||
638 | * @param qe the respective entry in the message queue | ||
639 | * @param msg the message we received | ||
640 | * @return #GNUNET_OK on success, #GNUNET_SYSERR if message malformed | ||
641 | */ | ||
642 | static int | ||
643 | check_zone_to_name_response (void *cls, | ||
644 | const struct ZoneToNameResponseMessage *msg) | ||
645 | { | ||
646 | size_t name_len; | ||
647 | size_t rd_ser_len; | ||
648 | const char *name_tmp; | ||
649 | |||
650 | (void) cls; | ||
651 | if (GNUNET_OK != ntohs (msg->res)) | ||
652 | return GNUNET_OK; | ||
653 | name_len = ntohs (msg->name_len); | ||
654 | rd_ser_len = ntohs (msg->rd_len); | ||
655 | if (ntohs (msg->gns_header.header.size) != | ||
656 | sizeof(struct ZoneToNameResponseMessage) + name_len + rd_ser_len) | ||
657 | { | ||
658 | GNUNET_break (0); | ||
659 | return GNUNET_SYSERR; | ||
660 | } | ||
661 | name_tmp = (const char *) &msg[1]; | ||
662 | if ((name_len > 0) && ('\0' != name_tmp[name_len - 1])) | ||
663 | { | ||
664 | GNUNET_break (0); | ||
665 | return GNUNET_SYSERR; | ||
666 | } | ||
667 | return check_rd (rd_ser_len, &name_tmp[name_len], ntohs (msg->rd_count)); | ||
668 | } | ||
669 | |||
670 | |||
671 | /** | ||
672 | * Handle an incoming message of type | ||
673 | * #GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_TO_NAME_RESPONSE. | ||
674 | * | ||
675 | * @param cls | ||
676 | * @param msg the message we received | ||
677 | */ | ||
678 | static void | ||
679 | handle_zone_to_name_response (void *cls, | ||
680 | const struct ZoneToNameResponseMessage *msg) | ||
681 | { | ||
682 | struct GNUNET_NAMESTORE_Handle *h = cls; | ||
683 | struct GNUNET_NAMESTORE_QueueEntry *qe; | ||
684 | int res; | ||
685 | size_t name_len; | ||
686 | size_t rd_ser_len; | ||
687 | unsigned int rd_count; | ||
688 | const char *name_tmp; | ||
689 | const char *rd_tmp; | ||
690 | |||
691 | LOG (GNUNET_ERROR_TYPE_DEBUG, "Received ZONE_TO_NAME_RESPONSE\n"); | ||
692 | qe = find_qe (h, ntohl (msg->gns_header.r_id)); | ||
693 | if (NULL == qe) | ||
694 | { | ||
695 | LOG (GNUNET_ERROR_TYPE_WARNING, | ||
696 | "Response queue already gone...\n"); | ||
697 | return; | ||
698 | } | ||
699 | res = ntohs (msg->res); | ||
700 | switch (res) | ||
701 | { | ||
702 | case GNUNET_SYSERR: | ||
703 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
704 | "An error occurred during zone to name operation\n"); | ||
705 | break; | ||
706 | |||
707 | case GNUNET_NO: | ||
708 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
709 | "Namestore has no result for zone to name mapping \n"); | ||
710 | if (NULL != qe->proc) | ||
711 | qe->proc (qe->proc_cls, &msg->zone, NULL, 0, NULL); | ||
712 | free_qe (qe); | ||
713 | return; | ||
714 | |||
715 | case GNUNET_YES: | ||
716 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
717 | "Namestore has result for zone to name mapping \n"); | ||
718 | name_len = ntohs (msg->name_len); | ||
719 | rd_count = ntohs (msg->rd_count); | ||
720 | rd_ser_len = ntohs (msg->rd_len); | ||
721 | name_tmp = (const char *) &msg[1]; | ||
722 | rd_tmp = &name_tmp[name_len]; | ||
723 | { | ||
724 | struct GNUNET_GNSRECORD_Data rd[rd_count]; | ||
725 | |||
726 | GNUNET_assert (GNUNET_OK == | ||
727 | GNUNET_GNSRECORD_records_deserialize (rd_ser_len, | ||
728 | rd_tmp, | ||
729 | rd_count, | ||
730 | rd)); | ||
731 | /* normal end, call continuation with result */ | ||
732 | if (NULL != qe->proc) | ||
733 | qe->proc (qe->proc_cls, &msg->zone, name_tmp, rd_count, rd); | ||
734 | /* return is important here: break would call continuation with error! */ | ||
735 | free_qe (qe); | ||
736 | return; | ||
737 | } | ||
738 | |||
739 | default: | ||
740 | GNUNET_break (0); | ||
741 | force_reconnect (h); | ||
742 | return; | ||
743 | } | ||
744 | /* error case, call continuation with error */ | ||
745 | if (NULL != qe->error_cb) | ||
746 | qe->error_cb (qe->error_cb_cls); | ||
747 | free_qe (qe); | ||
748 | } | ||
749 | |||
750 | |||
751 | /** | ||
752 | * Generic error handler, called with the appropriate error code and | ||
753 | * the same closure specified at the creation of the message queue. | ||
754 | * Not every message queue implementation supports an error handler. | ||
755 | * | ||
756 | * @param cls closure with the `struct GNUNET_NAMESTORE_Handle *` | ||
757 | * @param error error code | ||
758 | */ | ||
759 | static void | ||
760 | mq_error_handler (void *cls, enum GNUNET_MQ_Error error) | ||
761 | { | ||
762 | struct GNUNET_NAMESTORE_Handle *h = cls; | ||
763 | |||
764 | (void) error; | ||
765 | force_reconnect (h); | ||
766 | } | ||
767 | |||
768 | |||
769 | /** | ||
770 | * Reconnect to namestore service. | ||
771 | * | ||
772 | * @param h the handle to the NAMESTORE service | ||
773 | */ | ||
774 | static void | ||
775 | reconnect (struct GNUNET_NAMESTORE_Handle *h) | ||
776 | { | ||
777 | struct GNUNET_MQ_MessageHandler handlers[] = | ||
778 | { GNUNET_MQ_hd_fixed_size (record_store_response, | ||
779 | GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_STORE_RESPONSE, | ||
780 | struct RecordStoreResponseMessage, | ||
781 | h), | ||
782 | GNUNET_MQ_hd_var_size (zone_to_name_response, | ||
783 | GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_TO_NAME_RESPONSE, | ||
784 | struct ZoneToNameResponseMessage, | ||
785 | h), | ||
786 | GNUNET_MQ_hd_var_size (record_result, | ||
787 | GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_RESULT, | ||
788 | struct RecordResultMessage, | ||
789 | h), | ||
790 | GNUNET_MQ_hd_fixed_size (record_result_end, | ||
791 | GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_RESULT_END, | ||
792 | struct GNUNET_NAMESTORE_Header, | ||
793 | h), | ||
794 | GNUNET_MQ_hd_var_size (lookup_result, | ||
795 | GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_LOOKUP_RESPONSE, | ||
796 | struct LabelLookupResponseMessage, | ||
797 | h), | ||
798 | GNUNET_MQ_handler_end () }; | ||
799 | struct GNUNET_NAMESTORE_ZoneIterator *it; | ||
800 | struct GNUNET_NAMESTORE_QueueEntry *qe; | ||
801 | |||
802 | GNUNET_assert (NULL == h->mq); | ||
803 | h->mq = | ||
804 | GNUNET_CLIENT_connect (h->cfg, "namestore", handlers, &mq_error_handler, h); | ||
805 | if (NULL == h->mq) | ||
806 | return; | ||
807 | /* re-transmit pending requests that waited for a reconnect... */ | ||
808 | for (it = h->z_head; NULL != it; it = it->next) | ||
809 | { | ||
810 | GNUNET_MQ_send (h->mq, it->env); | ||
811 | it->env = NULL; | ||
812 | } | ||
813 | for (qe = h->op_head; NULL != qe; qe = qe->next) | ||
814 | { | ||
815 | GNUNET_MQ_send (h->mq, qe->env); | ||
816 | qe->env = NULL; | ||
817 | } | ||
818 | } | ||
819 | |||
820 | |||
821 | /** | ||
822 | * Re-establish the connection to the service. | ||
823 | * | ||
824 | * @param cls handle to use to re-connect. | ||
825 | */ | ||
826 | static void | ||
827 | reconnect_task (void *cls) | ||
828 | { | ||
829 | struct GNUNET_NAMESTORE_Handle *h = cls; | ||
830 | |||
831 | h->reconnect_task = NULL; | ||
832 | reconnect (h); | ||
833 | } | ||
834 | |||
835 | |||
836 | /** | ||
837 | * Disconnect from service and then reconnect. | ||
838 | * | ||
839 | * @param h our handle | ||
840 | */ | ||
841 | static void | ||
842 | force_reconnect (struct GNUNET_NAMESTORE_Handle *h) | ||
843 | { | ||
844 | struct GNUNET_NAMESTORE_ZoneIterator *ze; | ||
845 | struct GNUNET_NAMESTORE_QueueEntry *qe; | ||
846 | |||
847 | GNUNET_MQ_destroy (h->mq); | ||
848 | h->mq = NULL; | ||
849 | while (NULL != (ze = h->z_head)) | ||
850 | { | ||
851 | if (NULL != ze->error_cb) | ||
852 | ze->error_cb (ze->error_cb_cls); | ||
853 | free_ze (ze); | ||
854 | } | ||
855 | while (NULL != (qe = h->op_head)) | ||
856 | { | ||
857 | if (NULL != qe->error_cb) | ||
858 | qe->error_cb (qe->error_cb_cls); | ||
859 | if (NULL != qe->cont) | ||
860 | qe->cont (qe->cont_cls, | ||
861 | GNUNET_SYSERR, | ||
862 | "failure in communication with namestore service"); | ||
863 | free_qe (qe); | ||
864 | } | ||
865 | |||
866 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Reconnecting to namestore\n"); | ||
867 | h->reconnect_delay = GNUNET_TIME_STD_BACKOFF (h->reconnect_delay); | ||
868 | h->reconnect_task = | ||
869 | GNUNET_SCHEDULER_add_delayed (h->reconnect_delay, &reconnect_task, h); | ||
870 | } | ||
871 | |||
872 | |||
873 | /** | ||
874 | * Get a fresh operation id to distinguish between namestore requests | ||
875 | * | ||
876 | * @param h the namestore handle | ||
877 | * @return next operation id to use | ||
878 | */ | ||
879 | static uint32_t | ||
880 | get_op_id (struct GNUNET_NAMESTORE_Handle *h) | ||
881 | { | ||
882 | return h->last_op_id_used++; | ||
883 | } | ||
884 | |||
885 | |||
886 | /** | ||
887 | * Initialize the connection with the NAMESTORE service. | ||
888 | * | ||
889 | * @param cfg configuration to use | ||
890 | * @return handle to the GNS service, or NULL on error | ||
891 | */ | ||
892 | struct GNUNET_NAMESTORE_Handle * | ||
893 | GNUNET_NAMESTORE_connect (const struct GNUNET_CONFIGURATION_Handle *cfg) | ||
894 | { | ||
895 | struct GNUNET_NAMESTORE_Handle *h; | ||
896 | |||
897 | h = GNUNET_new (struct GNUNET_NAMESTORE_Handle); | ||
898 | h->cfg = cfg; | ||
899 | reconnect (h); | ||
900 | if (NULL == h->mq) | ||
901 | { | ||
902 | GNUNET_free (h); | ||
903 | return NULL; | ||
904 | } | ||
905 | return h; | ||
906 | } | ||
907 | |||
908 | |||
909 | /** | ||
910 | * Disconnect from the namestore service (and free associated | ||
911 | * resources). | ||
912 | * | ||
913 | * @param h handle to the namestore | ||
914 | */ | ||
915 | void | ||
916 | GNUNET_NAMESTORE_disconnect (struct GNUNET_NAMESTORE_Handle *h) | ||
917 | { | ||
918 | struct GNUNET_NAMESTORE_QueueEntry *q; | ||
919 | struct GNUNET_NAMESTORE_ZoneIterator *z; | ||
920 | |||
921 | LOG (GNUNET_ERROR_TYPE_DEBUG, "Cleaning up\n"); | ||
922 | GNUNET_break (NULL == h->op_head); | ||
923 | while (NULL != (q = h->op_head)) | ||
924 | { | ||
925 | GNUNET_CONTAINER_DLL_remove (h->op_head, h->op_tail, q); | ||
926 | GNUNET_free (q); | ||
927 | } | ||
928 | GNUNET_break (NULL == h->z_head); | ||
929 | while (NULL != (z = h->z_head)) | ||
930 | { | ||
931 | GNUNET_CONTAINER_DLL_remove (h->z_head, h->z_tail, z); | ||
932 | GNUNET_free (z); | ||
933 | } | ||
934 | if (NULL != h->mq) | ||
935 | { | ||
936 | GNUNET_MQ_destroy (h->mq); | ||
937 | h->mq = NULL; | ||
938 | } | ||
939 | if (NULL != h->reconnect_task) | ||
940 | { | ||
941 | GNUNET_SCHEDULER_cancel (h->reconnect_task); | ||
942 | h->reconnect_task = NULL; | ||
943 | } | ||
944 | GNUNET_free (h); | ||
945 | } | ||
946 | |||
947 | |||
948 | /** | ||
949 | * Task launched to warn the user that the namestore is | ||
950 | * excessively slow and that a query was thus dropped. | ||
951 | * | ||
952 | * @param cls a `struct GNUNET_NAMESTORE_QueueEntry *` | ||
953 | */ | ||
954 | static void | ||
955 | warn_delay (void *cls) | ||
956 | { | ||
957 | struct GNUNET_NAMESTORE_QueueEntry *qe = cls; | ||
958 | |||
959 | qe->timeout_task = NULL; | ||
960 | LOG (GNUNET_ERROR_TYPE_WARNING, | ||
961 | "Did not receive response from namestore after %s!\n", | ||
962 | GNUNET_STRINGS_relative_time_to_string (NAMESTORE_DELAY_TOLERANCE, | ||
963 | GNUNET_YES)); | ||
964 | if (NULL != qe->cont) | ||
965 | { | ||
966 | qe->cont (qe->cont_cls, GNUNET_SYSERR, "timeout"); | ||
967 | qe->cont = NULL; | ||
968 | } | ||
969 | GNUNET_NAMESTORE_cancel (qe); | ||
970 | } | ||
971 | |||
972 | |||
973 | /** | ||
974 | * Store an item in the namestore. If the item is already present, | ||
975 | * it is replaced with the new record. Use an empty array to | ||
976 | * remove all records under the given name. | ||
977 | * | ||
978 | * @param h handle to the namestore | ||
979 | * @param pkey private key of the zone | ||
980 | * @param label name that is being mapped (at most 255 characters long) | ||
981 | * @param rd_count number of records in the @a rd array | ||
982 | * @param rd array of records with data to store | ||
983 | * @param cont continuation to call when done | ||
984 | * @param cont_cls closure for @a cont | ||
985 | * @return handle to abort the request | ||
986 | */ | ||
987 | struct GNUNET_NAMESTORE_QueueEntry * | ||
988 | GNUNET_NAMESTORE_records_store ( | ||
989 | struct GNUNET_NAMESTORE_Handle *h, | ||
990 | const struct GNUNET_IDENTITY_PrivateKey *pkey, | ||
991 | const char *label, | ||
992 | unsigned int rd_count, | ||
993 | const struct GNUNET_GNSRECORD_Data *rd, | ||
994 | GNUNET_NAMESTORE_ContinuationWithStatus cont, | ||
995 | void *cont_cls) | ||
996 | { | ||
997 | struct GNUNET_NAMESTORE_QueueEntry *qe; | ||
998 | struct GNUNET_MQ_Envelope *env; | ||
999 | char *name_tmp; | ||
1000 | char *rd_ser; | ||
1001 | ssize_t rd_ser_len; | ||
1002 | size_t name_len; | ||
1003 | uint32_t rid; | ||
1004 | struct RecordStoreMessage *msg; | ||
1005 | ssize_t sret; | ||
1006 | |||
1007 | name_len = strlen (label) + 1; | ||
1008 | if (name_len > MAX_NAME_LEN) | ||
1009 | { | ||
1010 | GNUNET_break (0); | ||
1011 | return NULL; | ||
1012 | } | ||
1013 | rd_ser_len = GNUNET_GNSRECORD_records_get_size (rd_count, rd); | ||
1014 | if (rd_ser_len < 0) | ||
1015 | { | ||
1016 | GNUNET_break (0); | ||
1017 | return NULL; | ||
1018 | } | ||
1019 | if (rd_ser_len > UINT16_MAX) | ||
1020 | { | ||
1021 | GNUNET_break (0); | ||
1022 | return NULL; | ||
1023 | } | ||
1024 | rid = get_op_id (h); | ||
1025 | qe = GNUNET_new (struct GNUNET_NAMESTORE_QueueEntry); | ||
1026 | qe->h = h; | ||
1027 | qe->cont = cont; | ||
1028 | qe->cont_cls = cont_cls; | ||
1029 | qe->op_id = rid; | ||
1030 | GNUNET_CONTAINER_DLL_insert_tail (h->op_head, h->op_tail, qe); | ||
1031 | |||
1032 | /* setup msg */ | ||
1033 | env = GNUNET_MQ_msg_extra (msg, | ||
1034 | name_len + rd_ser_len, | ||
1035 | GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_STORE); | ||
1036 | msg->gns_header.r_id = htonl (rid); | ||
1037 | msg->name_len = htons (name_len); | ||
1038 | msg->rd_count = htons (rd_count); | ||
1039 | msg->rd_len = htons (rd_ser_len); | ||
1040 | msg->reserved = htons (0); | ||
1041 | msg->private_key = *pkey; | ||
1042 | |||
1043 | name_tmp = (char *) &msg[1]; | ||
1044 | GNUNET_memcpy (name_tmp, label, name_len); | ||
1045 | rd_ser = &name_tmp[name_len]; | ||
1046 | sret = GNUNET_GNSRECORD_records_serialize (rd_count, rd, rd_ser_len, rd_ser); | ||
1047 | if ((0 > sret) || (sret != rd_ser_len)) | ||
1048 | { | ||
1049 | GNUNET_break (0); | ||
1050 | GNUNET_free (env); | ||
1051 | return NULL; | ||
1052 | } | ||
1053 | GNUNET_assert (rd_ser_len == sret); | ||
1054 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1055 | "Sending NAMESTORE_RECORD_STORE message for name `%s' with %u records\n", | ||
1056 | label, | ||
1057 | rd_count); | ||
1058 | qe->timeout_task = | ||
1059 | GNUNET_SCHEDULER_add_delayed (NAMESTORE_DELAY_TOLERANCE, &warn_delay, qe); | ||
1060 | if (NULL == h->mq) | ||
1061 | { | ||
1062 | qe->env = env; | ||
1063 | LOG (GNUNET_ERROR_TYPE_WARNING, | ||
1064 | "Delaying NAMESTORE_RECORD_STORE message as namestore is not ready!\n"); | ||
1065 | } | ||
1066 | else | ||
1067 | { | ||
1068 | GNUNET_MQ_send (h->mq, env); | ||
1069 | } | ||
1070 | return qe; | ||
1071 | } | ||
1072 | |||
1073 | |||
1074 | /** | ||
1075 | * Lookup an item in the namestore. | ||
1076 | * | ||
1077 | * @param h handle to the namestore | ||
1078 | * @param pkey private key of the zone | ||
1079 | * @param label name that is being mapped (at most 255 characters long) | ||
1080 | * @param error_cb function to call on error (i.e. disconnect) | ||
1081 | * @param error_cb_cls closure for @a error_cb | ||
1082 | * @param rm function to call with the result (with 0 records if we don't have that label) | ||
1083 | * @param rm_cls closure for @a rm | ||
1084 | * @return handle to abort the request | ||
1085 | */ | ||
1086 | struct GNUNET_NAMESTORE_QueueEntry * | ||
1087 | GNUNET_NAMESTORE_records_lookup ( | ||
1088 | struct GNUNET_NAMESTORE_Handle *h, | ||
1089 | const struct GNUNET_IDENTITY_PrivateKey *pkey, | ||
1090 | const char *label, | ||
1091 | GNUNET_SCHEDULER_TaskCallback error_cb, | ||
1092 | void *error_cb_cls, | ||
1093 | GNUNET_NAMESTORE_RecordMonitor rm, | ||
1094 | void *rm_cls) | ||
1095 | { | ||
1096 | struct GNUNET_NAMESTORE_QueueEntry *qe; | ||
1097 | struct GNUNET_MQ_Envelope *env; | ||
1098 | struct LabelLookupMessage *msg; | ||
1099 | size_t label_len; | ||
1100 | |||
1101 | if (1 == (label_len = strlen (label) + 1)) | ||
1102 | { | ||
1103 | GNUNET_break (0); | ||
1104 | return NULL; | ||
1105 | } | ||
1106 | |||
1107 | qe = GNUNET_new (struct GNUNET_NAMESTORE_QueueEntry); | ||
1108 | qe->h = h; | ||
1109 | qe->error_cb = error_cb; | ||
1110 | qe->error_cb_cls = error_cb_cls; | ||
1111 | qe->proc = rm; | ||
1112 | qe->proc_cls = rm_cls; | ||
1113 | qe->op_id = get_op_id (h); | ||
1114 | GNUNET_CONTAINER_DLL_insert_tail (h->op_head, h->op_tail, qe); | ||
1115 | |||
1116 | env = GNUNET_MQ_msg_extra (msg, | ||
1117 | label_len, | ||
1118 | GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_LOOKUP); | ||
1119 | msg->gns_header.r_id = htonl (qe->op_id); | ||
1120 | msg->zone = *pkey; | ||
1121 | msg->label_len = htonl (label_len); | ||
1122 | GNUNET_memcpy (&msg[1], label, label_len); | ||
1123 | if (NULL == h->mq) | ||
1124 | qe->env = env; | ||
1125 | else | ||
1126 | GNUNET_MQ_send (h->mq, env); | ||
1127 | return qe; | ||
1128 | } | ||
1129 | |||
1130 | |||
1131 | /** | ||
1132 | * Look for an existing PKEY delegation record for a given public key. | ||
1133 | * Returns at most one result to the processor. | ||
1134 | * | ||
1135 | * @param h handle to the namestore | ||
1136 | * @param zone public key of the zone to look up in, never NULL | ||
1137 | * @param value_zone public key of the target zone (value), never NULL | ||
1138 | * @param error_cb function to call on error (i.e. disconnect) | ||
1139 | * @param error_cb_cls closure for @a error_cb | ||
1140 | * @param proc function to call on the matching records, or with | ||
1141 | * NULL (rd_count == 0) if there are no matching records | ||
1142 | * @param proc_cls closure for @a proc | ||
1143 | * @return a handle that can be used to | ||
1144 | * cancel | ||
1145 | */ | ||
1146 | struct GNUNET_NAMESTORE_QueueEntry * | ||
1147 | GNUNET_NAMESTORE_zone_to_name ( | ||
1148 | struct GNUNET_NAMESTORE_Handle *h, | ||
1149 | const struct GNUNET_IDENTITY_PrivateKey *zone, | ||
1150 | const struct GNUNET_IDENTITY_PublicKey *value_zone, | ||
1151 | GNUNET_SCHEDULER_TaskCallback error_cb, | ||
1152 | void *error_cb_cls, | ||
1153 | GNUNET_NAMESTORE_RecordMonitor proc, | ||
1154 | void *proc_cls) | ||
1155 | { | ||
1156 | struct GNUNET_NAMESTORE_QueueEntry *qe; | ||
1157 | struct GNUNET_MQ_Envelope *env; | ||
1158 | struct ZoneToNameMessage *msg; | ||
1159 | uint32_t rid; | ||
1160 | |||
1161 | rid = get_op_id (h); | ||
1162 | qe = GNUNET_new (struct GNUNET_NAMESTORE_QueueEntry); | ||
1163 | qe->h = h; | ||
1164 | qe->error_cb = error_cb; | ||
1165 | qe->error_cb_cls = error_cb_cls; | ||
1166 | qe->proc = proc; | ||
1167 | qe->proc_cls = proc_cls; | ||
1168 | qe->op_id = rid; | ||
1169 | GNUNET_CONTAINER_DLL_insert_tail (h->op_head, h->op_tail, qe); | ||
1170 | |||
1171 | env = GNUNET_MQ_msg (msg, GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_TO_NAME); | ||
1172 | msg->gns_header.r_id = htonl (rid); | ||
1173 | msg->zone = *zone; | ||
1174 | msg->value_zone = *value_zone; | ||
1175 | if (NULL == h->mq) | ||
1176 | qe->env = env; | ||
1177 | else | ||
1178 | GNUNET_MQ_send (h->mq, env); | ||
1179 | return qe; | ||
1180 | } | ||
1181 | |||
1182 | |||
1183 | /** | ||
1184 | * Starts a new zone iteration (used to periodically PUT all of our | ||
1185 | * records into our DHT). This MUST lock the struct GNUNET_NAMESTORE_Handle | ||
1186 | * for any other calls than #GNUNET_NAMESTORE_zone_iterator_next and | ||
1187 | * #GNUNET_NAMESTORE_zone_iteration_stop. @a proc will be called once | ||
1188 | * immediately, and then again after | ||
1189 | * #GNUNET_NAMESTORE_zone_iterator_next is invoked. | ||
1190 | * | ||
1191 | * @param h handle to the namestore | ||
1192 | * @param zone zone to access, NULL for all zones | ||
1193 | * @param error_cb function to call on error (i.e. disconnect) | ||
1194 | * @param error_cb_cls closure for @a error_cb | ||
1195 | * @param proc function to call on each name from the zone; it | ||
1196 | * will be called repeatedly with a value (if available) | ||
1197 | * @param proc_cls closure for @a proc | ||
1198 | * @param finish_cb function to call on completion | ||
1199 | * @param finish_cb_cls closure for @a finish_cb | ||
1200 | * @return an iterator handle to use for iteration | ||
1201 | */ | ||
1202 | struct GNUNET_NAMESTORE_ZoneIterator * | ||
1203 | GNUNET_NAMESTORE_zone_iteration_start ( | ||
1204 | struct GNUNET_NAMESTORE_Handle *h, | ||
1205 | const struct GNUNET_IDENTITY_PrivateKey *zone, | ||
1206 | GNUNET_SCHEDULER_TaskCallback error_cb, | ||
1207 | void *error_cb_cls, | ||
1208 | GNUNET_NAMESTORE_RecordMonitor proc, | ||
1209 | void *proc_cls, | ||
1210 | GNUNET_SCHEDULER_TaskCallback finish_cb, | ||
1211 | void *finish_cb_cls) | ||
1212 | { | ||
1213 | struct GNUNET_NAMESTORE_ZoneIterator *it; | ||
1214 | struct GNUNET_MQ_Envelope *env; | ||
1215 | struct ZoneIterationStartMessage *msg; | ||
1216 | uint32_t rid; | ||
1217 | |||
1218 | LOG (GNUNET_ERROR_TYPE_DEBUG, "Sending ZONE_ITERATION_START message\n"); | ||
1219 | rid = get_op_id (h); | ||
1220 | it = GNUNET_new (struct GNUNET_NAMESTORE_ZoneIterator); | ||
1221 | it->h = h; | ||
1222 | it->error_cb = error_cb; | ||
1223 | it->error_cb_cls = error_cb_cls; | ||
1224 | it->finish_cb = finish_cb; | ||
1225 | it->finish_cb_cls = finish_cb_cls; | ||
1226 | it->proc = proc; | ||
1227 | it->proc_cls = proc_cls; | ||
1228 | it->op_id = rid; | ||
1229 | if (NULL != zone) | ||
1230 | it->zone = *zone; | ||
1231 | GNUNET_CONTAINER_DLL_insert_tail (h->z_head, h->z_tail, it); | ||
1232 | env = GNUNET_MQ_msg (msg, GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_ITERATION_START); | ||
1233 | msg->gns_header.r_id = htonl (rid); | ||
1234 | if (NULL != zone) | ||
1235 | msg->zone = *zone; | ||
1236 | if (NULL == h->mq) | ||
1237 | it->env = env; | ||
1238 | else | ||
1239 | GNUNET_MQ_send (h->mq, env); | ||
1240 | return it; | ||
1241 | } | ||
1242 | |||
1243 | |||
1244 | /** | ||
1245 | * Calls the record processor specified in #GNUNET_NAMESTORE_zone_iteration_start | ||
1246 | * for the next record. | ||
1247 | * | ||
1248 | * @param it the iterator | ||
1249 | * @param limit number of records to return to the iterator in one shot | ||
1250 | * (before #GNUNET_NAMESTORE_zone_iterator_next is to be called again) | ||
1251 | */ | ||
1252 | void | ||
1253 | GNUNET_NAMESTORE_zone_iterator_next (struct GNUNET_NAMESTORE_ZoneIterator *it, | ||
1254 | uint64_t limit) | ||
1255 | { | ||
1256 | struct GNUNET_NAMESTORE_Handle *h = it->h; | ||
1257 | struct ZoneIterationNextMessage *msg; | ||
1258 | struct GNUNET_MQ_Envelope *env; | ||
1259 | |||
1260 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1261 | "Sending ZONE_ITERATION_NEXT message with limit %llu\n", | ||
1262 | (unsigned long long) limit); | ||
1263 | env = GNUNET_MQ_msg (msg, GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_ITERATION_NEXT); | ||
1264 | msg->gns_header.r_id = htonl (it->op_id); | ||
1265 | msg->limit = GNUNET_htonll (limit); | ||
1266 | GNUNET_MQ_send (h->mq, env); | ||
1267 | } | ||
1268 | |||
1269 | |||
1270 | /** | ||
1271 | * Stops iteration and releases the namestore handle for further calls. | ||
1272 | * | ||
1273 | * @param it the iterator | ||
1274 | */ | ||
1275 | void | ||
1276 | GNUNET_NAMESTORE_zone_iteration_stop (struct GNUNET_NAMESTORE_ZoneIterator *it) | ||
1277 | { | ||
1278 | struct GNUNET_NAMESTORE_Handle *h = it->h; | ||
1279 | struct GNUNET_MQ_Envelope *env; | ||
1280 | struct ZoneIterationStopMessage *msg; | ||
1281 | |||
1282 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending ZONE_ITERATION_STOP message\n"); | ||
1283 | if (NULL != h->mq) | ||
1284 | { | ||
1285 | env = | ||
1286 | GNUNET_MQ_msg (msg, GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_ITERATION_STOP); | ||
1287 | msg->gns_header.r_id = htonl (it->op_id); | ||
1288 | GNUNET_MQ_send (h->mq, env); | ||
1289 | } | ||
1290 | free_ze (it); | ||
1291 | } | ||
1292 | |||
1293 | |||
1294 | /** | ||
1295 | * Cancel a namestore operation. The final callback from the | ||
1296 | * operation must not have been done yet. | ||
1297 | * | ||
1298 | * @param qe operation to cancel | ||
1299 | */ | ||
1300 | void | ||
1301 | GNUNET_NAMESTORE_cancel (struct GNUNET_NAMESTORE_QueueEntry *qe) | ||
1302 | { | ||
1303 | free_qe (qe); | ||
1304 | } | ||
1305 | |||
1306 | |||
1307 | /* end of namestore_api.c */ | ||
diff --git a/src/namestore/namestore_api_monitor.c b/src/namestore/namestore_api_monitor.c deleted file mode 100644 index 6670e54ce..000000000 --- a/src/namestore/namestore_api_monitor.c +++ /dev/null | |||
@@ -1,388 +0,0 @@ | |||
1 | /* | ||
2 | This file is part of GNUnet. | ||
3 | Copyright (C) 2013, 2016, 2018 GNUnet e.V. | ||
4 | |||
5 | GNUnet is free software: you can redistribute it and/or modify it | ||
6 | under the terms of the GNU Affero General Public License as published | ||
7 | by the Free Software Foundation, either version 3 of the License, | ||
8 | or (at your option) any later version. | ||
9 | |||
10 | GNUnet is distributed in the hope that it will be useful, but | ||
11 | WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
13 | Affero General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU Affero General Public License | ||
16 | along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
17 | |||
18 | SPDX-License-Identifier: AGPL3.0-or-later | ||
19 | */ | ||
20 | /** | ||
21 | * @file namestore/namestore_api_monitor.c | ||
22 | * @brief API to monitor changes in the NAMESTORE | ||
23 | * @author Christian Grothoff | ||
24 | */ | ||
25 | |||
26 | #include "platform.h" | ||
27 | #include "gnunet_util_lib.h" | ||
28 | #include "gnunet_crypto_lib.h" | ||
29 | #include "gnunet_constants.h" | ||
30 | #include "gnunet_dnsparser_lib.h" | ||
31 | #include "gnunet_arm_service.h" | ||
32 | #include "gnunet_signatures.h" | ||
33 | #include "gnunet_namestore_service.h" | ||
34 | #include "namestore.h" | ||
35 | |||
36 | |||
37 | /** | ||
38 | * Handle for a monitoring activity. | ||
39 | */ | ||
40 | struct GNUNET_NAMESTORE_ZoneMonitor | ||
41 | { | ||
42 | /** | ||
43 | * Configuration (to reconnect). | ||
44 | */ | ||
45 | const struct GNUNET_CONFIGURATION_Handle *cfg; | ||
46 | |||
47 | /** | ||
48 | * Handle to namestore service. | ||
49 | */ | ||
50 | struct GNUNET_MQ_Handle *mq; | ||
51 | |||
52 | /** | ||
53 | * Function to call on errors. | ||
54 | */ | ||
55 | GNUNET_SCHEDULER_TaskCallback error_cb; | ||
56 | |||
57 | /** | ||
58 | * Closure for @e error_cb. | ||
59 | */ | ||
60 | void *error_cb_cls; | ||
61 | |||
62 | /** | ||
63 | * Function to call on events. | ||
64 | */ | ||
65 | GNUNET_NAMESTORE_RecordMonitor monitor; | ||
66 | |||
67 | /** | ||
68 | * Closure for @e monitor. | ||
69 | */ | ||
70 | void *monitor_cls; | ||
71 | |||
72 | /** | ||
73 | * Function called when we've synchronized. | ||
74 | */ | ||
75 | GNUNET_SCHEDULER_TaskCallback sync_cb; | ||
76 | |||
77 | /** | ||
78 | * Closure for @e sync_cb. | ||
79 | */ | ||
80 | void *sync_cb_cls; | ||
81 | |||
82 | /** | ||
83 | * Monitored zone. | ||
84 | */ | ||
85 | struct GNUNET_IDENTITY_PrivateKey zone; | ||
86 | |||
87 | /** | ||
88 | * Do we first iterate over all existing records? | ||
89 | */ | ||
90 | int iterate_first; | ||
91 | }; | ||
92 | |||
93 | |||
94 | /** | ||
95 | * Reconnect to the namestore service. | ||
96 | * | ||
97 | * @param zm monitor to reconnect | ||
98 | */ | ||
99 | static void | ||
100 | reconnect (struct GNUNET_NAMESTORE_ZoneMonitor *zm); | ||
101 | |||
102 | |||
103 | /** | ||
104 | * Handle SYNC message from the namestore service. | ||
105 | * | ||
106 | * @param cls the monitor | ||
107 | * @param msg the sync message | ||
108 | */ | ||
109 | static void | ||
110 | handle_sync (void *cls, const struct GNUNET_MessageHeader *msg) | ||
111 | { | ||
112 | struct GNUNET_NAMESTORE_ZoneMonitor *zm = cls; | ||
113 | |||
114 | (void) cls; | ||
115 | (void) msg; | ||
116 | if (NULL != zm->sync_cb) | ||
117 | zm->sync_cb (zm->sync_cb_cls); | ||
118 | } | ||
119 | |||
120 | |||
121 | /** | ||
122 | * We've received a notification about a change to our zone. | ||
123 | * Check that it is well-formed. | ||
124 | * | ||
125 | * @param cls the zone monitor handle | ||
126 | * @param lrm the message from the service. | ||
127 | */ | ||
128 | static int | ||
129 | check_result (void *cls, const struct RecordResultMessage *lrm) | ||
130 | { | ||
131 | struct GNUNET_NAMESTORE_ZoneMonitor *zm = cls; | ||
132 | size_t lrm_len; | ||
133 | size_t exp_lrm_len; | ||
134 | size_t name_len; | ||
135 | size_t rd_len; | ||
136 | unsigned rd_count; | ||
137 | const char *name_tmp; | ||
138 | const char *rd_ser_tmp; | ||
139 | |||
140 | (void) cls; | ||
141 | if ((0 != GNUNET_memcmp (&lrm->private_key, &zm->zone)) && | ||
142 | (GNUNET_NO == GNUNET_is_zero (&zm->zone))) | ||
143 | { | ||
144 | GNUNET_break (0); | ||
145 | return GNUNET_SYSERR; | ||
146 | } | ||
147 | lrm_len = ntohs (lrm->gns_header.header.size); | ||
148 | rd_len = ntohs (lrm->rd_len); | ||
149 | rd_count = ntohs (lrm->rd_count); | ||
150 | name_len = ntohs (lrm->name_len); | ||
151 | if (name_len > MAX_NAME_LEN) | ||
152 | { | ||
153 | GNUNET_break (0); | ||
154 | return GNUNET_SYSERR; | ||
155 | } | ||
156 | exp_lrm_len = sizeof(struct RecordResultMessage) + name_len + rd_len; | ||
157 | if (lrm_len != exp_lrm_len) | ||
158 | { | ||
159 | GNUNET_break (0); | ||
160 | return GNUNET_SYSERR; | ||
161 | } | ||
162 | if (0 == name_len) | ||
163 | { | ||
164 | GNUNET_break (0); | ||
165 | return GNUNET_SYSERR; | ||
166 | } | ||
167 | name_tmp = (const char *) &lrm[1]; | ||
168 | if (name_tmp[name_len - 1] != '\0') | ||
169 | { | ||
170 | GNUNET_break (0); | ||
171 | return GNUNET_SYSERR; | ||
172 | } | ||
173 | rd_ser_tmp = (const char *) &name_tmp[name_len]; | ||
174 | { | ||
175 | struct GNUNET_GNSRECORD_Data rd[rd_count]; | ||
176 | |||
177 | if (GNUNET_OK != | ||
178 | GNUNET_GNSRECORD_records_deserialize (rd_len, rd_ser_tmp, rd_count, rd)) | ||
179 | { | ||
180 | GNUNET_break (0); | ||
181 | return GNUNET_SYSERR; | ||
182 | } | ||
183 | } | ||
184 | return GNUNET_OK; | ||
185 | } | ||
186 | |||
187 | |||
188 | /** | ||
189 | * We've received a notification about a change to our zone. | ||
190 | * Forward to monitor callback. | ||
191 | * | ||
192 | * @param cls the zone monitor handle | ||
193 | * @param lrm the message from the service. | ||
194 | */ | ||
195 | static void | ||
196 | handle_result (void *cls, const struct RecordResultMessage *lrm) | ||
197 | { | ||
198 | struct GNUNET_NAMESTORE_ZoneMonitor *zm = cls; | ||
199 | size_t name_len; | ||
200 | size_t rd_len; | ||
201 | unsigned rd_count; | ||
202 | const char *name_tmp; | ||
203 | const char *rd_ser_tmp; | ||
204 | |||
205 | rd_len = ntohs (lrm->rd_len); | ||
206 | rd_count = ntohs (lrm->rd_count); | ||
207 | name_len = ntohs (lrm->name_len); | ||
208 | name_tmp = (const char *) &lrm[1]; | ||
209 | rd_ser_tmp = (const char *) &name_tmp[name_len]; | ||
210 | { | ||
211 | struct GNUNET_GNSRECORD_Data rd[rd_count]; | ||
212 | |||
213 | GNUNET_assert ( | ||
214 | GNUNET_OK == | ||
215 | GNUNET_GNSRECORD_records_deserialize (rd_len, rd_ser_tmp, rd_count, rd)); | ||
216 | zm->monitor (zm->monitor_cls, &lrm->private_key, name_tmp, rd_count, rd); | ||
217 | } | ||
218 | } | ||
219 | |||
220 | |||
221 | /** | ||
222 | * Generic error handler, called with the appropriate error code and | ||
223 | * the same closure specified at the creation of the message queue. | ||
224 | * Not every message queue implementation supports an error handler. | ||
225 | * | ||
226 | * @param cls closure with the `struct GNUNET_NAMESTORE_ZoneMonitor *` | ||
227 | * @param error error code | ||
228 | */ | ||
229 | static void | ||
230 | mq_error_handler (void *cls, enum GNUNET_MQ_Error error) | ||
231 | { | ||
232 | struct GNUNET_NAMESTORE_ZoneMonitor *zm = cls; | ||
233 | |||
234 | (void) error; | ||
235 | reconnect (zm); | ||
236 | } | ||
237 | |||
238 | |||
239 | /** | ||
240 | * Reconnect to the namestore service. | ||
241 | * | ||
242 | * @param zm monitor to reconnect | ||
243 | */ | ||
244 | static void | ||
245 | reconnect (struct GNUNET_NAMESTORE_ZoneMonitor *zm) | ||
246 | { | ||
247 | struct GNUNET_MQ_MessageHandler handlers[] = | ||
248 | { GNUNET_MQ_hd_fixed_size (sync, | ||
249 | GNUNET_MESSAGE_TYPE_NAMESTORE_MONITOR_SYNC, | ||
250 | struct GNUNET_MessageHeader, | ||
251 | zm), | ||
252 | GNUNET_MQ_hd_var_size (result, | ||
253 | GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_RESULT, | ||
254 | struct RecordResultMessage, | ||
255 | zm), | ||
256 | GNUNET_MQ_handler_end () }; | ||
257 | struct GNUNET_MQ_Envelope *env; | ||
258 | struct ZoneMonitorStartMessage *sm; | ||
259 | |||
260 | if (NULL != zm->mq) | ||
261 | { | ||
262 | GNUNET_MQ_destroy (zm->mq); | ||
263 | zm->error_cb (zm->error_cb_cls); | ||
264 | } | ||
265 | zm->mq = GNUNET_CLIENT_connect (zm->cfg, | ||
266 | "namestore", | ||
267 | handlers, | ||
268 | &mq_error_handler, | ||
269 | zm); | ||
270 | if (NULL == zm->mq) | ||
271 | return; | ||
272 | env = GNUNET_MQ_msg (sm, GNUNET_MESSAGE_TYPE_NAMESTORE_MONITOR_START); | ||
273 | sm->iterate_first = htonl (zm->iterate_first); | ||
274 | sm->zone = zm->zone; | ||
275 | GNUNET_MQ_send (zm->mq, env); | ||
276 | } | ||
277 | |||
278 | |||
279 | /** | ||
280 | * Begin monitoring a zone for changes. If @a iterate_first is set, | ||
281 | * we Will first call the @a monitor function on all existing records | ||
282 | * in the selected zone(s). In any case, we will call @a sync and | ||
283 | * afterwards call @a monitor whenever a record changes. | ||
284 | * | ||
285 | * @param cfg configuration to use to connect to namestore | ||
286 | * @param zone zone to monitor | ||
287 | * @param iterate_first #GNUNET_YES to first iterate over all existing records, | ||
288 | * #GNUNET_NO to only return changes that happen from now | ||
289 | * on | ||
290 | * @param error_cb function to call on error (i.e. disconnect); note that | ||
291 | * unlike the other error callbacks in this API, a call to this | ||
292 | * function does NOT destroy the monitor handle, it merely signals | ||
293 | * that monitoring is down. You need to still explicitly call | ||
294 | * #GNUNET_NAMESTORE_zone_monitor_stop(). | ||
295 | * @param error_cb_cls closure for @a error_cb | ||
296 | * @param monitor function to call on zone changes | ||
297 | * @param monitor_cls closure for @a monitor | ||
298 | * @param sync_cb function called when we're in sync with the namestore | ||
299 | * @param cls closure for @a sync_cb | ||
300 | * @return handle to stop monitoring | ||
301 | */ | ||
302 | struct GNUNET_NAMESTORE_ZoneMonitor * | ||
303 | GNUNET_NAMESTORE_zone_monitor_start ( | ||
304 | const struct GNUNET_CONFIGURATION_Handle *cfg, | ||
305 | const struct GNUNET_IDENTITY_PrivateKey *zone, | ||
306 | int iterate_first, | ||
307 | GNUNET_SCHEDULER_TaskCallback error_cb, | ||
308 | void *error_cb_cls, | ||
309 | GNUNET_NAMESTORE_RecordMonitor monitor, | ||
310 | void *monitor_cls, | ||
311 | GNUNET_SCHEDULER_TaskCallback sync_cb, | ||
312 | void *sync_cb_cls) | ||
313 | { | ||
314 | struct GNUNET_NAMESTORE_ZoneMonitor *zm; | ||
315 | |||
316 | zm = GNUNET_new (struct GNUNET_NAMESTORE_ZoneMonitor); | ||
317 | if (NULL != zone) | ||
318 | zm->zone = *zone; | ||
319 | zm->iterate_first = iterate_first; | ||
320 | zm->error_cb = error_cb; | ||
321 | zm->error_cb_cls = error_cb_cls; | ||
322 | zm->monitor = monitor; | ||
323 | zm->monitor_cls = monitor_cls; | ||
324 | zm->sync_cb = sync_cb; | ||
325 | zm->sync_cb_cls = sync_cb_cls; | ||
326 | zm->cfg = cfg; | ||
327 | reconnect (zm); | ||
328 | if (NULL == zm->mq) | ||
329 | { | ||
330 | GNUNET_free (zm); | ||
331 | return NULL; | ||
332 | } | ||
333 | return zm; | ||
334 | } | ||
335 | |||
336 | |||
337 | /** | ||
338 | * Calls the monitor processor specified in #GNUNET_NAMESTORE_zone_monitor_start | ||
339 | * for the next record(s). This function is used to allow clients that merely | ||
340 | * monitor the NAMESTORE to still throttle namestore operations, so we can be | ||
341 | * sure that the monitors can keep up. | ||
342 | * | ||
343 | * Note that #GNUNET_NAMESTORE_records_store() only waits for this | ||
344 | * call if the previous limit set by the client was already reached. | ||
345 | * Thus, by using a @a limit greater than 1, monitors basically enable | ||
346 | * a queue of notifications to be processed asynchronously with some | ||
347 | * delay. Note that even with a limit of 1 the | ||
348 | * #GNUNET_NAMESTORE_records_store() function will run asynchronously | ||
349 | * and the continuation may be invoked before the monitors completed | ||
350 | * (or even started) processing the notification. Thus, monitors will | ||
351 | * only closely track the current state of the namestore, but not | ||
352 | * be involved in the transactions. | ||
353 | * | ||
354 | * @param zm the monitor | ||
355 | * @param limit number of records to return to the iterator in one shot | ||
356 | * (before #GNUNET_NAMESTORE_zone_monitor_next is to be called again) | ||
357 | */ | ||
358 | void | ||
359 | GNUNET_NAMESTORE_zone_monitor_next (struct GNUNET_NAMESTORE_ZoneMonitor *zm, | ||
360 | uint64_t limit) | ||
361 | { | ||
362 | struct GNUNET_MQ_Envelope *env; | ||
363 | struct ZoneMonitorNextMessage *nm; | ||
364 | |||
365 | env = GNUNET_MQ_msg (nm, GNUNET_MESSAGE_TYPE_NAMESTORE_MONITOR_NEXT); | ||
366 | nm->limit = GNUNET_htonll (limit); | ||
367 | GNUNET_MQ_send (zm->mq, env); | ||
368 | } | ||
369 | |||
370 | |||
371 | /** | ||
372 | * Stop monitoring a zone for changes. | ||
373 | * | ||
374 | * @param zm handle to the monitor activity to stop | ||
375 | */ | ||
376 | void | ||
377 | GNUNET_NAMESTORE_zone_monitor_stop (struct GNUNET_NAMESTORE_ZoneMonitor *zm) | ||
378 | { | ||
379 | if (NULL != zm->mq) | ||
380 | { | ||
381 | GNUNET_MQ_destroy (zm->mq); | ||
382 | zm->mq = NULL; | ||
383 | } | ||
384 | GNUNET_free (zm); | ||
385 | } | ||
386 | |||
387 | |||
388 | /* end of namestore_api_monitor.c */ | ||
diff --git a/src/namestore/perf_namestore_api_flat.conf b/src/namestore/perf_namestore_api_flat.conf deleted file mode 100644 index 30759ce7a..000000000 --- a/src/namestore/perf_namestore_api_flat.conf +++ /dev/null | |||
@@ -1,10 +0,0 @@ | |||
1 | @INLINE@ test_namestore_api.conf | ||
2 | |||
3 | [namestore] | ||
4 | DATABASE = flat | ||
5 | |||
6 | [namecache] | ||
7 | DISABLE = YES | ||
8 | |||
9 | [namestore-heap] | ||
10 | FILENAME = $GNUNET_TEST_HOME/namestore/heap.db | ||
diff --git a/src/namestore/perf_namestore_api_postgres.conf b/src/namestore/perf_namestore_api_postgres.conf deleted file mode 100644 index 52d0ecdd5..000000000 --- a/src/namestore/perf_namestore_api_postgres.conf +++ /dev/null | |||
@@ -1,11 +0,0 @@ | |||
1 | @INLINE@ test_namestore_api.conf | ||
2 | |||
3 | [namestore] | ||
4 | DATABASE = postgres | ||
5 | |||
6 | [namecache] | ||
7 | DISABLE = YES | ||
8 | |||
9 | [namestore-postgres] | ||
10 | CONFIG = connect_timeout=10 dbname=gnunetcheck | ||
11 | TEMPORARY_TABLE = YES | ||
diff --git a/src/namestore/perf_namestore_api_sqlite.conf b/src/namestore/perf_namestore_api_sqlite.conf deleted file mode 100644 index de0fa3f1f..000000000 --- a/src/namestore/perf_namestore_api_sqlite.conf +++ /dev/null | |||
@@ -1,7 +0,0 @@ | |||
1 | @INLINE@ test_namestore_api.conf | ||
2 | |||
3 | [namecache] | ||
4 | DISABLE = YES | ||
5 | |||
6 | [namestore-sqlite] | ||
7 | FILENAME = $GNUNET_TEST_HOME/namestore/sqlite_test.db | ||
diff --git a/src/namestore/perf_namestore_api_zone_iteration.c b/src/namestore/perf_namestore_api_zone_iteration.c deleted file mode 100644 index ce1cddf87..000000000 --- a/src/namestore/perf_namestore_api_zone_iteration.c +++ /dev/null | |||
@@ -1,379 +0,0 @@ | |||
1 | /* | ||
2 | This file is part of GNUnet. | ||
3 | Copyright (C) 2013, 2018 GNUnet e.V. | ||
4 | |||
5 | GNUnet is free software: you can redistribute it and/or modify it | ||
6 | under the terms of the GNU Affero General Public License as published | ||
7 | by the Free Software Foundation, either version 3 of the License, | ||
8 | or (at your option) any later version. | ||
9 | |||
10 | GNUnet is distributed in the hope that it will be useful, but | ||
11 | WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
13 | Affero General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU Affero General Public License | ||
16 | along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
17 | |||
18 | SPDX-License-Identifier: AGPL3.0-or-later | ||
19 | */ | ||
20 | /** | ||
21 | * @file namestore/perf_namestore_api_zone_iteration.c | ||
22 | * @brief testcase for zone iteration functionality: iterate all zones | ||
23 | * @author Christian Grothoff | ||
24 | */ | ||
25 | #include "platform.h" | ||
26 | #include "gnunet_namestore_service.h" | ||
27 | #include "gnunet_testing_lib.h" | ||
28 | #include "namestore.h" | ||
29 | #include "gnunet_dnsparser_lib.h" | ||
30 | |||
31 | #define TEST_RECORD_TYPE GNUNET_DNSPARSER_TYPE_TXT | ||
32 | |||
33 | /** | ||
34 | * A #BENCHMARK_SIZE of 1000 takes less than a minute on a reasonably | ||
35 | * modern system, so 30 minutes should be OK even for very, very | ||
36 | * slow systems. | ||
37 | */ | ||
38 | #define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 30) | ||
39 | |||
40 | /** | ||
41 | * The runtime of the benchmark is expected to be linear | ||
42 | * for the iteration phase with a *good* database. The FLAT | ||
43 | * database uses a quadratic retrieval algorithm, | ||
44 | * hence it should be quadratic in the size. | ||
45 | */ | ||
46 | #define BENCHMARK_SIZE 1000 | ||
47 | |||
48 | /** | ||
49 | * Maximum record size | ||
50 | */ | ||
51 | #define MAX_REC_SIZE 500 | ||
52 | |||
53 | /** | ||
54 | * How big are the blocks we fetch? Note that the first block is | ||
55 | * always just 1 record set per current API. Smaller block | ||
56 | * sizes will make quadratic iteration-by-offset penalties | ||
57 | * more pronounced. | ||
58 | */ | ||
59 | #define BLOCK_SIZE 100 | ||
60 | |||
61 | static struct GNUNET_NAMESTORE_Handle *nsh; | ||
62 | |||
63 | static struct GNUNET_SCHEDULER_Task *timeout_task; | ||
64 | |||
65 | static struct GNUNET_SCHEDULER_Task *t; | ||
66 | |||
67 | static struct GNUNET_IDENTITY_PrivateKey privkey; | ||
68 | |||
69 | static struct GNUNET_NAMESTORE_ZoneIterator *zi; | ||
70 | |||
71 | static struct GNUNET_NAMESTORE_QueueEntry *qe; | ||
72 | |||
73 | static int res; | ||
74 | |||
75 | static unsigned int off; | ||
76 | |||
77 | static unsigned int left_until_next; | ||
78 | |||
79 | static uint8_t seen[1 + BENCHMARK_SIZE / 8]; | ||
80 | |||
81 | static struct GNUNET_TIME_Absolute start; | ||
82 | |||
83 | |||
84 | /** | ||
85 | * Terminate everything | ||
86 | * | ||
87 | * @param cls NULL | ||
88 | */ | ||
89 | static void | ||
90 | end (void *cls) | ||
91 | { | ||
92 | (void) cls; | ||
93 | if (NULL != qe) | ||
94 | { | ||
95 | GNUNET_NAMESTORE_cancel (qe); | ||
96 | qe = NULL; | ||
97 | } | ||
98 | if (NULL != zi) | ||
99 | { | ||
100 | GNUNET_NAMESTORE_zone_iteration_stop (zi); | ||
101 | zi = NULL; | ||
102 | } | ||
103 | if (NULL != nsh) | ||
104 | { | ||
105 | GNUNET_NAMESTORE_disconnect (nsh); | ||
106 | nsh = NULL; | ||
107 | } | ||
108 | if (NULL != t) | ||
109 | { | ||
110 | GNUNET_SCHEDULER_cancel (t); | ||
111 | t = NULL; | ||
112 | } | ||
113 | if (NULL != timeout_task) | ||
114 | { | ||
115 | GNUNET_SCHEDULER_cancel (timeout_task); | ||
116 | timeout_task = NULL; | ||
117 | } | ||
118 | } | ||
119 | |||
120 | |||
121 | /** | ||
122 | * End with timeout. As this is a benchmark, we do not | ||
123 | * fail hard but return "skipped". | ||
124 | */ | ||
125 | static void | ||
126 | timeout (void *cls) | ||
127 | { | ||
128 | (void) cls; | ||
129 | timeout_task = NULL; | ||
130 | GNUNET_SCHEDULER_shutdown (); | ||
131 | res = 77; | ||
132 | } | ||
133 | |||
134 | |||
135 | static struct GNUNET_GNSRECORD_Data * | ||
136 | create_record (unsigned int count) | ||
137 | { | ||
138 | struct GNUNET_GNSRECORD_Data *rd; | ||
139 | |||
140 | rd = GNUNET_malloc (count + sizeof(struct GNUNET_GNSRECORD_Data)); | ||
141 | rd->expiration_time = GNUNET_TIME_relative_to_absolute ( | ||
142 | GNUNET_TIME_UNIT_HOURS).abs_value_us; | ||
143 | rd->record_type = TEST_RECORD_TYPE; | ||
144 | rd->data_size = count; | ||
145 | rd->data = (void *) &rd[1]; | ||
146 | rd->flags = 0; | ||
147 | memset (&rd[1], | ||
148 | 'a', | ||
149 | count); | ||
150 | return rd; | ||
151 | } | ||
152 | |||
153 | |||
154 | static void | ||
155 | zone_end (void *cls) | ||
156 | { | ||
157 | struct GNUNET_TIME_Relative delay; | ||
158 | |||
159 | zi = NULL; | ||
160 | delay = GNUNET_TIME_absolute_get_duration (start); | ||
161 | fprintf (stdout, | ||
162 | "Iterating over %u records took %s\n", | ||
163 | off, | ||
164 | GNUNET_STRINGS_relative_time_to_string (delay, | ||
165 | GNUNET_YES)); | ||
166 | if (BENCHMARK_SIZE == off) | ||
167 | { | ||
168 | res = 0; | ||
169 | } | ||
170 | else | ||
171 | { | ||
172 | GNUNET_break (0); | ||
173 | res = 1; | ||
174 | } | ||
175 | GNUNET_SCHEDULER_shutdown (); | ||
176 | } | ||
177 | |||
178 | |||
179 | static void | ||
180 | fail_cb (void *cls) | ||
181 | { | ||
182 | zi = NULL; | ||
183 | res = 2; | ||
184 | GNUNET_break (0); | ||
185 | GNUNET_SCHEDULER_shutdown (); | ||
186 | } | ||
187 | |||
188 | |||
189 | static void | ||
190 | zone_proc (void *cls, | ||
191 | const struct GNUNET_IDENTITY_PrivateKey *zone, | ||
192 | const char *label, | ||
193 | unsigned int rd_count, | ||
194 | const struct GNUNET_GNSRECORD_Data *rd) | ||
195 | { | ||
196 | struct GNUNET_GNSRECORD_Data *wrd; | ||
197 | unsigned int xoff; | ||
198 | |||
199 | GNUNET_assert (NULL != zone); | ||
200 | if (1 != sscanf (label, | ||
201 | "l%u", | ||
202 | &xoff)) | ||
203 | { | ||
204 | res = 3; | ||
205 | GNUNET_break (0); | ||
206 | GNUNET_SCHEDULER_shutdown (); | ||
207 | return; | ||
208 | } | ||
209 | if ((xoff > BENCHMARK_SIZE) || | ||
210 | (0 != (seen[xoff / 8] & (1U << (xoff % 8))))) | ||
211 | { | ||
212 | res = 3; | ||
213 | GNUNET_break (0); | ||
214 | GNUNET_SCHEDULER_shutdown (); | ||
215 | return; | ||
216 | } | ||
217 | seen[xoff / 8] |= (1U << (xoff % 8)); | ||
218 | wrd = create_record (xoff % MAX_REC_SIZE); | ||
219 | if ((rd->record_type != wrd->record_type) || | ||
220 | (rd->data_size != wrd->data_size) || | ||
221 | (rd->flags != wrd->flags)) | ||
222 | { | ||
223 | res = 4; | ||
224 | GNUNET_break (0); | ||
225 | GNUNET_SCHEDULER_shutdown (); | ||
226 | GNUNET_free (wrd); | ||
227 | return; | ||
228 | } | ||
229 | if (0 != memcmp (rd->data, | ||
230 | wrd->data, | ||
231 | wrd->data_size)) | ||
232 | { | ||
233 | res = 4; | ||
234 | GNUNET_break (0); | ||
235 | GNUNET_SCHEDULER_shutdown (); | ||
236 | GNUNET_free (wrd); | ||
237 | return; | ||
238 | } | ||
239 | GNUNET_free (wrd); | ||
240 | if (0 != GNUNET_memcmp (zone, | ||
241 | &privkey)) | ||
242 | { | ||
243 | res = 5; | ||
244 | GNUNET_break (0); | ||
245 | GNUNET_SCHEDULER_shutdown (); | ||
246 | return; | ||
247 | } | ||
248 | off++; | ||
249 | left_until_next--; | ||
250 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
251 | "Obtained record %u, expecting %u more until asking for more explicitly\n", | ||
252 | off, | ||
253 | left_until_next); | ||
254 | if (0 == left_until_next) | ||
255 | { | ||
256 | left_until_next = BLOCK_SIZE; | ||
257 | GNUNET_NAMESTORE_zone_iterator_next (zi, | ||
258 | left_until_next); | ||
259 | } | ||
260 | } | ||
261 | |||
262 | |||
263 | static void | ||
264 | publish_record (void *cls); | ||
265 | |||
266 | |||
267 | static void | ||
268 | put_cont (void *cls, | ||
269 | int32_t success, | ||
270 | const char *emsg) | ||
271 | { | ||
272 | (void) cls; | ||
273 | qe = NULL; | ||
274 | if (GNUNET_OK != success) | ||
275 | { | ||
276 | GNUNET_break (0); | ||
277 | GNUNET_SCHEDULER_shutdown (); | ||
278 | return; | ||
279 | } | ||
280 | t = GNUNET_SCHEDULER_add_now (&publish_record, | ||
281 | NULL); | ||
282 | } | ||
283 | |||
284 | |||
285 | static void | ||
286 | publish_record (void *cls) | ||
287 | { | ||
288 | struct GNUNET_GNSRECORD_Data *rd; | ||
289 | char *label; | ||
290 | |||
291 | (void) cls; | ||
292 | t = NULL; | ||
293 | if (BENCHMARK_SIZE == off) | ||
294 | { | ||
295 | struct GNUNET_TIME_Relative delay; | ||
296 | |||
297 | delay = GNUNET_TIME_absolute_get_duration (start); | ||
298 | fprintf (stdout, | ||
299 | "Inserting %u records took %s\n", | ||
300 | off, | ||
301 | GNUNET_STRINGS_relative_time_to_string (delay, | ||
302 | GNUNET_YES)); | ||
303 | start = GNUNET_TIME_absolute_get (); | ||
304 | off = 0; | ||
305 | left_until_next = 1; | ||
306 | zi = GNUNET_NAMESTORE_zone_iteration_start (nsh, | ||
307 | NULL, | ||
308 | &fail_cb, | ||
309 | NULL, | ||
310 | &zone_proc, | ||
311 | NULL, | ||
312 | &zone_end, | ||
313 | NULL); | ||
314 | GNUNET_assert (NULL != zi); | ||
315 | return; | ||
316 | } | ||
317 | rd = create_record ((++off) % MAX_REC_SIZE); | ||
318 | GNUNET_asprintf (&label, | ||
319 | "l%u", | ||
320 | off); | ||
321 | qe = GNUNET_NAMESTORE_records_store (nsh, | ||
322 | &privkey, | ||
323 | label, | ||
324 | 1, rd, | ||
325 | &put_cont, | ||
326 | NULL); | ||
327 | GNUNET_free (label); | ||
328 | GNUNET_free (rd); | ||
329 | } | ||
330 | |||
331 | |||
332 | static void | ||
333 | run (void *cls, | ||
334 | const struct GNUNET_CONFIGURATION_Handle *cfg, | ||
335 | struct GNUNET_TESTING_Peer *peer) | ||
336 | { | ||
337 | GNUNET_SCHEDULER_add_shutdown (&end, | ||
338 | NULL); | ||
339 | timeout_task = GNUNET_SCHEDULER_add_delayed (TIMEOUT, | ||
340 | &timeout, | ||
341 | NULL); | ||
342 | nsh = GNUNET_NAMESTORE_connect (cfg); | ||
343 | GNUNET_assert (NULL != nsh); | ||
344 | privkey.type = htonl (GNUNET_GNSRECORD_TYPE_PKEY); | ||
345 | GNUNET_CRYPTO_ecdsa_key_create (&privkey.ecdsa_key); | ||
346 | start = GNUNET_TIME_absolute_get (); | ||
347 | t = GNUNET_SCHEDULER_add_now (&publish_record, | ||
348 | NULL); | ||
349 | } | ||
350 | |||
351 | |||
352 | #include "test_common.c" | ||
353 | |||
354 | |||
355 | int | ||
356 | main (int argc, | ||
357 | char *argv[]) | ||
358 | { | ||
359 | const char *plugin_name; | ||
360 | char *cfg_name; | ||
361 | |||
362 | SETUP_CFG (plugin_name, cfg_name); | ||
363 | res = 1; | ||
364 | if (0 != | ||
365 | GNUNET_TESTING_peer_run ("perf-namestore-api-zone-iteration", | ||
366 | cfg_name, | ||
367 | &run, | ||
368 | NULL)) | ||
369 | { | ||
370 | res = 1; | ||
371 | } | ||
372 | GNUNET_DISK_purge_cfg_dir (cfg_name, | ||
373 | "GNUNET_TEST_HOME"); | ||
374 | GNUNET_free (cfg_name); | ||
375 | return res; | ||
376 | } | ||
377 | |||
378 | |||
379 | /* end of perf_namestore_api_zone_iteration.c */ | ||
diff --git a/src/namestore/plugin_namestore_flat.c b/src/namestore/plugin_namestore_flat.c deleted file mode 100644 index 3576b14e0..000000000 --- a/src/namestore/plugin_namestore_flat.c +++ /dev/null | |||
@@ -1,818 +0,0 @@ | |||
1 | /* | ||
2 | * This file is part of GNUnet | ||
3 | * Copyright (C) 2009-2015, 2018, 2019 GNUnet e.V. | ||
4 | * | ||
5 | * GNUnet is free software: you can redistribute it and/or modify it | ||
6 | * under the terms of the GNU Affero General Public License as published | ||
7 | * by the Free Software Foundation, either version 3 of the License, | ||
8 | * or (at your option) any later version. | ||
9 | * | ||
10 | * GNUnet is distributed in the hope that it will be useful, but | ||
11 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
13 | * Affero General Public License for more details. | ||
14 | * | ||
15 | * You should have received a copy of the GNU Affero General Public License | ||
16 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
17 | |||
18 | SPDX-License-Identifier: AGPL3.0-or-later | ||
19 | */ | ||
20 | /** | ||
21 | * @file namestore/plugin_namestore_flat.c | ||
22 | * @brief file-based namestore backend | ||
23 | * @author Martin Schanzenbach | ||
24 | * @author Christian Grothoff | ||
25 | */ | ||
26 | |||
27 | #include "platform.h" | ||
28 | #include "gnunet_namestore_plugin.h" | ||
29 | #include "gnunet_namestore_service.h" | ||
30 | #include "gnunet_gnsrecord_lib.h" | ||
31 | #include "namestore.h" | ||
32 | |||
33 | /** | ||
34 | * Context for all functions in this plugin. | ||
35 | */ | ||
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_IDENTITY_PrivateKey private_key; | ||
58 | |||
59 | /** | ||
60 | * Record count. | ||
61 | */ | ||
62 | uint32_t record_count; | ||
63 | |||
64 | /** | ||
65 | * Rvalue | ||
66 | */ | ||
67 | uint64_t rvalue; | ||
68 | |||
69 | /** | ||
70 | * Record data | ||
71 | */ | ||
72 | struct GNUNET_GNSRECORD_Data *record_data; | ||
73 | |||
74 | /** | ||
75 | * Label | ||
76 | */ | ||
77 | char *label; | ||
78 | }; | ||
79 | |||
80 | |||
81 | /** | ||
82 | * Hash contactenation of @a pkey and @a label into @a h | ||
83 | * | ||
84 | * @param pkey a key | ||
85 | * @param label a label | ||
86 | * @param h[out] initialized hash | ||
87 | */ | ||
88 | static void | ||
89 | hash_pkey_and_label (const struct GNUNET_IDENTITY_PrivateKey *pkey, | ||
90 | const char *label, | ||
91 | struct GNUNET_HashCode *h) | ||
92 | { | ||
93 | char *key; | ||
94 | size_t label_len; | ||
95 | size_t key_len; | ||
96 | |||
97 | label_len = strlen (label); | ||
98 | key_len = label_len + sizeof(struct GNUNET_IDENTITY_PrivateKey); | ||
99 | key = GNUNET_malloc (key_len); | ||
100 | GNUNET_memcpy (key, | ||
101 | label, | ||
102 | label_len); | ||
103 | GNUNET_memcpy (key + label_len, | ||
104 | pkey, | ||
105 | sizeof(struct GNUNET_IDENTITY_PrivateKey)); | ||
106 | GNUNET_CRYPTO_hash (key, | ||
107 | key_len, | ||
108 | h); | ||
109 | GNUNET_free (key); | ||
110 | } | ||
111 | |||
112 | |||
113 | /** | ||
114 | * Initialize the database connections and associated | ||
115 | * data structures (create tables and indices | ||
116 | * as needed as well). | ||
117 | * | ||
118 | * @param plugin the plugin context (state for this module) | ||
119 | * @return #GNUNET_OK on success | ||
120 | */ | ||
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_IDENTITY_PrivateKey *private_key; | ||
300 | |||
301 | GNUNET_STRINGS_base64_decode (zone_private_key, | ||
302 | strlen (zone_private_key), | ||
303 | (void **) &private_key); | ||
304 | entry->private_key = *private_key; | ||
305 | GNUNET_free (private_key); | ||
306 | } | ||
307 | |||
308 | hash_pkey_and_label (&entry->private_key, | ||
309 | label, | ||
310 | &hkey); | ||
311 | if (GNUNET_OK != | ||
312 | GNUNET_CONTAINER_multihashmap_put (plugin->hm, | ||
313 | &hkey, | ||
314 | entry, | ||
315 | GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY)) | ||
316 | { | ||
317 | GNUNET_free (entry); | ||
318 | GNUNET_break (0); | ||
319 | } | ||
320 | } | ||
321 | GNUNET_DISK_file_unmap (mh); | ||
322 | GNUNET_DISK_file_close (fh); | ||
323 | return GNUNET_OK; | ||
324 | } | ||
325 | |||
326 | |||
327 | /** | ||
328 | * Store values in hashmap in file and free data | ||
329 | * | ||
330 | * @param plugin the plugin context | ||
331 | * @param key key in the map | ||
332 | * @param value a `struct FlatFileEntry` | ||
333 | */ | ||
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_IDENTITY_PrivateKey), | ||
349 | &zone_private_key); | ||
350 | data_size = GNUNET_GNSRECORD_records_get_size (entry->record_count, | ||
351 | entry->record_data); | ||
352 | if (data_size < 0) | ||
353 | { | ||
354 | GNUNET_break (0); | ||
355 | GNUNET_free (zone_private_key); | ||
356 | return GNUNET_SYSERR; | ||
357 | } | ||
358 | if (data_size >= UINT16_MAX) | ||
359 | { | ||
360 | GNUNET_break (0); | ||
361 | GNUNET_free (zone_private_key); | ||
362 | return GNUNET_SYSERR; | ||
363 | } | ||
364 | { | ||
365 | char data[data_size]; | ||
366 | ssize_t ret; | ||
367 | |||
368 | ret = GNUNET_GNSRECORD_records_serialize (entry->record_count, | ||
369 | entry->record_data, | ||
370 | data_size, | ||
371 | data); | ||
372 | if ((ret < 0) || | ||
373 | (data_size != ret)) | ||
374 | { | ||
375 | GNUNET_break (0); | ||
376 | GNUNET_free (zone_private_key); | ||
377 | return GNUNET_SYSERR; | ||
378 | } | ||
379 | GNUNET_STRINGS_base64_encode (data, | ||
380 | data_size, | ||
381 | &record_data_b64); | ||
382 | } | ||
383 | GNUNET_asprintf (&line, | ||
384 | "%s,%llu,%u,%s,%s\n", | ||
385 | zone_private_key, | ||
386 | (unsigned long long) entry->rvalue, | ||
387 | (unsigned int) entry->record_count, | ||
388 | record_data_b64, | ||
389 | entry->label); | ||
390 | GNUNET_free (record_data_b64); | ||
391 | GNUNET_free (zone_private_key); | ||
392 | |||
393 | GNUNET_DISK_file_write (fh, | ||
394 | line, | ||
395 | strlen (line)); | ||
396 | |||
397 | GNUNET_free (line); | ||
398 | GNUNET_free (entry->label); | ||
399 | GNUNET_free (entry->record_data); | ||
400 | GNUNET_free (entry); | ||
401 | return GNUNET_YES; | ||
402 | } | ||
403 | |||
404 | |||
405 | /** | ||
406 | * Shutdown database connection and associate data | ||
407 | * structures. | ||
408 | * @param plugin the plugin context (state for this module) | ||
409 | */ | ||
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_IDENTITY_PrivateKey *zone_key, | ||
456 | const char *label, | ||
457 | unsigned int rd_count, | ||
458 | const struct GNUNET_GNSRECORD_Data *rd) | ||
459 | { | ||
460 | struct Plugin *plugin = cls; | ||
461 | uint64_t rvalue; | ||
462 | struct GNUNET_HashCode hkey; | ||
463 | struct FlatFileEntry *entry; | ||
464 | |||
465 | rvalue = GNUNET_CRYPTO_random_u64 (GNUNET_CRYPTO_QUALITY_WEAK, | ||
466 | UINT64_MAX); | ||
467 | hash_pkey_and_label (zone_key, | ||
468 | label, | ||
469 | &hkey); | ||
470 | GNUNET_CONTAINER_multihashmap_remove_all (plugin->hm, | ||
471 | &hkey); | ||
472 | if (0 == rd_count) | ||
473 | { | ||
474 | GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, | ||
475 | "sqlite", | ||
476 | "Record deleted\n"); | ||
477 | return GNUNET_OK; | ||
478 | } | ||
479 | entry = GNUNET_new (struct FlatFileEntry); | ||
480 | GNUNET_asprintf (&entry->label, | ||
481 | label, | ||
482 | strlen (label)); | ||
483 | GNUNET_memcpy (&entry->private_key, | ||
484 | zone_key, | ||
485 | sizeof(struct GNUNET_IDENTITY_PrivateKey)); | ||
486 | entry->rvalue = rvalue; | ||
487 | entry->record_count = rd_count; | ||
488 | entry->record_data = GNUNET_new_array (rd_count, | ||
489 | struct GNUNET_GNSRECORD_Data); | ||
490 | for (unsigned int i = 0; i < rd_count; i++) | ||
491 | { | ||
492 | entry->record_data[i].expiration_time = rd[i].expiration_time; | ||
493 | entry->record_data[i].record_type = rd[i].record_type; | ||
494 | entry->record_data[i].flags = rd[i].flags; | ||
495 | entry->record_data[i].data_size = rd[i].data_size; | ||
496 | entry->record_data[i].data = GNUNET_malloc (rd[i].data_size); | ||
497 | GNUNET_memcpy ((char *) entry->record_data[i].data, | ||
498 | rd[i].data, | ||
499 | rd[i].data_size); | ||
500 | } | ||
501 | return GNUNET_CONTAINER_multihashmap_put (plugin->hm, | ||
502 | &hkey, | ||
503 | entry, | ||
504 | GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY); | ||
505 | } | ||
506 | |||
507 | |||
508 | /** | ||
509 | * Lookup records in the datastore for which we are the authority. | ||
510 | * | ||
511 | * @param cls closure (internal context for the plugin) | ||
512 | * @param zone private key of the zone | ||
513 | * @param label name of the record in the zone | ||
514 | * @param iter function to call with the result | ||
515 | * @param iter_cls closure for @a iter | ||
516 | * @return #GNUNET_OK on success, #GNUNET_NO for no results, else #GNUNET_SYSERR | ||
517 | */ | ||
518 | static int | ||
519 | namestore_flat_lookup_records (void *cls, | ||
520 | const struct GNUNET_IDENTITY_PrivateKey *zone, | ||
521 | const char *label, | ||
522 | GNUNET_NAMESTORE_RecordIterator iter, | ||
523 | void *iter_cls) | ||
524 | { | ||
525 | struct Plugin *plugin = cls; | ||
526 | struct FlatFileEntry *entry; | ||
527 | struct GNUNET_HashCode hkey; | ||
528 | |||
529 | if (NULL == zone) | ||
530 | { | ||
531 | GNUNET_break (0); | ||
532 | return GNUNET_SYSERR; | ||
533 | } | ||
534 | hash_pkey_and_label (zone, | ||
535 | label, | ||
536 | &hkey); | ||
537 | entry = GNUNET_CONTAINER_multihashmap_get (plugin->hm, | ||
538 | &hkey); | ||
539 | |||
540 | if (NULL == entry) | ||
541 | return GNUNET_NO; | ||
542 | if (NULL != iter) | ||
543 | iter (iter_cls, | ||
544 | 1, /* zero is illegal */ | ||
545 | &entry->private_key, | ||
546 | entry->label, | ||
547 | entry->record_count, | ||
548 | entry->record_data); | ||
549 | return GNUNET_YES; | ||
550 | } | ||
551 | |||
552 | |||
553 | /** | ||
554 | * Closure for #iterate_zones. | ||
555 | */ | ||
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_IDENTITY_PrivateKey *zone; | ||
578 | |||
579 | /** | ||
580 | * Function to call on each record. | ||
581 | */ | ||
582 | GNUNET_NAMESTORE_RecordIterator iter; | ||
583 | |||
584 | /** | ||
585 | * Closure for @e iter. | ||
586 | */ | ||
587 | void *iter_cls; | ||
588 | }; | ||
589 | |||
590 | |||
591 | /** | ||
592 | * Helper function for #namestore_flat_iterate_records(). | ||
593 | * | ||
594 | * @param cls a `struct IterateContext` | ||
595 | * @param key unused | ||
596 | * @param value a `struct FlatFileEntry` | ||
597 | * @return #GNUNET_YES to continue the iteration | ||
598 | */ | ||
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_IDENTITY_PrivateKey *zone, | ||
651 | uint64_t serial, | ||
652 | uint64_t limit, | ||
653 | GNUNET_NAMESTORE_RecordIterator iter, | ||
654 | void *iter_cls) | ||
655 | { | ||
656 | struct Plugin *plugin = cls; | ||
657 | struct IterateContext ic; | ||
658 | |||
659 | ic.offset = serial; | ||
660 | ic.pos = 0; | ||
661 | ic.limit = limit; | ||
662 | ic.iter = iter; | ||
663 | ic.iter_cls = iter_cls; | ||
664 | ic.zone = zone; | ||
665 | GNUNET_CONTAINER_multihashmap_iterate (plugin->hm, | ||
666 | &iterate_zones, | ||
667 | &ic); | ||
668 | return (0 == ic.limit) ? GNUNET_OK : GNUNET_NO; | ||
669 | } | ||
670 | |||
671 | |||
672 | /** | ||
673 | * Closure for #zone_to_name. | ||
674 | */ | ||
675 | struct ZoneToNameContext | ||
676 | { | ||
677 | const struct GNUNET_IDENTITY_PrivateKey *zone; | ||
678 | const struct GNUNET_IDENTITY_PublicKey *value_zone; | ||
679 | GNUNET_NAMESTORE_RecordIterator iter; | ||
680 | void *iter_cls; | ||
681 | |||
682 | int result_found; | ||
683 | }; | ||
684 | |||
685 | |||
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_IDENTITY_PrivateKey *zone, | ||
737 | const struct | ||
738 | GNUNET_IDENTITY_PublicKey *value_zone, | ||
739 | GNUNET_NAMESTORE_RecordIterator iter, | ||
740 | void *iter_cls) | ||
741 | { | ||
742 | struct Plugin *plugin = cls; | ||
743 | struct ZoneToNameContext ztn = { | ||
744 | .iter = iter, | ||
745 | .iter_cls = iter_cls, | ||
746 | .zone = zone, | ||
747 | .value_zone = value_zone, | ||
748 | .result_found = GNUNET_NO | ||
749 | }; | ||
750 | |||
751 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
752 | "Performing reverse lookup for `%s'\n", | ||
753 | GNUNET_GNSRECORD_z2s (value_zone)); | ||
754 | GNUNET_CONTAINER_multihashmap_iterate (plugin->hm, | ||
755 | &zone_to_name, | ||
756 | &ztn); | ||
757 | return ztn.result_found; | ||
758 | } | ||
759 | |||
760 | |||
761 | /** | ||
762 | * Entry point for the plugin. | ||
763 | * | ||
764 | * @param cls the "struct GNUNET_NAMESTORE_PluginEnvironment*" | ||
765 | * @return NULL on error, otherwise the plugin context | ||
766 | */ | ||
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 bdbaf96b3..000000000 --- a/src/namestore/plugin_namestore_postgres.c +++ /dev/null | |||
@@ -1,626 +0,0 @@ | |||
1 | /* | ||
2 | * This file is part of GNUnet | ||
3 | * Copyright (C) 2009-2013, 2016-2018 GNUnet e.V. | ||
4 | * | ||
5 | * GNUnet is free software: you can redistribute it and/or modify it | ||
6 | * under the terms of the GNU Affero General Public License as published | ||
7 | * by the Free Software Foundation, either version 3 of the License, | ||
8 | * or (at your option) any later version. | ||
9 | * | ||
10 | * GNUnet is distributed in the hope that it will be useful, but | ||
11 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
13 | * Affero General Public License for more details. | ||
14 | * | ||
15 | * You should have received a copy of the GNU Affero General Public License | ||
16 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
17 | |||
18 | SPDX-License-Identifier: AGPL3.0-or-later | ||
19 | */ | ||
20 | |||
21 | /** | ||
22 | * @file namestore/plugin_namestore_postgres.c | ||
23 | * @brief postgres-based namestore backend | ||
24 | * @author Christian Grothoff | ||
25 | */ | ||
26 | #include "platform.h" | ||
27 | #include "gnunet_namestore_plugin.h" | ||
28 | #include "gnunet_namestore_service.h" | ||
29 | #include "gnunet_gnsrecord_lib.h" | ||
30 | #include "gnunet_pq_lib.h" | ||
31 | #include "namestore.h" | ||
32 | |||
33 | |||
34 | #define LOG(kind, ...) GNUNET_log_from (kind, "namestore-postgres", __VA_ARGS__) | ||
35 | |||
36 | |||
37 | /** | ||
38 | * Context for all functions in this plugin. | ||
39 | */ | ||
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 | |||
54 | /** | ||
55 | * Initialize the database connections and associated | ||
56 | * data structures (create tables and indices | ||
57 | * as needed as well). | ||
58 | * | ||
59 | * @param plugin the plugin context (state for this module) | ||
60 | * @return #GNUNET_OK on success | ||
61 | */ | ||
62 | static int | ||
63 | database_setup (struct Plugin *plugin) | ||
64 | { | ||
65 | struct GNUNET_PQ_ExecuteStatement es_temporary = | ||
66 | GNUNET_PQ_make_execute ( | ||
67 | "CREATE TEMPORARY TABLE IF NOT EXISTS ns098records (" | ||
68 | " seq BIGSERIAL PRIMARY KEY," | ||
69 | " zone_private_key BYTEA NOT NULL DEFAULT ''," | ||
70 | " pkey BYTEA DEFAULT ''," | ||
71 | " rvalue BYTEA NOT NULL DEFAULT ''," | ||
72 | " record_count INTEGER NOT NULL DEFAULT 0," | ||
73 | " record_data BYTEA NOT NULL DEFAULT ''," | ||
74 | " label TEXT NOT NULL DEFAULT ''," | ||
75 | " CONSTRAINT zl UNIQUE (zone_private_key,label)" | ||
76 | ")"); | ||
77 | struct GNUNET_PQ_ExecuteStatement es_default = | ||
78 | GNUNET_PQ_make_execute ("CREATE TABLE IF NOT EXISTS ns098records (" | ||
79 | " seq BIGSERIAL PRIMARY KEY," | ||
80 | " zone_private_key BYTEA NOT NULL DEFAULT ''," | ||
81 | " pkey BYTEA DEFAULT ''," | ||
82 | " rvalue BYTEA NOT NULL DEFAULT ''," | ||
83 | " record_count INTEGER NOT NULL DEFAULT 0," | ||
84 | " record_data BYTEA NOT NULL DEFAULT ''," | ||
85 | " label TEXT NOT NULL DEFAULT ''," | ||
86 | " CONSTRAINT zl UNIQUE (zone_private_key,label)" | ||
87 | ")"); | ||
88 | const struct GNUNET_PQ_ExecuteStatement *cr; | ||
89 | struct GNUNET_PQ_ExecuteStatement sc = GNUNET_PQ_EXECUTE_STATEMENT_END; | ||
90 | |||
91 | if (GNUNET_YES == | ||
92 | GNUNET_CONFIGURATION_get_value_yesno (plugin->cfg, | ||
93 | "namestore-postgres", | ||
94 | "TEMPORARY_TABLE")) | ||
95 | { | ||
96 | cr = &es_temporary; | ||
97 | } | ||
98 | else | ||
99 | { | ||
100 | cr = &es_default; | ||
101 | } | ||
102 | |||
103 | if (GNUNET_YES == | ||
104 | GNUNET_CONFIGURATION_get_value_yesno (plugin->cfg, | ||
105 | "namestore-postgres", | ||
106 | "ASYNC_COMMIT")) | ||
107 | sc = GNUNET_PQ_make_try_execute ("SET synchronous_commit TO off"); | ||
108 | |||
109 | { | ||
110 | struct GNUNET_PQ_ExecuteStatement es[] = { | ||
111 | *cr, | ||
112 | GNUNET_PQ_make_try_execute ("CREATE INDEX IF NOT EXISTS ir_pkey_reverse " | ||
113 | "ON ns098records (zone_private_key,pkey)"), | ||
114 | GNUNET_PQ_make_try_execute ("CREATE INDEX IF NOT EXISTS ir_pkey_iter " | ||
115 | "ON ns098records (zone_private_key,seq)"), | ||
116 | GNUNET_PQ_make_try_execute ("CREATE INDEX IF NOT EXISTS ir_label " | ||
117 | "ON ns098records (label)"), | ||
118 | GNUNET_PQ_make_try_execute ("CREATE INDEX IF NOT EXISTS zone_label " | ||
119 | "ON ns098records (zone_private_key,label)"), | ||
120 | sc, | ||
121 | GNUNET_PQ_EXECUTE_STATEMENT_END | ||
122 | }; | ||
123 | struct GNUNET_PQ_PreparedStatement ps[] = { | ||
124 | GNUNET_PQ_make_prepare ("store_records", | ||
125 | "INSERT INTO ns098records" | ||
126 | " (zone_private_key, pkey, rvalue, record_count, record_data, label)" | ||
127 | " VALUES ($1, $2, $3, $4, $5, $6)" | ||
128 | " ON CONFLICT ON CONSTRAINT zl" | ||
129 | " DO UPDATE" | ||
130 | " SET pkey=$2,rvalue=$3,record_count=$4,record_data=$5" | ||
131 | " WHERE ns098records.zone_private_key = $1" | ||
132 | " AND ns098records.label = $6", | ||
133 | 6), | ||
134 | GNUNET_PQ_make_prepare ("delete_records", | ||
135 | "DELETE FROM ns098records " | ||
136 | "WHERE zone_private_key=$1 AND label=$2", | ||
137 | 2), | ||
138 | GNUNET_PQ_make_prepare ("zone_to_name", | ||
139 | "SELECT seq,record_count,record_data,label FROM ns098records" | ||
140 | " WHERE zone_private_key=$1 AND pkey=$2", | ||
141 | 2), | ||
142 | GNUNET_PQ_make_prepare ("iterate_zone", | ||
143 | "SELECT seq,record_count,record_data,label FROM ns098records " | ||
144 | "WHERE zone_private_key=$1 AND seq > $2 ORDER BY seq ASC LIMIT $3", | ||
145 | 3), | ||
146 | GNUNET_PQ_make_prepare ("iterate_all_zones", | ||
147 | "SELECT seq,record_count,record_data,label,zone_private_key" | ||
148 | " FROM ns098records WHERE seq > $1 ORDER BY seq ASC LIMIT $2", | ||
149 | 2), | ||
150 | GNUNET_PQ_make_prepare ("lookup_label", | ||
151 | "SELECT seq,record_count,record_data,label " | ||
152 | "FROM ns098records WHERE zone_private_key=$1 AND label=$2", | ||
153 | 2), | ||
154 | GNUNET_PQ_PREPARED_STATEMENT_END | ||
155 | }; | ||
156 | |||
157 | plugin->dbh = GNUNET_PQ_connect_with_cfg (plugin->cfg, | ||
158 | "namestore-postgres", | ||
159 | NULL, | ||
160 | es, | ||
161 | ps); | ||
162 | } | ||
163 | if (NULL == plugin->dbh) | ||
164 | return GNUNET_SYSERR; | ||
165 | return GNUNET_OK; | ||
166 | } | ||
167 | |||
168 | |||
169 | /** | ||
170 | * Store a record in the datastore. Removes any existing record in the | ||
171 | * same zone with the same name. | ||
172 | * | ||
173 | * @param cls closure (internal context for the plugin) | ||
174 | * @param zone_key private key of the zone | ||
175 | * @param label name that is being mapped (at most 255 characters long) | ||
176 | * @param rd_count number of entries in @a rd array | ||
177 | * @param rd array of records with data to store | ||
178 | * @return #GNUNET_OK on success, else #GNUNET_SYSERR | ||
179 | */ | ||
180 | static int | ||
181 | namestore_postgres_store_records (void *cls, | ||
182 | const struct | ||
183 | GNUNET_IDENTITY_PrivateKey *zone_key, | ||
184 | const char *label, | ||
185 | unsigned int rd_count, | ||
186 | const struct GNUNET_GNSRECORD_Data *rd) | ||
187 | { | ||
188 | struct Plugin *plugin = cls; | ||
189 | struct GNUNET_IDENTITY_PublicKey pkey; | ||
190 | uint64_t rvalue; | ||
191 | uint32_t rd_count32 = (uint32_t) rd_count; | ||
192 | ssize_t data_size; | ||
193 | |||
194 | memset (&pkey, | ||
195 | 0, | ||
196 | sizeof(pkey)); | ||
197 | for (unsigned int i = 0; i < rd_count; i++) | ||
198 | if (GNUNET_YES == | ||
199 | GNUNET_GNSRECORD_is_zonekey_type (rd[i].record_type)) | ||
200 | { | ||
201 | GNUNET_break (GNUNET_OK == | ||
202 | GNUNET_GNSRECORD_identity_from_data (rd[i].data, | ||
203 | rd[i].data_size, | ||
204 | rd[i].record_type, | ||
205 | &pkey)); | ||
206 | break; | ||
207 | } | ||
208 | rvalue = GNUNET_CRYPTO_random_u64 (GNUNET_CRYPTO_QUALITY_WEAK, | ||
209 | UINT64_MAX); | ||
210 | data_size = GNUNET_GNSRECORD_records_get_size (rd_count, | ||
211 | rd); | ||
212 | if (data_size < 0) | ||
213 | { | ||
214 | GNUNET_break (0); | ||
215 | return GNUNET_SYSERR; | ||
216 | } | ||
217 | if (data_size >= UINT16_MAX) | ||
218 | { | ||
219 | GNUNET_break (0); | ||
220 | return GNUNET_SYSERR; | ||
221 | } | ||
222 | /* if record set is empty, delete existing records */ | ||
223 | if (0 == rd_count) | ||
224 | { | ||
225 | struct GNUNET_PQ_QueryParam params[] = { | ||
226 | GNUNET_PQ_query_param_auto_from_type (zone_key), | ||
227 | GNUNET_PQ_query_param_string (label), | ||
228 | GNUNET_PQ_query_param_end | ||
229 | }; | ||
230 | enum GNUNET_DB_QueryStatus res; | ||
231 | |||
232 | res = GNUNET_PQ_eval_prepared_non_select (plugin->dbh, | ||
233 | "delete_records", | ||
234 | params); | ||
235 | if ((GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != res) && | ||
236 | (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS != res)) | ||
237 | { | ||
238 | GNUNET_break (0); | ||
239 | return GNUNET_SYSERR; | ||
240 | } | ||
241 | GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, | ||
242 | "postgres", | ||
243 | "Record deleted\n"); | ||
244 | return GNUNET_OK; | ||
245 | } | ||
246 | /* otherwise, UPSERT (i.e. UPDATE if exists, otherwise INSERT) */ | ||
247 | { | ||
248 | char data[data_size]; | ||
249 | struct GNUNET_PQ_QueryParam params[] = { | ||
250 | GNUNET_PQ_query_param_auto_from_type (zone_key), | ||
251 | GNUNET_PQ_query_param_auto_from_type (&pkey), | ||
252 | GNUNET_PQ_query_param_uint64 (&rvalue), | ||
253 | GNUNET_PQ_query_param_uint32 (&rd_count32), | ||
254 | GNUNET_PQ_query_param_fixed_size (data, data_size), | ||
255 | GNUNET_PQ_query_param_string (label), | ||
256 | GNUNET_PQ_query_param_end | ||
257 | }; | ||
258 | enum GNUNET_DB_QueryStatus res; | ||
259 | ssize_t ret; | ||
260 | |||
261 | ret = GNUNET_GNSRECORD_records_serialize (rd_count, | ||
262 | rd, | ||
263 | data_size, | ||
264 | data); | ||
265 | if ((ret < 0) || | ||
266 | (data_size != ret)) | ||
267 | { | ||
268 | GNUNET_break (0); | ||
269 | return GNUNET_SYSERR; | ||
270 | } | ||
271 | |||
272 | res = GNUNET_PQ_eval_prepared_non_select (plugin->dbh, | ||
273 | "store_records", | ||
274 | params); | ||
275 | if (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != res) | ||
276 | return GNUNET_SYSERR; | ||
277 | } | ||
278 | return GNUNET_OK; | ||
279 | } | ||
280 | |||
281 | |||
282 | /** | ||
283 | * Closure for #parse_result_call_iterator. | ||
284 | */ | ||
285 | struct ParserContext | ||
286 | { | ||
287 | /** | ||
288 | * Function to call for each result. | ||
289 | */ | ||
290 | GNUNET_NAMESTORE_RecordIterator iter; | ||
291 | |||
292 | /** | ||
293 | * Closure for @e iter. | ||
294 | */ | ||
295 | void *iter_cls; | ||
296 | |||
297 | /** | ||
298 | * Zone key, NULL if part of record. | ||
299 | */ | ||
300 | const struct GNUNET_IDENTITY_PrivateKey *zone_key; | ||
301 | |||
302 | /** | ||
303 | * Number of results still to return (counted down by | ||
304 | * number of results given to iterator). | ||
305 | */ | ||
306 | uint64_t limit; | ||
307 | }; | ||
308 | |||
309 | |||
310 | /** | ||
311 | * A statement has been run. We should evaluate the result, and if possible | ||
312 | * call the @a iter in @a cls with the result. | ||
313 | * | ||
314 | * @param cls closure of type `struct ParserContext *` | ||
315 | * @param result the postgres result | ||
316 | * @param num_result the number of results in @a result | ||
317 | */ | ||
318 | static void | ||
319 | parse_result_call_iterator (void *cls, | ||
320 | PGresult *res, | ||
321 | unsigned int num_results) | ||
322 | { | ||
323 | struct ParserContext *pc = cls; | ||
324 | |||
325 | if (NULL == pc->iter) | ||
326 | return; /* no need to do more work */ | ||
327 | for (unsigned int i = 0; i < num_results; i++) | ||
328 | { | ||
329 | uint64_t serial; | ||
330 | void *data; | ||
331 | size_t data_size; | ||
332 | uint32_t record_count; | ||
333 | char *label; | ||
334 | struct GNUNET_IDENTITY_PrivateKey zk; | ||
335 | struct GNUNET_PQ_ResultSpec rs_with_zone[] = { | ||
336 | GNUNET_PQ_result_spec_uint64 ("seq", &serial), | ||
337 | GNUNET_PQ_result_spec_uint32 ("record_count", &record_count), | ||
338 | GNUNET_PQ_result_spec_variable_size ("record_data", &data, &data_size), | ||
339 | GNUNET_PQ_result_spec_string ("label", &label), | ||
340 | GNUNET_PQ_result_spec_auto_from_type ("zone_private_key", &zk), | ||
341 | GNUNET_PQ_result_spec_end | ||
342 | }; | ||
343 | struct GNUNET_PQ_ResultSpec rs_without_zone[] = { | ||
344 | GNUNET_PQ_result_spec_uint64 ("seq", &serial), | ||
345 | GNUNET_PQ_result_spec_uint32 ("record_count", &record_count), | ||
346 | GNUNET_PQ_result_spec_variable_size ("record_data", &data, &data_size), | ||
347 | GNUNET_PQ_result_spec_string ("label", &label), | ||
348 | GNUNET_PQ_result_spec_end | ||
349 | }; | ||
350 | struct GNUNET_PQ_ResultSpec *rs; | ||
351 | |||
352 | rs = (NULL == pc->zone_key) ? rs_with_zone : rs_without_zone; | ||
353 | if (GNUNET_YES != | ||
354 | GNUNET_PQ_extract_result (res, | ||
355 | rs, | ||
356 | i)) | ||
357 | { | ||
358 | GNUNET_break (0); | ||
359 | return; | ||
360 | } | ||
361 | |||
362 | if (record_count > 64 * 1024) | ||
363 | { | ||
364 | /* sanity check, don't stack allocate far too much just | ||
365 | because database might contain a large value here */ | ||
366 | GNUNET_break (0); | ||
367 | GNUNET_PQ_cleanup_result (rs); | ||
368 | return; | ||
369 | } | ||
370 | |||
371 | { | ||
372 | struct GNUNET_GNSRECORD_Data rd[GNUNET_NZL (record_count)]; | ||
373 | |||
374 | GNUNET_assert (0 != serial); | ||
375 | if (GNUNET_OK != | ||
376 | GNUNET_GNSRECORD_records_deserialize (data_size, | ||
377 | data, | ||
378 | record_count, | ||
379 | rd)) | ||
380 | { | ||
381 | GNUNET_break (0); | ||
382 | GNUNET_PQ_cleanup_result (rs); | ||
383 | return; | ||
384 | } | ||
385 | pc->iter (pc->iter_cls, | ||
386 | serial, | ||
387 | (NULL == pc->zone_key) ? &zk : pc->zone_key, | ||
388 | label, | ||
389 | record_count, | ||
390 | rd); | ||
391 | } | ||
392 | GNUNET_PQ_cleanup_result (rs); | ||
393 | } | ||
394 | pc->limit -= num_results; | ||
395 | } | ||
396 | |||
397 | |||
398 | /** | ||
399 | * Lookup records in the datastore for which we are the authority. | ||
400 | * | ||
401 | * @param cls closure (internal context for the plugin) | ||
402 | * @param zone private key of the zone | ||
403 | * @param label name of the record in the zone | ||
404 | * @param iter function to call with the result | ||
405 | * @param iter_cls closure for @a iter | ||
406 | * @return #GNUNET_OK on success, #GNUNET_NO for no results, else #GNUNET_SYSERR | ||
407 | */ | ||
408 | static int | ||
409 | namestore_postgres_lookup_records (void *cls, | ||
410 | const struct | ||
411 | GNUNET_IDENTITY_PrivateKey *zone, | ||
412 | const char *label, | ||
413 | GNUNET_NAMESTORE_RecordIterator iter, | ||
414 | void *iter_cls) | ||
415 | { | ||
416 | struct Plugin *plugin = cls; | ||
417 | struct GNUNET_PQ_QueryParam params[] = { | ||
418 | GNUNET_PQ_query_param_auto_from_type (zone), | ||
419 | GNUNET_PQ_query_param_string (label), | ||
420 | GNUNET_PQ_query_param_end | ||
421 | }; | ||
422 | struct ParserContext pc; | ||
423 | enum GNUNET_DB_QueryStatus res; | ||
424 | |||
425 | if (NULL == zone) | ||
426 | { | ||
427 | GNUNET_break (0); | ||
428 | return GNUNET_SYSERR; | ||
429 | } | ||
430 | pc.iter = iter; | ||
431 | pc.iter_cls = iter_cls; | ||
432 | pc.zone_key = zone; | ||
433 | res = GNUNET_PQ_eval_prepared_multi_select (plugin->dbh, | ||
434 | "lookup_label", | ||
435 | params, | ||
436 | &parse_result_call_iterator, | ||
437 | &pc); | ||
438 | if (res < 0) | ||
439 | return GNUNET_SYSERR; | ||
440 | if (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS == res) | ||
441 | return GNUNET_NO; | ||
442 | return GNUNET_OK; | ||
443 | } | ||
444 | |||
445 | |||
446 | /** | ||
447 | * Iterate over the results for a particular key and zone in the | ||
448 | * datastore. Will return at most one result to the iterator. | ||
449 | * | ||
450 | * @param cls closure (internal context for the plugin) | ||
451 | * @param zone hash of public key of the zone, NULL to iterate over all zones | ||
452 | * @param serial serial number to exclude in the list of all matching records | ||
453 | * @param limit maximum number of results to fetch | ||
454 | * @param iter function to call with the result | ||
455 | * @param iter_cls closure for @a iter | ||
456 | * @return #GNUNET_OK on success, #GNUNET_NO if there were no more results, #GNUNET_SYSERR on error | ||
457 | */ | ||
458 | static int | ||
459 | namestore_postgres_iterate_records (void *cls, | ||
460 | const struct | ||
461 | GNUNET_IDENTITY_PrivateKey *zone, | ||
462 | uint64_t serial, | ||
463 | uint64_t limit, | ||
464 | GNUNET_NAMESTORE_RecordIterator iter, | ||
465 | void *iter_cls) | ||
466 | { | ||
467 | struct Plugin *plugin = cls; | ||
468 | enum GNUNET_DB_QueryStatus res; | ||
469 | struct ParserContext pc; | ||
470 | |||
471 | pc.iter = iter; | ||
472 | pc.iter_cls = iter_cls; | ||
473 | pc.zone_key = zone; | ||
474 | pc.limit = limit; | ||
475 | if (NULL == zone) | ||
476 | { | ||
477 | struct GNUNET_PQ_QueryParam params_without_zone[] = { | ||
478 | GNUNET_PQ_query_param_uint64 (&serial), | ||
479 | GNUNET_PQ_query_param_uint64 (&limit), | ||
480 | GNUNET_PQ_query_param_end | ||
481 | }; | ||
482 | |||
483 | res = GNUNET_PQ_eval_prepared_multi_select (plugin->dbh, | ||
484 | "iterate_all_zones", | ||
485 | params_without_zone, | ||
486 | &parse_result_call_iterator, | ||
487 | &pc); | ||
488 | } | ||
489 | else | ||
490 | { | ||
491 | struct GNUNET_PQ_QueryParam params_with_zone[] = { | ||
492 | GNUNET_PQ_query_param_auto_from_type (zone), | ||
493 | GNUNET_PQ_query_param_uint64 (&serial), | ||
494 | GNUNET_PQ_query_param_uint64 (&limit), | ||
495 | GNUNET_PQ_query_param_end | ||
496 | }; | ||
497 | |||
498 | res = GNUNET_PQ_eval_prepared_multi_select (plugin->dbh, | ||
499 | "iterate_zone", | ||
500 | params_with_zone, | ||
501 | &parse_result_call_iterator, | ||
502 | &pc); | ||
503 | } | ||
504 | if (res < 0) | ||
505 | return GNUNET_SYSERR; | ||
506 | |||
507 | if ((GNUNET_DB_STATUS_SUCCESS_NO_RESULTS == res) || | ||
508 | (pc.limit > 0)) | ||
509 | return GNUNET_NO; | ||
510 | return GNUNET_OK; | ||
511 | } | ||
512 | |||
513 | |||
514 | /** | ||
515 | * Look for an existing PKEY delegation record for a given public key. | ||
516 | * Returns at most one result to the iterator. | ||
517 | * | ||
518 | * @param cls closure (internal context for the plugin) | ||
519 | * @param zone private key of the zone to look up in, never NULL | ||
520 | * @param value_zone public key of the target zone (value), never NULL | ||
521 | * @param iter function to call with the result | ||
522 | * @param iter_cls closure for @a iter | ||
523 | * @return #GNUNET_OK on success, #GNUNET_NO if there were no results, #GNUNET_SYSERR on error | ||
524 | */ | ||
525 | static int | ||
526 | namestore_postgres_zone_to_name (void *cls, | ||
527 | const struct | ||
528 | GNUNET_IDENTITY_PrivateKey *zone, | ||
529 | const struct | ||
530 | GNUNET_IDENTITY_PublicKey *value_zone, | ||
531 | GNUNET_NAMESTORE_RecordIterator iter, | ||
532 | void *iter_cls) | ||
533 | { | ||
534 | struct Plugin *plugin = cls; | ||
535 | struct GNUNET_PQ_QueryParam params[] = { | ||
536 | GNUNET_PQ_query_param_auto_from_type (zone), | ||
537 | GNUNET_PQ_query_param_auto_from_type (value_zone), | ||
538 | GNUNET_PQ_query_param_end | ||
539 | }; | ||
540 | enum GNUNET_DB_QueryStatus res; | ||
541 | struct ParserContext pc; | ||
542 | |||
543 | pc.iter = iter; | ||
544 | pc.iter_cls = iter_cls; | ||
545 | pc.zone_key = zone; | ||
546 | res = GNUNET_PQ_eval_prepared_multi_select (plugin->dbh, | ||
547 | "zone_to_name", | ||
548 | params, | ||
549 | &parse_result_call_iterator, | ||
550 | &pc); | ||
551 | if (res < 0) | ||
552 | return GNUNET_SYSERR; | ||
553 | return GNUNET_OK; | ||
554 | } | ||
555 | |||
556 | |||
557 | /** | ||
558 | * Shutdown database connection and associate data | ||
559 | * structures. | ||
560 | * | ||
561 | * @param plugin the plugin context (state for this module) | ||
562 | */ | ||
563 | static void | ||
564 | database_shutdown (struct Plugin *plugin) | ||
565 | { | ||
566 | GNUNET_PQ_disconnect (plugin->dbh); | ||
567 | plugin->dbh = NULL; | ||
568 | } | ||
569 | |||
570 | |||
571 | /** | ||
572 | * Entry point for the plugin. | ||
573 | * | ||
574 | * @param cls the `struct GNUNET_NAMESTORE_PluginEnvironment*` | ||
575 | * @return NULL on error, othrewise the plugin context | ||
576 | */ | ||
577 | void * | ||
578 | libgnunet_plugin_namestore_postgres_init (void *cls) | ||
579 | { | ||
580 | static struct Plugin plugin; | ||
581 | const struct GNUNET_CONFIGURATION_Handle *cfg = cls; | ||
582 | struct GNUNET_NAMESTORE_PluginFunctions *api; | ||
583 | |||
584 | if (NULL != plugin.cfg) | ||
585 | return NULL; /* can only initialize once! */ | ||
586 | memset (&plugin, 0, sizeof(struct Plugin)); | ||
587 | plugin.cfg = cfg; | ||
588 | if (GNUNET_OK != database_setup (&plugin)) | ||
589 | { | ||
590 | database_shutdown (&plugin); | ||
591 | return NULL; | ||
592 | } | ||
593 | api = GNUNET_new (struct GNUNET_NAMESTORE_PluginFunctions); | ||
594 | api->cls = &plugin; | ||
595 | api->store_records = &namestore_postgres_store_records; | ||
596 | api->iterate_records = &namestore_postgres_iterate_records; | ||
597 | api->zone_to_name = &namestore_postgres_zone_to_name; | ||
598 | api->lookup_records = &namestore_postgres_lookup_records; | ||
599 | LOG (GNUNET_ERROR_TYPE_INFO, | ||
600 | "Postgres namestore plugin running\n"); | ||
601 | return api; | ||
602 | } | ||
603 | |||
604 | |||
605 | /** | ||
606 | * Exit point from the plugin. | ||
607 | * | ||
608 | * @param cls the plugin context (as returned by "init") | ||
609 | * @return always NULL | ||
610 | */ | ||
611 | void * | ||
612 | libgnunet_plugin_namestore_postgres_done (void *cls) | ||
613 | { | ||
614 | struct GNUNET_NAMESTORE_PluginFunctions *api = cls; | ||
615 | struct Plugin *plugin = api->cls; | ||
616 | |||
617 | database_shutdown (plugin); | ||
618 | plugin->cfg = NULL; | ||
619 | GNUNET_free (api); | ||
620 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
621 | "Postgres namestore plugin is finished\n"); | ||
622 | return NULL; | ||
623 | } | ||
624 | |||
625 | |||
626 | /* end of plugin_namestore_postgres.c */ | ||
diff --git a/src/namestore/plugin_namestore_sqlite.c b/src/namestore/plugin_namestore_sqlite.c deleted file mode 100644 index 7cb9b7ed0..000000000 --- a/src/namestore/plugin_namestore_sqlite.c +++ /dev/null | |||
@@ -1,791 +0,0 @@ | |||
1 | /* | ||
2 | * This file is part of GNUnet | ||
3 | * Copyright (C) 2009-2017 GNUnet e.V. | ||
4 | * | ||
5 | * GNUnet is free software: you can redistribute it and/or modify it | ||
6 | * under the terms of the GNU Affero General Public License as published | ||
7 | * by the Free Software Foundation, either version 3 of the License, | ||
8 | * or (at your option) any later version. | ||
9 | * | ||
10 | * GNUnet is distributed in the hope that it will be useful, but | ||
11 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
13 | * Affero General Public License for more details. | ||
14 | * | ||
15 | * You should have received a copy of the GNU Affero General Public License | ||
16 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
17 | |||
18 | SPDX-License-Identifier: AGPL3.0-or-later | ||
19 | */ | ||
20 | |||
21 | /** | ||
22 | * @file namestore/plugin_namestore_sqlite.c | ||
23 | * @brief sqlite-based namestore backend | ||
24 | * @author Christian Grothoff | ||
25 | */ | ||
26 | |||
27 | #include "platform.h" | ||
28 | #include "gnunet_namestore_plugin.h" | ||
29 | #include "gnunet_namestore_service.h" | ||
30 | #include "gnunet_gnsrecord_lib.h" | ||
31 | #include "gnunet_sq_lib.h" | ||
32 | #include "namestore.h" | ||
33 | #include <sqlite3.h> | ||
34 | |||
35 | /** | ||
36 | * After how many ms "busy" should a DB operation fail for good? A | ||
37 | * low value makes sure that we are more responsive to requests | ||
38 | * (especially PUTs). A high value guarantees a higher success rate | ||
39 | * (SELECTs in iterate can take several seconds despite LIMIT=1). | ||
40 | * | ||
41 | * The default value of 1s should ensure that users do not experience | ||
42 | * huge latencies while at the same time allowing operations to | ||
43 | * succeed with reasonable probability. | ||
44 | */ | ||
45 | #define BUSY_TIMEOUT_MS 1000 | ||
46 | |||
47 | |||
48 | /** | ||
49 | * Log an error message at log-level 'level' that indicates | ||
50 | * a failure of the command 'cmd' on file 'filename' | ||
51 | * with the message given by strerror(errno). | ||
52 | */ | ||
53 | #define LOG_SQLITE(db, level, cmd) do { GNUNET_log_from (level, \ | ||
54 | "namestore-sqlite", _ ( \ | ||
55 | "`%s' failed at %s:%d with error: %s\n"), \ | ||
56 | cmd, \ | ||
57 | __FILE__, __LINE__, \ | ||
58 | sqlite3_errmsg ( \ | ||
59 | db->dbh)); \ | ||
60 | } while (0) | ||
61 | |||
62 | #define LOG(kind, ...) GNUNET_log_from (kind, "namestore-sqlite", __VA_ARGS__) | ||
63 | |||
64 | |||
65 | /** | ||
66 | * Context for all functions in this plugin. | ||
67 | */ | ||
68 | struct Plugin | ||
69 | { | ||
70 | const struct GNUNET_CONFIGURATION_Handle *cfg; | ||
71 | |||
72 | /** | ||
73 | * Database filename. | ||
74 | */ | ||
75 | char *fn; | ||
76 | |||
77 | /** | ||
78 | * Native SQLite database handle. | ||
79 | */ | ||
80 | sqlite3 *dbh; | ||
81 | |||
82 | /** | ||
83 | * Precompiled SQL to store records. | ||
84 | */ | ||
85 | sqlite3_stmt *store_records; | ||
86 | |||
87 | /** | ||
88 | * Precompiled SQL to deltete existing records. | ||
89 | */ | ||
90 | sqlite3_stmt *delete_records; | ||
91 | |||
92 | /** | ||
93 | * Precompiled SQL for iterate records within a zone. | ||
94 | */ | ||
95 | sqlite3_stmt *iterate_zone; | ||
96 | |||
97 | /** | ||
98 | * Precompiled SQL for iterate all records within all zones. | ||
99 | */ | ||
100 | sqlite3_stmt *iterate_all_zones; | ||
101 | |||
102 | /** | ||
103 | * Precompiled SQL to for reverse lookup based on PKEY. | ||
104 | */ | ||
105 | sqlite3_stmt *zone_to_name; | ||
106 | |||
107 | /** | ||
108 | * Precompiled SQL to lookup records based on label. | ||
109 | */ | ||
110 | sqlite3_stmt *lookup_label; | ||
111 | }; | ||
112 | |||
113 | |||
114 | /** | ||
115 | * Initialize the database connections and associated | ||
116 | * data structures (create tables and indices | ||
117 | * as needed as well). | ||
118 | * | ||
119 | * @param plugin the plugin context (state for this module) | ||
120 | * @return #GNUNET_OK on success | ||
121 | */ | ||
122 | static int | ||
123 | database_setup (struct Plugin *plugin) | ||
124 | { | ||
125 | char *sqlite_filename; | ||
126 | struct GNUNET_SQ_ExecuteStatement es[] = { | ||
127 | GNUNET_SQ_make_try_execute ("PRAGMA temp_store=MEMORY"), | ||
128 | GNUNET_SQ_make_try_execute ("PRAGMA synchronous=NORMAL"), | ||
129 | GNUNET_SQ_make_try_execute ("PRAGMA legacy_file_format=OFF"), | ||
130 | GNUNET_SQ_make_try_execute ("PRAGMA auto_vacuum=INCREMENTAL"), | ||
131 | GNUNET_SQ_make_try_execute ("PRAGMA encoding=\"UTF-8\""), | ||
132 | GNUNET_SQ_make_try_execute ("PRAGMA locking_mode=EXCLUSIVE"), | ||
133 | GNUNET_SQ_make_try_execute ("PRAGMA journal_mode=WAL"), | ||
134 | GNUNET_SQ_make_try_execute ("PRAGMA page_size=4092"), | ||
135 | GNUNET_SQ_make_execute ("CREATE TABLE IF NOT EXISTS ns098records (" | ||
136 | " uid INTEGER PRIMARY KEY," | ||
137 | " zone_private_key BLOB NOT NULL," | ||
138 | " pkey BLOB," | ||
139 | " rvalue INT8 NOT NULL," | ||
140 | " record_count INT NOT NULL," | ||
141 | " record_data BLOB NOT NULL," | ||
142 | " label TEXT NOT NULL" | ||
143 | ")"), | ||
144 | GNUNET_SQ_make_try_execute ("CREATE INDEX IF NOT EXISTS ir_pkey_reverse " | ||
145 | "ON ns098records (zone_private_key,pkey)"), | ||
146 | GNUNET_SQ_make_try_execute ("CREATE INDEX IF NOT EXISTS ir_pkey_iter " | ||
147 | "ON ns098records (zone_private_key,uid)"), | ||
148 | GNUNET_SQ_EXECUTE_STATEMENT_END | ||
149 | }; | ||
150 | struct GNUNET_SQ_PrepareStatement ps[] = { | ||
151 | GNUNET_SQ_make_prepare ("INSERT INTO ns098records " | ||
152 | "(zone_private_key,pkey,rvalue,record_count,record_data,label)" | ||
153 | " VALUES (?, ?, ?, ?, ?, ?)", | ||
154 | &plugin->store_records), | ||
155 | GNUNET_SQ_make_prepare ("DELETE FROM ns098records " | ||
156 | "WHERE zone_private_key=? AND label=?", | ||
157 | &plugin->delete_records), | ||
158 | GNUNET_SQ_make_prepare ("SELECT uid,record_count,record_data,label" | ||
159 | " FROM ns098records" | ||
160 | " WHERE zone_private_key=? AND pkey=?", | ||
161 | &plugin->zone_to_name), | ||
162 | GNUNET_SQ_make_prepare ("SELECT uid,record_count,record_data,label" | ||
163 | " FROM ns098records" | ||
164 | " WHERE zone_private_key=? AND uid > ?" | ||
165 | " ORDER BY uid ASC" | ||
166 | " LIMIT ?", | ||
167 | &plugin->iterate_zone), | ||
168 | GNUNET_SQ_make_prepare ( | ||
169 | "SELECT uid,record_count,record_data,label,zone_private_key" | ||
170 | " FROM ns098records" | ||
171 | " WHERE uid > ?" | ||
172 | " ORDER BY uid ASC" | ||
173 | " LIMIT ?", | ||
174 | &plugin->iterate_all_zones), | ||
175 | GNUNET_SQ_make_prepare ("SELECT uid,record_count,record_data,label" | ||
176 | " FROM ns098records" | ||
177 | " WHERE zone_private_key=? AND label=?", | ||
178 | &plugin->lookup_label), | ||
179 | GNUNET_SQ_PREPARE_END | ||
180 | }; | ||
181 | |||
182 | if (GNUNET_OK != | ||
183 | GNUNET_CONFIGURATION_get_value_filename (plugin->cfg, | ||
184 | "namestore-sqlite", | ||
185 | "FILENAME", | ||
186 | &sqlite_filename)) | ||
187 | { | ||
188 | GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR, | ||
189 | "namestore-sqlite", | ||
190 | "FILENAME"); | ||
191 | return GNUNET_SYSERR; | ||
192 | } | ||
193 | if (GNUNET_OK != | ||
194 | GNUNET_DISK_file_test (sqlite_filename)) | ||
195 | { | ||
196 | if (GNUNET_OK != | ||
197 | GNUNET_DISK_directory_create_for_file (sqlite_filename)) | ||
198 | { | ||
199 | GNUNET_break (0); | ||
200 | GNUNET_free (sqlite_filename); | ||
201 | return GNUNET_SYSERR; | ||
202 | } | ||
203 | } | ||
204 | /* sqlite_filename should be UTF-8-encoded. If it isn't, it's a bug */ | ||
205 | plugin->fn = sqlite_filename; | ||
206 | |||
207 | /* Open database and precompile statements */ | ||
208 | if (SQLITE_OK != | ||
209 | sqlite3_open (plugin->fn, | ||
210 | &plugin->dbh)) | ||
211 | { | ||
212 | LOG (GNUNET_ERROR_TYPE_ERROR, | ||
213 | _ ("Unable to initialize SQLite: %s.\n"), | ||
214 | sqlite3_errmsg (plugin->dbh)); | ||
215 | return GNUNET_SYSERR; | ||
216 | } | ||
217 | GNUNET_break (SQLITE_OK == | ||
218 | sqlite3_busy_timeout (plugin->dbh, | ||
219 | BUSY_TIMEOUT_MS)); | ||
220 | if (GNUNET_OK != | ||
221 | GNUNET_SQ_exec_statements (plugin->dbh, | ||
222 | es)) | ||
223 | { | ||
224 | GNUNET_break (0); | ||
225 | LOG (GNUNET_ERROR_TYPE_ERROR, | ||
226 | _ ("Failed to setup database at `%s'\n"), | ||
227 | plugin->fn); | ||
228 | return GNUNET_SYSERR; | ||
229 | } | ||
230 | |||
231 | if (GNUNET_OK != | ||
232 | GNUNET_SQ_prepare (plugin->dbh, | ||
233 | ps)) | ||
234 | { | ||
235 | GNUNET_break (0); | ||
236 | LOG (GNUNET_ERROR_TYPE_ERROR, | ||
237 | _ ("Failed to setup database at `%s'\n"), | ||
238 | plugin->fn); | ||
239 | return GNUNET_SYSERR; | ||
240 | } | ||
241 | return GNUNET_OK; | ||
242 | } | ||
243 | |||
244 | |||
245 | /** | ||
246 | * Shutdown database connection and associate data | ||
247 | * structures. | ||
248 | * @param plugin the plugin context (state for this module) | ||
249 | */ | ||
250 | static void | ||
251 | database_shutdown (struct Plugin *plugin) | ||
252 | { | ||
253 | int result; | ||
254 | sqlite3_stmt *stmt; | ||
255 | |||
256 | if (NULL != plugin->store_records) | ||
257 | sqlite3_finalize (plugin->store_records); | ||
258 | if (NULL != plugin->delete_records) | ||
259 | sqlite3_finalize (plugin->delete_records); | ||
260 | if (NULL != plugin->iterate_zone) | ||
261 | sqlite3_finalize (plugin->iterate_zone); | ||
262 | if (NULL != plugin->iterate_all_zones) | ||
263 | sqlite3_finalize (plugin->iterate_all_zones); | ||
264 | if (NULL != plugin->zone_to_name) | ||
265 | sqlite3_finalize (plugin->zone_to_name); | ||
266 | if (NULL != plugin->lookup_label) | ||
267 | sqlite3_finalize (plugin->lookup_label); | ||
268 | result = sqlite3_close (plugin->dbh); | ||
269 | if (result == SQLITE_BUSY) | ||
270 | { | ||
271 | LOG (GNUNET_ERROR_TYPE_WARNING, | ||
272 | _ ( | ||
273 | "Tried to close sqlite without finalizing all prepared statements.\n")); | ||
274 | stmt = sqlite3_next_stmt (plugin->dbh, | ||
275 | NULL); | ||
276 | while (NULL != stmt) | ||
277 | { | ||
278 | GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, | ||
279 | "sqlite", | ||
280 | "Closing statement %p\n", | ||
281 | stmt); | ||
282 | result = sqlite3_finalize (stmt); | ||
283 | if (result != SQLITE_OK) | ||
284 | GNUNET_log_from (GNUNET_ERROR_TYPE_WARNING, | ||
285 | "sqlite", | ||
286 | "Failed to close statement %p: %d\n", | ||
287 | stmt, | ||
288 | result); | ||
289 | stmt = sqlite3_next_stmt (plugin->dbh, | ||
290 | NULL); | ||
291 | } | ||
292 | result = sqlite3_close (plugin->dbh); | ||
293 | } | ||
294 | if (SQLITE_OK != result) | ||
295 | LOG_SQLITE (plugin, | ||
296 | GNUNET_ERROR_TYPE_ERROR, | ||
297 | "sqlite3_close"); | ||
298 | |||
299 | GNUNET_free (plugin->fn); | ||
300 | } | ||
301 | |||
302 | |||
303 | /** | ||
304 | * Store a record in the datastore. Removes any existing record in the | ||
305 | * same zone with the same name. | ||
306 | * | ||
307 | * @param cls closure (internal context for the plugin) | ||
308 | * @param zone_key private key of the zone | ||
309 | * @param label name that is being mapped (at most 255 characters long) | ||
310 | * @param rd_count number of entries in @a rd array | ||
311 | * @param rd array of records with data to store | ||
312 | * @return #GNUNET_OK on success, else #GNUNET_SYSERR | ||
313 | */ | ||
314 | static int | ||
315 | namestore_sqlite_store_records (void *cls, | ||
316 | const struct | ||
317 | GNUNET_IDENTITY_PrivateKey *zone_key, | ||
318 | const char *label, | ||
319 | unsigned int rd_count, | ||
320 | const struct GNUNET_GNSRECORD_Data *rd) | ||
321 | { | ||
322 | struct Plugin *plugin = cls; | ||
323 | int n; | ||
324 | struct GNUNET_IDENTITY_PublicKey pkey; | ||
325 | uint64_t rvalue; | ||
326 | ssize_t data_size; | ||
327 | |||
328 | memset (&pkey, | ||
329 | 0, | ||
330 | sizeof(pkey)); | ||
331 | for (unsigned int i = 0; i < rd_count; i++) | ||
332 | if (GNUNET_YES == GNUNET_GNSRECORD_is_zonekey_type (rd[i].record_type)) | ||
333 | { | ||
334 | GNUNET_break (GNUNET_YES == | ||
335 | GNUNET_GNSRECORD_identity_from_data (rd[i].data, | ||
336 | rd[i].data_size, | ||
337 | rd[i].record_type, | ||
338 | &pkey)); | ||
339 | break; | ||
340 | } | ||
341 | rvalue = GNUNET_CRYPTO_random_u64 (GNUNET_CRYPTO_QUALITY_WEAK, | ||
342 | UINT64_MAX); | ||
343 | data_size = GNUNET_GNSRECORD_records_get_size (rd_count, | ||
344 | rd); | ||
345 | if (data_size < 0) | ||
346 | { | ||
347 | GNUNET_break (0); | ||
348 | return GNUNET_SYSERR; | ||
349 | } | ||
350 | if (data_size > 64 * 65536) | ||
351 | { | ||
352 | GNUNET_break (0); | ||
353 | return GNUNET_SYSERR; | ||
354 | } | ||
355 | { | ||
356 | /* First delete 'old' records */ | ||
357 | char data[data_size]; | ||
358 | struct GNUNET_SQ_QueryParam dparams[] = { | ||
359 | GNUNET_SQ_query_param_auto_from_type (zone_key), | ||
360 | GNUNET_SQ_query_param_string (label), | ||
361 | GNUNET_SQ_query_param_end | ||
362 | }; | ||
363 | ssize_t ret; | ||
364 | |||
365 | ret = GNUNET_GNSRECORD_records_serialize (rd_count, | ||
366 | rd, | ||
367 | data_size, | ||
368 | data); | ||
369 | if ((ret < 0) || | ||
370 | (data_size != ret)) | ||
371 | { | ||
372 | GNUNET_break (0); | ||
373 | return GNUNET_SYSERR; | ||
374 | } | ||
375 | if (GNUNET_OK != | ||
376 | GNUNET_SQ_bind (plugin->delete_records, | ||
377 | dparams)) | ||
378 | { | ||
379 | LOG_SQLITE (plugin, | ||
380 | GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, | ||
381 | "sqlite3_bind_XXXX"); | ||
382 | GNUNET_SQ_reset (plugin->dbh, | ||
383 | plugin->delete_records); | ||
384 | return GNUNET_SYSERR; | ||
385 | } | ||
386 | n = sqlite3_step (plugin->delete_records); | ||
387 | GNUNET_SQ_reset (plugin->dbh, | ||
388 | plugin->delete_records); | ||
389 | |||
390 | if (0 != rd_count) | ||
391 | { | ||
392 | uint32_t rd_count32 = (uint32_t) rd_count; | ||
393 | struct GNUNET_SQ_QueryParam sparams[] = { | ||
394 | GNUNET_SQ_query_param_auto_from_type (zone_key), | ||
395 | GNUNET_SQ_query_param_auto_from_type (&pkey), | ||
396 | GNUNET_SQ_query_param_uint64 (&rvalue), | ||
397 | GNUNET_SQ_query_param_uint32 (&rd_count32), | ||
398 | GNUNET_SQ_query_param_fixed_size (data, data_size), | ||
399 | GNUNET_SQ_query_param_string (label), | ||
400 | GNUNET_SQ_query_param_end | ||
401 | }; | ||
402 | |||
403 | if (GNUNET_OK != | ||
404 | GNUNET_SQ_bind (plugin->store_records, | ||
405 | sparams)) | ||
406 | { | ||
407 | LOG_SQLITE (plugin, | ||
408 | GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, | ||
409 | "sqlite3_bind_XXXX"); | ||
410 | GNUNET_SQ_reset (plugin->dbh, | ||
411 | plugin->store_records); | ||
412 | return GNUNET_SYSERR; | ||
413 | } | ||
414 | n = sqlite3_step (plugin->store_records); | ||
415 | GNUNET_SQ_reset (plugin->dbh, | ||
416 | plugin->store_records); | ||
417 | } | ||
418 | } | ||
419 | switch (n) | ||
420 | { | ||
421 | case SQLITE_DONE: | ||
422 | if (0 != rd_count) | ||
423 | GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, | ||
424 | "sqlite", | ||
425 | "Record stored\n"); | ||
426 | else | ||
427 | GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, | ||
428 | "sqlite", | ||
429 | "Record deleted\n"); | ||
430 | return GNUNET_OK; | ||
431 | |||
432 | case SQLITE_BUSY: | ||
433 | LOG_SQLITE (plugin, | ||
434 | GNUNET_ERROR_TYPE_WARNING | GNUNET_ERROR_TYPE_BULK, | ||
435 | "sqlite3_step"); | ||
436 | return GNUNET_NO; | ||
437 | |||
438 | default: | ||
439 | LOG_SQLITE (plugin, | ||
440 | GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, | ||
441 | "sqlite3_step"); | ||
442 | return GNUNET_SYSERR; | ||
443 | } | ||
444 | } | ||
445 | |||
446 | |||
447 | /** | ||
448 | * The given 'sqlite' statement has been prepared to be run. | ||
449 | * It will return a record which should be given to the iterator. | ||
450 | * Runs the statement and parses the returned record. | ||
451 | * | ||
452 | * @param plugin plugin context | ||
453 | * @param stmt to run (and then clean up) | ||
454 | * @param zone_key private key of the zone | ||
455 | * @param limit maximum number of results to fetch | ||
456 | * @param iter iterator to call with the result | ||
457 | * @param iter_cls closure for @a iter | ||
458 | * @return #GNUNET_OK on success, #GNUNET_NO if there were no results, #GNUNET_SYSERR on error | ||
459 | */ | ||
460 | static int | ||
461 | get_records_and_call_iterator (struct Plugin *plugin, | ||
462 | sqlite3_stmt *stmt, | ||
463 | const struct | ||
464 | GNUNET_IDENTITY_PrivateKey *zone_key, | ||
465 | uint64_t limit, | ||
466 | GNUNET_NAMESTORE_RecordIterator iter, | ||
467 | void *iter_cls) | ||
468 | { | ||
469 | int ret; | ||
470 | int sret; | ||
471 | |||
472 | ret = GNUNET_OK; | ||
473 | for (uint64_t i = 0; i < limit; i++) | ||
474 | { | ||
475 | sret = sqlite3_step (stmt); | ||
476 | |||
477 | if (SQLITE_DONE == sret) | ||
478 | { | ||
479 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
480 | "Iteration done (no results)\n"); | ||
481 | ret = GNUNET_NO; | ||
482 | break; | ||
483 | } | ||
484 | if (SQLITE_ROW != sret) | ||
485 | { | ||
486 | LOG_SQLITE (plugin, | ||
487 | GNUNET_ERROR_TYPE_ERROR, | ||
488 | "sqlite_step"); | ||
489 | ret = GNUNET_SYSERR; | ||
490 | break; | ||
491 | } | ||
492 | |||
493 | { | ||
494 | uint64_t seq; | ||
495 | uint32_t record_count; | ||
496 | size_t data_size; | ||
497 | void *data; | ||
498 | char *label; | ||
499 | struct GNUNET_IDENTITY_PrivateKey zk; | ||
500 | struct GNUNET_SQ_ResultSpec rs[] = { | ||
501 | GNUNET_SQ_result_spec_uint64 (&seq), | ||
502 | GNUNET_SQ_result_spec_uint32 (&record_count), | ||
503 | GNUNET_SQ_result_spec_variable_size (&data, | ||
504 | &data_size), | ||
505 | GNUNET_SQ_result_spec_string (&label), | ||
506 | GNUNET_SQ_result_spec_end | ||
507 | }; | ||
508 | struct GNUNET_SQ_ResultSpec rsx[] = { | ||
509 | GNUNET_SQ_result_spec_uint64 (&seq), | ||
510 | GNUNET_SQ_result_spec_uint32 (&record_count), | ||
511 | GNUNET_SQ_result_spec_variable_size (&data, | ||
512 | &data_size), | ||
513 | GNUNET_SQ_result_spec_string (&label), | ||
514 | GNUNET_SQ_result_spec_auto_from_type (&zk), | ||
515 | GNUNET_SQ_result_spec_end | ||
516 | }; | ||
517 | |||
518 | ret = GNUNET_SQ_extract_result (stmt, | ||
519 | (NULL == zone_key) | ||
520 | ? rsx | ||
521 | : rs); | ||
522 | if ((GNUNET_OK != ret) || | ||
523 | (record_count > 64 * 1024)) | ||
524 | { | ||
525 | /* sanity check, don't stack allocate far too much just | ||
526 | because database might contain a large value here */ | ||
527 | GNUNET_break (0); | ||
528 | ret = GNUNET_SYSERR; | ||
529 | break; | ||
530 | } | ||
531 | else | ||
532 | { | ||
533 | struct GNUNET_GNSRECORD_Data rd[record_count]; | ||
534 | |||
535 | GNUNET_assert (0 != seq); | ||
536 | if (GNUNET_OK != | ||
537 | GNUNET_GNSRECORD_records_deserialize (data_size, | ||
538 | data, | ||
539 | record_count, | ||
540 | rd)) | ||
541 | { | ||
542 | GNUNET_break (0); | ||
543 | ret = GNUNET_SYSERR; | ||
544 | break; | ||
545 | } | ||
546 | else | ||
547 | { | ||
548 | if (NULL != zone_key) | ||
549 | zk = *zone_key; | ||
550 | if (NULL != iter) | ||
551 | iter (iter_cls, | ||
552 | seq, | ||
553 | &zk, | ||
554 | label, | ||
555 | record_count, | ||
556 | rd); | ||
557 | } | ||
558 | } | ||
559 | GNUNET_SQ_cleanup_result (rs); | ||
560 | } | ||
561 | } | ||
562 | GNUNET_SQ_reset (plugin->dbh, | ||
563 | stmt); | ||
564 | return ret; | ||
565 | } | ||
566 | |||
567 | |||
568 | /** | ||
569 | * Lookup records in the datastore for which we are the authority. | ||
570 | * | ||
571 | * @param cls closure (internal context for the plugin) | ||
572 | * @param zone private key of the zone | ||
573 | * @param label name of the record in the zone | ||
574 | * @param iter function to call with the result | ||
575 | * @param iter_cls closure for @a iter | ||
576 | * @return #GNUNET_OK on success, #GNUNET_NO for no results, else #GNUNET_SYSERR | ||
577 | */ | ||
578 | static int | ||
579 | namestore_sqlite_lookup_records (void *cls, | ||
580 | const struct | ||
581 | GNUNET_IDENTITY_PrivateKey *zone, | ||
582 | const char *label, | ||
583 | GNUNET_NAMESTORE_RecordIterator iter, | ||
584 | void *iter_cls) | ||
585 | { | ||
586 | struct Plugin *plugin = cls; | ||
587 | struct GNUNET_SQ_QueryParam params[] = { | ||
588 | GNUNET_SQ_query_param_auto_from_type (zone), | ||
589 | GNUNET_SQ_query_param_string (label), | ||
590 | GNUNET_SQ_query_param_end | ||
591 | }; | ||
592 | |||
593 | if (NULL == zone) | ||
594 | { | ||
595 | GNUNET_break (0); | ||
596 | return GNUNET_SYSERR; | ||
597 | } | ||
598 | if (GNUNET_OK != | ||
599 | GNUNET_SQ_bind (plugin->lookup_label, | ||
600 | params)) | ||
601 | { | ||
602 | LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, | ||
603 | "sqlite3_bind_XXXX"); | ||
604 | GNUNET_SQ_reset (plugin->dbh, | ||
605 | plugin->lookup_label); | ||
606 | return GNUNET_SYSERR; | ||
607 | } | ||
608 | return get_records_and_call_iterator (plugin, | ||
609 | plugin->lookup_label, | ||
610 | zone, | ||
611 | 1, | ||
612 | iter, | ||
613 | iter_cls); | ||
614 | } | ||
615 | |||
616 | |||
617 | /** | ||
618 | * Iterate over the results for a particular key and zone in the | ||
619 | * datastore. Will return at most one result to the iterator. | ||
620 | * | ||
621 | * @param cls closure (internal context for the plugin) | ||
622 | * @param zone hash of public key of the zone, NULL to iterate over all zones | ||
623 | * @param serial serial number to exclude in the list of all matching records | ||
624 | * @param limit maximum number of results to return | ||
625 | * @param iter function to call with the result | ||
626 | * @param iter_cls closure for @a iter | ||
627 | * @return #GNUNET_OK on success, #GNUNET_NO if there were no more results, #GNUNET_SYSERR on error | ||
628 | */ | ||
629 | static int | ||
630 | namestore_sqlite_iterate_records (void *cls, | ||
631 | const struct | ||
632 | GNUNET_IDENTITY_PrivateKey *zone, | ||
633 | uint64_t serial, | ||
634 | uint64_t limit, | ||
635 | GNUNET_NAMESTORE_RecordIterator iter, | ||
636 | void *iter_cls) | ||
637 | { | ||
638 | struct Plugin *plugin = cls; | ||
639 | sqlite3_stmt *stmt; | ||
640 | int err; | ||
641 | |||
642 | if (NULL == zone) | ||
643 | { | ||
644 | struct GNUNET_SQ_QueryParam params[] = { | ||
645 | GNUNET_SQ_query_param_uint64 (&serial), | ||
646 | GNUNET_SQ_query_param_uint64 (&limit), | ||
647 | GNUNET_SQ_query_param_end | ||
648 | }; | ||
649 | |||
650 | stmt = plugin->iterate_all_zones; | ||
651 | err = GNUNET_SQ_bind (stmt, | ||
652 | params); | ||
653 | } | ||
654 | else | ||
655 | { | ||
656 | struct GNUNET_SQ_QueryParam params[] = { | ||
657 | GNUNET_SQ_query_param_auto_from_type (zone), | ||
658 | GNUNET_SQ_query_param_uint64 (&serial), | ||
659 | GNUNET_SQ_query_param_uint64 (&limit), | ||
660 | GNUNET_SQ_query_param_end | ||
661 | }; | ||
662 | |||
663 | stmt = plugin->iterate_zone; | ||
664 | err = GNUNET_SQ_bind (stmt, | ||
665 | params); | ||
666 | } | ||
667 | if (GNUNET_OK != err) | ||
668 | { | ||
669 | LOG_SQLITE (plugin, | ||
670 | GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, | ||
671 | "sqlite3_bind_XXXX"); | ||
672 | GNUNET_SQ_reset (plugin->dbh, | ||
673 | stmt); | ||
674 | return GNUNET_SYSERR; | ||
675 | } | ||
676 | return get_records_and_call_iterator (plugin, | ||
677 | stmt, | ||
678 | zone, | ||
679 | limit, | ||
680 | iter, | ||
681 | iter_cls); | ||
682 | } | ||
683 | |||
684 | |||
685 | /** | ||
686 | * Look for an existing PKEY delegation record for a given public key. | ||
687 | * Returns at most one result to the iterator. | ||
688 | * | ||
689 | * @param cls closure (internal context for the plugin) | ||
690 | * @param zone private key of the zone to look up in, never NULL | ||
691 | * @param value_zone public key of the target zone (value), never NULL | ||
692 | * @param iter function to call with the result | ||
693 | * @param iter_cls closure for @a iter | ||
694 | * @return #GNUNET_OK on success, #GNUNET_NO if there were no results, #GNUNET_SYSERR on error | ||
695 | */ | ||
696 | static int | ||
697 | namestore_sqlite_zone_to_name (void *cls, | ||
698 | const struct GNUNET_IDENTITY_PrivateKey *zone, | ||
699 | const struct | ||
700 | GNUNET_IDENTITY_PublicKey *value_zone, | ||
701 | GNUNET_NAMESTORE_RecordIterator iter, | ||
702 | void *iter_cls) | ||
703 | { | ||
704 | struct Plugin *plugin = cls; | ||
705 | struct GNUNET_SQ_QueryParam params[] = { | ||
706 | GNUNET_SQ_query_param_auto_from_type (zone), | ||
707 | GNUNET_SQ_query_param_auto_from_type (value_zone), | ||
708 | GNUNET_SQ_query_param_end | ||
709 | }; | ||
710 | |||
711 | if (GNUNET_OK != | ||
712 | GNUNET_SQ_bind (plugin->zone_to_name, | ||
713 | params)) | ||
714 | { | ||
715 | LOG_SQLITE (plugin, | ||
716 | GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, | ||
717 | "sqlite3_bind_XXXX"); | ||
718 | GNUNET_SQ_reset (plugin->dbh, | ||
719 | plugin->zone_to_name); | ||
720 | return GNUNET_SYSERR; | ||
721 | } | ||
722 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
723 | "Performing reverse lookup for `%s'\n", | ||
724 | GNUNET_GNSRECORD_z2s (value_zone)); | ||
725 | return get_records_and_call_iterator (plugin, | ||
726 | plugin->zone_to_name, | ||
727 | zone, | ||
728 | 1, | ||
729 | iter, | ||
730 | iter_cls); | ||
731 | } | ||
732 | |||
733 | |||
734 | /** | ||
735 | * Entry point for the plugin. | ||
736 | * | ||
737 | * @param cls the "struct GNUNET_NAMESTORE_PluginEnvironment*" | ||
738 | * @return NULL on error, otherwise the plugin context | ||
739 | */ | ||
740 | void * | ||
741 | libgnunet_plugin_namestore_sqlite_init (void *cls) | ||
742 | { | ||
743 | static struct Plugin plugin; | ||
744 | const struct GNUNET_CONFIGURATION_Handle *cfg = cls; | ||
745 | struct GNUNET_NAMESTORE_PluginFunctions *api; | ||
746 | |||
747 | if (NULL != plugin.cfg) | ||
748 | return NULL; /* can only initialize once! */ | ||
749 | memset (&plugin, | ||
750 | 0, | ||
751 | sizeof(struct Plugin)); | ||
752 | plugin.cfg = cfg; | ||
753 | if (GNUNET_OK != database_setup (&plugin)) | ||
754 | { | ||
755 | database_shutdown (&plugin); | ||
756 | return NULL; | ||
757 | } | ||
758 | api = GNUNET_new (struct GNUNET_NAMESTORE_PluginFunctions); | ||
759 | api->cls = &plugin; | ||
760 | api->store_records = &namestore_sqlite_store_records; | ||
761 | api->iterate_records = &namestore_sqlite_iterate_records; | ||
762 | api->zone_to_name = &namestore_sqlite_zone_to_name; | ||
763 | api->lookup_records = &namestore_sqlite_lookup_records; | ||
764 | LOG (GNUNET_ERROR_TYPE_INFO, | ||
765 | _ ("Sqlite database running\n")); | ||
766 | return api; | ||
767 | } | ||
768 | |||
769 | |||
770 | /** | ||
771 | * Exit point from the plugin. | ||
772 | * | ||
773 | * @param cls the plugin context (as returned by "init") | ||
774 | * @return always NULL | ||
775 | */ | ||
776 | void * | ||
777 | libgnunet_plugin_namestore_sqlite_done (void *cls) | ||
778 | { | ||
779 | struct GNUNET_NAMESTORE_PluginFunctions *api = cls; | ||
780 | struct Plugin *plugin = api->cls; | ||
781 | |||
782 | database_shutdown (plugin); | ||
783 | plugin->cfg = NULL; | ||
784 | GNUNET_free (api); | ||
785 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
786 | "sqlite plugin is finished\n"); | ||
787 | return NULL; | ||
788 | } | ||
789 | |||
790 | |||
791 | /* end of plugin_namestore_sqlite.c */ | ||
diff --git a/src/namestore/plugin_rest_namestore.c b/src/namestore/plugin_rest_namestore.c deleted file mode 100644 index ff5494dc7..000000000 --- a/src/namestore/plugin_rest_namestore.c +++ /dev/null | |||
@@ -1,1155 +0,0 @@ | |||
1 | /* | ||
2 | This file is part of GNUnet. | ||
3 | Copyright (C) 2012-2015 GNUnet e.V. | ||
4 | |||
5 | GNUnet is free software: you can redistribute it and/or modify it | ||
6 | under the terms of the GNU Affero General Public License as published | ||
7 | by the Free Software Foundation, either version 3 of the License, | ||
8 | or (at your option) any later version. | ||
9 | |||
10 | GNUnet is distributed in the hope that it will be useful, but | ||
11 | WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
13 | Affero General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU Affero General Public License | ||
16 | along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
17 | |||
18 | SPDX-License-Identifier: AGPL3.0-or-later | ||
19 | */ | ||
20 | /** | ||
21 | * @author Martin Schanzenbach | ||
22 | * @author Philippe Buschmann | ||
23 | * @file namestore/plugin_rest_namestore.c | ||
24 | * @brief GNUnet Namestore REST plugin | ||
25 | */ | ||
26 | |||
27 | #include "platform.h" | ||
28 | #include "gnunet_rest_plugin.h" | ||
29 | #include "gnunet_gns_service.h" | ||
30 | #include "gnunet_namestore_service.h" | ||
31 | #include "gnunet_identity_service.h" | ||
32 | #include "gnunet_rest_lib.h" | ||
33 | #include "gnunet_gnsrecord_json_lib.h" | ||
34 | #include "microhttpd.h" | ||
35 | #include <jansson.h> | ||
36 | |||
37 | /** | ||
38 | * Namestore Namespace | ||
39 | */ | ||
40 | #define GNUNET_REST_API_NS_NAMESTORE "/namestore" | ||
41 | |||
42 | /** | ||
43 | * Error message Unknown Error | ||
44 | */ | ||
45 | #define GNUNET_REST_NAMESTORE_ERROR_UNKNOWN "Unknown Error" | ||
46 | |||
47 | /** | ||
48 | * Error message No identity found | ||
49 | */ | ||
50 | #define GNUNET_REST_IDENTITY_NOT_FOUND "No identity found" | ||
51 | |||
52 | |||
53 | /** | ||
54 | * Error message Failed request | ||
55 | */ | ||
56 | #define GNUNET_REST_NAMESTORE_FAILED "Namestore action failed" | ||
57 | |||
58 | /** | ||
59 | * Error message invalid data | ||
60 | */ | ||
61 | #define GNUNET_REST_NAMESTORE_INVALID_DATA "Data invalid" | ||
62 | |||
63 | /** | ||
64 | * Error message No data | ||
65 | */ | ||
66 | #define GNUNET_REST_NAMESTORE_NO_DATA "No data" | ||
67 | |||
68 | /** | ||
69 | * State while collecting all egos | ||
70 | */ | ||
71 | #define ID_REST_STATE_INIT 0 | ||
72 | |||
73 | /** | ||
74 | * Done collecting egos | ||
75 | */ | ||
76 | #define ID_REST_STATE_POST_INIT 1 | ||
77 | /** | ||
78 | * The configuration handle | ||
79 | */ | ||
80 | const struct GNUNET_CONFIGURATION_Handle *cfg; | ||
81 | |||
82 | /** | ||
83 | * HTTP methods allows for this plugin | ||
84 | */ | ||
85 | static char *allow_methods; | ||
86 | |||
87 | /** | ||
88 | * Ego list | ||
89 | */ | ||
90 | static struct EgoEntry *ego_head; | ||
91 | |||
92 | /** | ||
93 | * Ego list | ||
94 | */ | ||
95 | static struct EgoEntry *ego_tail; | ||
96 | |||
97 | /** | ||
98 | * The processing state | ||
99 | */ | ||
100 | static int state; | ||
101 | |||
102 | /** | ||
103 | * Handle to NAMESTORE | ||
104 | */ | ||
105 | static struct GNUNET_NAMESTORE_Handle *ns_handle; | ||
106 | |||
107 | /** | ||
108 | * Handle to Identity service. | ||
109 | */ | ||
110 | static struct GNUNET_IDENTITY_Handle *identity_handle; | ||
111 | |||
112 | /** | ||
113 | * @brief struct returned by the initialization function of the plugin | ||
114 | */ | ||
115 | struct Plugin | ||
116 | { | ||
117 | const struct GNUNET_CONFIGURATION_Handle *cfg; | ||
118 | }; | ||
119 | |||
120 | /** | ||
121 | * The default namestore ego | ||
122 | */ | ||
123 | struct EgoEntry | ||
124 | { | ||
125 | /** | ||
126 | * DLL | ||
127 | */ | ||
128 | struct EgoEntry *next; | ||
129 | |||
130 | /** | ||
131 | * DLL | ||
132 | */ | ||
133 | struct EgoEntry *prev; | ||
134 | |||
135 | /** | ||
136 | * Ego Identifier | ||
137 | */ | ||
138 | char *identifier; | ||
139 | |||
140 | /** | ||
141 | * Public key string | ||
142 | */ | ||
143 | char *keystring; | ||
144 | |||
145 | /** | ||
146 | * The Ego | ||
147 | */ | ||
148 | struct GNUNET_IDENTITY_Ego *ego; | ||
149 | }; | ||
150 | |||
151 | |||
152 | enum UpdateStrategy | ||
153 | { | ||
154 | UPDATE_STRATEGY_REPLACE, | ||
155 | UPDATE_STRATEGY_APPEND | ||
156 | }; | ||
157 | |||
158 | /** | ||
159 | * The request handle | ||
160 | */ | ||
161 | struct RequestHandle | ||
162 | { | ||
163 | /** | ||
164 | * DLL | ||
165 | */ | ||
166 | struct RequestHandle *next; | ||
167 | |||
168 | /** | ||
169 | * DLL | ||
170 | */ | ||
171 | struct RequestHandle *prev; | ||
172 | |||
173 | /** | ||
174 | * Records to store | ||
175 | */ | ||
176 | char *record_name; | ||
177 | |||
178 | /** | ||
179 | * Record type filter | ||
180 | */ | ||
181 | uint32_t record_type; | ||
182 | |||
183 | /** | ||
184 | * How to update the record set | ||
185 | */ | ||
186 | enum UpdateStrategy update_strategy; | ||
187 | |||
188 | /** | ||
189 | * Records to store | ||
190 | */ | ||
191 | struct GNUNET_GNSRECORD_Data *rd; | ||
192 | |||
193 | /** | ||
194 | * Number of records in rd | ||
195 | */ | ||
196 | unsigned int rd_count; | ||
197 | |||
198 | /** | ||
199 | * NAMESTORE Operation | ||
200 | */ | ||
201 | struct GNUNET_NAMESTORE_QueueEntry *ns_qe; | ||
202 | |||
203 | /** | ||
204 | * Response object | ||
205 | */ | ||
206 | json_t *resp_object; | ||
207 | |||
208 | |||
209 | /** | ||
210 | * Handle to NAMESTORE it | ||
211 | */ | ||
212 | struct GNUNET_NAMESTORE_ZoneIterator *list_it; | ||
213 | |||
214 | /** | ||
215 | * Private key for the zone | ||
216 | */ | ||
217 | const struct GNUNET_IDENTITY_PrivateKey *zone_pkey; | ||
218 | |||
219 | /** | ||
220 | * IDENTITY Operation | ||
221 | */ | ||
222 | struct EgoEntry *ego_entry; | ||
223 | |||
224 | /** | ||
225 | * IDENTITY Operation | ||
226 | */ | ||
227 | struct GNUNET_IDENTITY_Operation *op; | ||
228 | |||
229 | /** | ||
230 | * Rest connection | ||
231 | */ | ||
232 | struct GNUNET_REST_RequestHandle *rest_handle; | ||
233 | |||
234 | /** | ||
235 | * Desired timeout for the lookup (default is no timeout). | ||
236 | */ | ||
237 | struct GNUNET_TIME_Relative timeout; | ||
238 | |||
239 | /** | ||
240 | * ID of a task associated with the resolution process. | ||
241 | */ | ||
242 | struct GNUNET_SCHEDULER_Task *timeout_task; | ||
243 | |||
244 | /** | ||
245 | * The plugin result processor | ||
246 | */ | ||
247 | GNUNET_REST_ResultProcessor proc; | ||
248 | |||
249 | /** | ||
250 | * The closure of the result processor | ||
251 | */ | ||
252 | void *proc_cls; | ||
253 | |||
254 | /** | ||
255 | * The url | ||
256 | */ | ||
257 | char *url; | ||
258 | |||
259 | /** | ||
260 | * Error response message | ||
261 | */ | ||
262 | char *emsg; | ||
263 | |||
264 | /** | ||
265 | * Response code | ||
266 | */ | ||
267 | int response_code; | ||
268 | }; | ||
269 | |||
270 | /** | ||
271 | * DLL | ||
272 | */ | ||
273 | static struct RequestHandle *requests_head; | ||
274 | |||
275 | /** | ||
276 | * DLL | ||
277 | */ | ||
278 | static struct RequestHandle *requests_tail; | ||
279 | |||
280 | |||
281 | /** | ||
282 | * Cleanup lookup handle | ||
283 | * @param handle Handle to clean up | ||
284 | */ | ||
285 | static void | ||
286 | cleanup_handle (void *cls) | ||
287 | { | ||
288 | struct RequestHandle *handle = cls; | ||
289 | |||
290 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Cleaning up\n"); | ||
291 | if (NULL != handle->timeout_task) | ||
292 | { | ||
293 | GNUNET_SCHEDULER_cancel (handle->timeout_task); | ||
294 | handle->timeout_task = NULL; | ||
295 | } | ||
296 | if (NULL != handle->record_name) | ||
297 | GNUNET_free (handle->record_name); | ||
298 | if (NULL != handle->url) | ||
299 | GNUNET_free (handle->url); | ||
300 | if (NULL != handle->emsg) | ||
301 | GNUNET_free (handle->emsg); | ||
302 | if (NULL != handle->rd) | ||
303 | { | ||
304 | for (int i = 0; i < handle->rd_count; i++) | ||
305 | { | ||
306 | if (NULL != handle->rd[i].data) | ||
307 | GNUNET_free_nz ((void *) handle->rd[i].data); | ||
308 | } | ||
309 | GNUNET_free (handle->rd); | ||
310 | } | ||
311 | if (NULL != handle->timeout_task) | ||
312 | GNUNET_SCHEDULER_cancel (handle->timeout_task); | ||
313 | if (NULL != handle->list_it) | ||
314 | GNUNET_NAMESTORE_zone_iteration_stop (handle->list_it); | ||
315 | if (NULL != handle->ns_qe) | ||
316 | GNUNET_NAMESTORE_cancel (handle->ns_qe); | ||
317 | |||
318 | if (NULL != handle->resp_object) | ||
319 | { | ||
320 | json_decref (handle->resp_object); | ||
321 | } | ||
322 | GNUNET_CONTAINER_DLL_remove (requests_head, | ||
323 | requests_tail, | ||
324 | handle); | ||
325 | GNUNET_free (handle); | ||
326 | } | ||
327 | |||
328 | |||
329 | /** | ||
330 | * Task run on errors. Reports an error and cleans up everything. | ||
331 | * | ||
332 | * @param cls the `struct RequestHandle` | ||
333 | */ | ||
334 | static void | ||
335 | do_error (void *cls) | ||
336 | { | ||
337 | struct RequestHandle *handle = cls; | ||
338 | struct MHD_Response *resp; | ||
339 | json_t *json_error = json_object (); | ||
340 | char *response; | ||
341 | |||
342 | if (NULL == handle->emsg) | ||
343 | handle->emsg = GNUNET_strdup (GNUNET_REST_NAMESTORE_ERROR_UNKNOWN); | ||
344 | |||
345 | json_object_set_new (json_error, "error", json_string (handle->emsg)); | ||
346 | |||
347 | if (0 == handle->response_code) | ||
348 | handle->response_code = MHD_HTTP_INTERNAL_SERVER_ERROR; | ||
349 | response = json_dumps (json_error, 0); | ||
350 | resp = GNUNET_REST_create_response (response); | ||
351 | MHD_add_response_header (resp, "Content-Type", "application/json"); | ||
352 | handle->proc (handle->proc_cls, resp, handle->response_code); | ||
353 | json_decref (json_error); | ||
354 | GNUNET_free (response); | ||
355 | cleanup_handle (handle); | ||
356 | } | ||
357 | |||
358 | |||
359 | /** | ||
360 | * Get EgoEntry from list with either a public key or a name | ||
361 | * If public key and name are not NULL, it returns the public key result first | ||
362 | * | ||
363 | * @param handle the RequestHandle | ||
364 | * @param pubkey the public key of an identity (only one can be NULL) | ||
365 | * @param name the name of an identity (only one can be NULL) | ||
366 | * @return EgoEntry or NULL if not found | ||
367 | */ | ||
368 | struct EgoEntry * | ||
369 | get_egoentry_namestore (struct RequestHandle *handle, char *name) | ||
370 | { | ||
371 | struct EgoEntry *ego_entry; | ||
372 | char *copy = GNUNET_strdup (name); | ||
373 | char *tmp; | ||
374 | |||
375 | if (NULL == name) | ||
376 | return NULL; | ||
377 | tmp = strtok (copy, "/"); | ||
378 | if (NULL == tmp) | ||
379 | return NULL; | ||
380 | for (ego_entry = ego_head; NULL != ego_entry; | ||
381 | ego_entry = ego_entry->next) | ||
382 | { | ||
383 | if (0 != strcasecmp (tmp, ego_entry->identifier)) | ||
384 | continue; | ||
385 | GNUNET_free (copy); | ||
386 | return ego_entry; | ||
387 | } | ||
388 | GNUNET_free (copy); | ||
389 | return NULL; | ||
390 | } | ||
391 | |||
392 | |||
393 | /** | ||
394 | * Does internal server error when iteration failed. | ||
395 | * | ||
396 | * @param cls the `struct RequestHandle` | ||
397 | */ | ||
398 | static void | ||
399 | namestore_iteration_error (void *cls) | ||
400 | { | ||
401 | struct RequestHandle *handle = cls; | ||
402 | |||
403 | handle->emsg = GNUNET_strdup (GNUNET_REST_NAMESTORE_FAILED); | ||
404 | GNUNET_SCHEDULER_add_now (&do_error, handle); | ||
405 | return; | ||
406 | } | ||
407 | |||
408 | |||
409 | /** | ||
410 | * Create finished callback | ||
411 | * | ||
412 | * @param cls the `struct RequestHandle` | ||
413 | * @param success the success indicating integer, GNUNET_OK on success | ||
414 | * @param emsg the error message (can be NULL) | ||
415 | */ | ||
416 | static void | ||
417 | create_finished (void *cls, int32_t success, const char *emsg) | ||
418 | { | ||
419 | struct RequestHandle *handle = cls; | ||
420 | struct MHD_Response *resp; | ||
421 | |||
422 | handle->ns_qe = NULL; | ||
423 | if (GNUNET_YES != success) | ||
424 | { | ||
425 | if (NULL != emsg) | ||
426 | { | ||
427 | handle->emsg = GNUNET_strdup (emsg); | ||
428 | GNUNET_SCHEDULER_add_now (&do_error, handle); | ||
429 | return; | ||
430 | } | ||
431 | handle->emsg = GNUNET_strdup ("Error storing records"); | ||
432 | GNUNET_SCHEDULER_add_now (&do_error, handle); | ||
433 | return; | ||
434 | } | ||
435 | resp = GNUNET_REST_create_response (NULL); | ||
436 | handle->proc (handle->proc_cls, resp, MHD_HTTP_NO_CONTENT); | ||
437 | GNUNET_SCHEDULER_add_now (&cleanup_handle, handle); | ||
438 | } | ||
439 | |||
440 | |||
441 | /** | ||
442 | * Delete finished callback | ||
443 | * | ||
444 | * @param cls the `struct RequestHandle` | ||
445 | * @param success the success indicating integer, GNUNET_OK on success | ||
446 | * @param emsg the error message (can be NULL) | ||
447 | */ | ||
448 | static void | ||
449 | del_finished (void *cls, int32_t success, const char *emsg) | ||
450 | { | ||
451 | struct RequestHandle *handle = cls; | ||
452 | |||
453 | handle->ns_qe = NULL; | ||
454 | if (GNUNET_NO == success) | ||
455 | { | ||
456 | handle->response_code = MHD_HTTP_NOT_FOUND; | ||
457 | handle->emsg = GNUNET_strdup ("No record found"); | ||
458 | GNUNET_SCHEDULER_add_now (&do_error, handle); | ||
459 | return; | ||
460 | } | ||
461 | if (GNUNET_SYSERR == success) | ||
462 | { | ||
463 | if (NULL != emsg) | ||
464 | { | ||
465 | handle->emsg = GNUNET_strdup (emsg); | ||
466 | GNUNET_SCHEDULER_add_now (&do_error, handle); | ||
467 | return; | ||
468 | } | ||
469 | handle->emsg = GNUNET_strdup ("Deleting record failed"); | ||
470 | GNUNET_SCHEDULER_add_now (&do_error, handle); | ||
471 | return; | ||
472 | } | ||
473 | handle->proc (handle->proc_cls, | ||
474 | GNUNET_REST_create_response (NULL), | ||
475 | MHD_HTTP_NO_CONTENT); | ||
476 | GNUNET_SCHEDULER_add_now (&cleanup_handle, handle); | ||
477 | } | ||
478 | |||
479 | |||
480 | /** | ||
481 | * Iteration over all results finished, build final | ||
482 | * response. | ||
483 | * | ||
484 | * @param cls the `struct RequestHandle` | ||
485 | */ | ||
486 | static void | ||
487 | namestore_list_finished (void *cls) | ||
488 | { | ||
489 | struct RequestHandle *handle = cls; | ||
490 | char *result_str; | ||
491 | struct MHD_Response *resp; | ||
492 | |||
493 | handle->list_it = NULL; | ||
494 | |||
495 | if (NULL == handle->resp_object) | ||
496 | handle->resp_object = json_array (); | ||
497 | |||
498 | result_str = json_dumps (handle->resp_object, 0); | ||
499 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Result %s\n", result_str); | ||
500 | resp = GNUNET_REST_create_response (result_str); | ||
501 | MHD_add_response_header (resp, "Content-Type", "application/json"); | ||
502 | handle->proc (handle->proc_cls, resp, MHD_HTTP_OK); | ||
503 | GNUNET_free (result_str); | ||
504 | GNUNET_SCHEDULER_add_now (&cleanup_handle, handle); | ||
505 | } | ||
506 | |||
507 | |||
508 | /** | ||
509 | * Create a response with requested records | ||
510 | * | ||
511 | * @param handle the RequestHandle | ||
512 | */ | ||
513 | static void | ||
514 | namestore_list_iteration (void *cls, | ||
515 | const struct GNUNET_IDENTITY_PrivateKey *zone_key, | ||
516 | const char *rname, | ||
517 | unsigned int rd_len, | ||
518 | const struct GNUNET_GNSRECORD_Data *rd) | ||
519 | { | ||
520 | struct RequestHandle *handle = cls; | ||
521 | struct GNUNET_GNSRECORD_Data rd_filtered[rd_len]; | ||
522 | json_t *record_obj; | ||
523 | int i = 0; | ||
524 | int j = 0; | ||
525 | |||
526 | if (NULL == handle->resp_object) | ||
527 | handle->resp_object = json_array (); | ||
528 | for (i = 0; i < rd_len; i++) | ||
529 | { | ||
530 | if ((GNUNET_GNSRECORD_TYPE_ANY != handle->record_type) && | ||
531 | (rd[i].record_type != handle->record_type)) | ||
532 | continue; /* Apply filter */ | ||
533 | rd_filtered[j] = rd[i]; | ||
534 | rd_filtered[j].data = rd[i].data; | ||
535 | j++; | ||
536 | } | ||
537 | /** Only add if not empty **/ | ||
538 | if (j > 0) | ||
539 | { | ||
540 | record_obj = GNUNET_GNSRECORD_JSON_from_gnsrecord (rname, | ||
541 | rd_filtered, | ||
542 | j); | ||
543 | json_array_append_new (handle->resp_object, record_obj); | ||
544 | } | ||
545 | GNUNET_NAMESTORE_zone_iterator_next (handle->list_it, 1); | ||
546 | } | ||
547 | |||
548 | |||
549 | /** | ||
550 | * Handle lookup error | ||
551 | * | ||
552 | * @param cls the request handle | ||
553 | */ | ||
554 | static void | ||
555 | ns_lookup_error_cb (void *cls) | ||
556 | { | ||
557 | struct RequestHandle *handle = cls; | ||
558 | |||
559 | handle->emsg = GNUNET_strdup (GNUNET_REST_NAMESTORE_FAILED); | ||
560 | GNUNET_SCHEDULER_add_now (&do_error, handle); | ||
561 | } | ||
562 | |||
563 | |||
564 | static void | ||
565 | ns_get_lookup_cb (void *cls, | ||
566 | const struct GNUNET_IDENTITY_PrivateKey *zone, | ||
567 | const char *label, | ||
568 | unsigned int rd_len, | ||
569 | const struct GNUNET_GNSRECORD_Data *rd) | ||
570 | { | ||
571 | struct RequestHandle *handle = cls; | ||
572 | struct GNUNET_GNSRECORD_Data rd_filtered[rd_len]; | ||
573 | json_t *record_obj; | ||
574 | int i = 0; | ||
575 | int j = 0; | ||
576 | |||
577 | handle->ns_qe = NULL; | ||
578 | if (NULL == handle->resp_object) | ||
579 | handle->resp_object = json_array (); | ||
580 | for (i = 0; i < rd_len; i++) | ||
581 | { | ||
582 | if ((GNUNET_GNSRECORD_TYPE_ANY != handle->record_type) && | ||
583 | (rd[i].record_type != handle->record_type)) | ||
584 | continue; /* Apply filter */ | ||
585 | rd_filtered[j] = rd[i]; | ||
586 | rd_filtered[j].data = rd[i].data; | ||
587 | j++; | ||
588 | } | ||
589 | /** Only add if not empty **/ | ||
590 | if (j > 0) | ||
591 | { | ||
592 | record_obj = GNUNET_GNSRECORD_JSON_from_gnsrecord (label, | ||
593 | rd_filtered, | ||
594 | j); | ||
595 | json_array_append_new (handle->resp_object, record_obj); | ||
596 | } | ||
597 | GNUNET_SCHEDULER_add_now (&namestore_list_finished, handle); | ||
598 | } | ||
599 | |||
600 | |||
601 | /** | ||
602 | * Handle namestore GET request | ||
603 | * | ||
604 | * @param con_handle the connection handle | ||
605 | * @param url the url | ||
606 | * @param cls the RequestHandle | ||
607 | */ | ||
608 | void | ||
609 | namestore_get (struct GNUNET_REST_RequestHandle *con_handle, | ||
610 | const char *url, | ||
611 | void *cls) | ||
612 | { | ||
613 | struct RequestHandle *handle = cls; | ||
614 | struct EgoEntry *ego_entry; | ||
615 | struct GNUNET_HashCode key; | ||
616 | char *egoname; | ||
617 | char *labelname; | ||
618 | char *typename; | ||
619 | |||
620 | egoname = NULL; | ||
621 | ego_entry = NULL; | ||
622 | |||
623 | // set zone to name if given | ||
624 | if (strlen (GNUNET_REST_API_NS_NAMESTORE) + 1 >= strlen (handle->url)) | ||
625 | { | ||
626 | handle->response_code = MHD_HTTP_NOT_FOUND; | ||
627 | handle->emsg = GNUNET_strdup (GNUNET_REST_IDENTITY_NOT_FOUND); | ||
628 | GNUNET_SCHEDULER_add_now (&do_error, handle); | ||
629 | return; | ||
630 | } | ||
631 | egoname = &handle->url[strlen (GNUNET_REST_API_NS_NAMESTORE) + 1]; | ||
632 | ego_entry = get_egoentry_namestore (handle, egoname); | ||
633 | if (NULL == ego_entry) | ||
634 | { | ||
635 | handle->response_code = MHD_HTTP_NOT_FOUND; | ||
636 | handle->emsg = GNUNET_strdup (GNUNET_REST_IDENTITY_NOT_FOUND); | ||
637 | GNUNET_SCHEDULER_add_now (&do_error, handle); | ||
638 | return; | ||
639 | } | ||
640 | handle->zone_pkey = GNUNET_IDENTITY_ego_get_private_key (ego_entry->ego); | ||
641 | |||
642 | GNUNET_CRYPTO_hash ("record_type", strlen ("record_type"), &key); | ||
643 | if (GNUNET_NO == | ||
644 | GNUNET_CONTAINER_multihashmap_contains (con_handle->url_param_map, &key)) | ||
645 | { | ||
646 | handle->record_type = GNUNET_GNSRECORD_TYPE_ANY; | ||
647 | } | ||
648 | else | ||
649 | { | ||
650 | typename = GNUNET_CONTAINER_multihashmap_get (con_handle->url_param_map, | ||
651 | &key); | ||
652 | handle->record_type = GNUNET_GNSRECORD_typename_to_number (typename); | ||
653 | } | ||
654 | labelname = &egoname[strlen (ego_entry->identifier)]; | ||
655 | // set zone to name if given | ||
656 | if (1 >= strlen (labelname)) | ||
657 | { | ||
658 | handle->list_it = | ||
659 | GNUNET_NAMESTORE_zone_iteration_start (ns_handle, | ||
660 | handle->zone_pkey, | ||
661 | &namestore_iteration_error, | ||
662 | handle, | ||
663 | &namestore_list_iteration, | ||
664 | handle, | ||
665 | &namestore_list_finished, | ||
666 | handle); | ||
667 | if (NULL == handle->list_it) | ||
668 | { | ||
669 | handle->emsg = GNUNET_strdup (GNUNET_REST_NAMESTORE_FAILED); | ||
670 | GNUNET_SCHEDULER_add_now (&do_error, handle); | ||
671 | return; | ||
672 | } | ||
673 | return; | ||
674 | } | ||
675 | handle->record_name = GNUNET_strdup (labelname + 1); | ||
676 | handle->ns_qe = GNUNET_NAMESTORE_records_lookup (ns_handle, | ||
677 | handle->zone_pkey, | ||
678 | handle->record_name, | ||
679 | &ns_lookup_error_cb, | ||
680 | handle, | ||
681 | &ns_get_lookup_cb, | ||
682 | handle); | ||
683 | if (NULL == handle->ns_qe) | ||
684 | { | ||
685 | handle->emsg = GNUNET_strdup (GNUNET_REST_NAMESTORE_FAILED); | ||
686 | GNUNET_SCHEDULER_add_now (&do_error, handle); | ||
687 | return; | ||
688 | } | ||
689 | } | ||
690 | |||
691 | |||
692 | static void | ||
693 | ns_lookup_cb (void *cls, | ||
694 | const struct GNUNET_IDENTITY_PrivateKey *zone, | ||
695 | const char *label, | ||
696 | unsigned int rd_count, | ||
697 | const struct GNUNET_GNSRECORD_Data *rd) | ||
698 | { | ||
699 | struct RequestHandle *handle = cls; | ||
700 | struct GNUNET_GNSRECORD_Data rd_new[rd_count + handle->rd_count]; | ||
701 | int i = 0; | ||
702 | int j = 0; | ||
703 | |||
704 | if (UPDATE_STRATEGY_APPEND == handle->update_strategy) | ||
705 | { | ||
706 | for (i = 0; i < rd_count; i++) | ||
707 | rd_new[i] = rd[i]; | ||
708 | } | ||
709 | for (j = 0; j < handle->rd_count; j++) | ||
710 | rd_new[i + j] = handle->rd[j]; | ||
711 | handle->ns_qe = GNUNET_NAMESTORE_records_store (ns_handle, | ||
712 | handle->zone_pkey, | ||
713 | handle->record_name, | ||
714 | i + j, | ||
715 | rd_new, | ||
716 | &create_finished, | ||
717 | handle); | ||
718 | if (NULL == handle->ns_qe) | ||
719 | { | ||
720 | handle->emsg = GNUNET_strdup (GNUNET_REST_NAMESTORE_FAILED); | ||
721 | GNUNET_SCHEDULER_add_now (&do_error, handle); | ||
722 | return; | ||
723 | } | ||
724 | } | ||
725 | |||
726 | |||
727 | /** | ||
728 | * Handle namestore POST/PUT request | ||
729 | * | ||
730 | * @param con_handle the connection handle | ||
731 | * @param url the url | ||
732 | * @param cls the RequestHandle | ||
733 | */ | ||
734 | void | ||
735 | namestore_add_or_update (struct GNUNET_REST_RequestHandle *con_handle, | ||
736 | const char *url, | ||
737 | void *cls) | ||
738 | { | ||
739 | struct RequestHandle *handle = cls; | ||
740 | struct EgoEntry *ego_entry; | ||
741 | char *egoname; | ||
742 | json_t *data_js; | ||
743 | json_error_t err; | ||
744 | |||
745 | char term_data[handle->rest_handle->data_size + 1]; | ||
746 | |||
747 | if (0 >= handle->rest_handle->data_size) | ||
748 | { | ||
749 | handle->response_code = MHD_HTTP_BAD_REQUEST; | ||
750 | handle->emsg = GNUNET_strdup (GNUNET_REST_NAMESTORE_NO_DATA); | ||
751 | GNUNET_SCHEDULER_add_now (&do_error, handle); | ||
752 | return; | ||
753 | } | ||
754 | term_data[handle->rest_handle->data_size] = '\0'; | ||
755 | GNUNET_memcpy (term_data, | ||
756 | handle->rest_handle->data, | ||
757 | handle->rest_handle->data_size); | ||
758 | data_js = json_loads (term_data, JSON_DECODE_ANY, &err); | ||
759 | struct GNUNET_JSON_Specification gnsspec[] = | ||
760 | { GNUNET_GNSRECORD_JSON_spec_gnsrecord (&handle->rd, &handle->rd_count, | ||
761 | &handle->record_name), | ||
762 | GNUNET_JSON_spec_end () }; | ||
763 | if (GNUNET_OK != GNUNET_JSON_parse (data_js, gnsspec, NULL, NULL)) | ||
764 | { | ||
765 | handle->emsg = GNUNET_strdup (GNUNET_REST_NAMESTORE_INVALID_DATA); | ||
766 | GNUNET_SCHEDULER_add_now (&do_error, handle); | ||
767 | json_decref (data_js); | ||
768 | return; | ||
769 | } | ||
770 | GNUNET_JSON_parse_free (gnsspec); | ||
771 | if (0 >= strlen (handle->record_name)) | ||
772 | { | ||
773 | handle->response_code = MHD_HTTP_BAD_REQUEST; | ||
774 | handle->emsg = GNUNET_strdup (GNUNET_REST_NAMESTORE_INVALID_DATA); | ||
775 | GNUNET_SCHEDULER_add_now (&do_error, handle); | ||
776 | json_decref (data_js); | ||
777 | return; | ||
778 | } | ||
779 | json_decref (data_js); | ||
780 | |||
781 | egoname = NULL; | ||
782 | ego_entry = NULL; | ||
783 | |||
784 | // set zone to name if given | ||
785 | if (strlen (GNUNET_REST_API_NS_NAMESTORE) + 1 >= strlen (handle->url)) | ||
786 | { | ||
787 | handle->response_code = MHD_HTTP_NOT_FOUND; | ||
788 | handle->emsg = GNUNET_strdup (GNUNET_REST_IDENTITY_NOT_FOUND); | ||
789 | GNUNET_SCHEDULER_add_now (&do_error, handle); | ||
790 | return; | ||
791 | } | ||
792 | egoname = &handle->url[strlen (GNUNET_REST_API_NS_NAMESTORE) + 1]; | ||
793 | ego_entry = get_egoentry_namestore (handle, egoname); | ||
794 | |||
795 | if (NULL == ego_entry) | ||
796 | { | ||
797 | handle->response_code = MHD_HTTP_NOT_FOUND; | ||
798 | handle->emsg = GNUNET_strdup (GNUNET_REST_IDENTITY_NOT_FOUND); | ||
799 | GNUNET_SCHEDULER_add_now (&do_error, handle); | ||
800 | return; | ||
801 | } | ||
802 | handle->zone_pkey = GNUNET_IDENTITY_ego_get_private_key (ego_entry->ego); | ||
803 | handle->ns_qe = GNUNET_NAMESTORE_records_lookup (ns_handle, | ||
804 | handle->zone_pkey, | ||
805 | handle->record_name, | ||
806 | &ns_lookup_error_cb, | ||
807 | handle, | ||
808 | &ns_lookup_cb, | ||
809 | handle); | ||
810 | if (NULL == handle->ns_qe) | ||
811 | { | ||
812 | handle->emsg = GNUNET_strdup (GNUNET_REST_NAMESTORE_FAILED); | ||
813 | GNUNET_SCHEDULER_add_now (&do_error, handle); | ||
814 | return; | ||
815 | } | ||
816 | } | ||
817 | |||
818 | |||
819 | /** | ||
820 | * Handle namestore PUT request | ||
821 | * | ||
822 | * @param con_handle the connection handle | ||
823 | * @param url the url | ||
824 | * @param cls the RequestHandle | ||
825 | */ | ||
826 | void | ||
827 | namestore_update (struct GNUNET_REST_RequestHandle *con_handle, | ||
828 | const char *url, | ||
829 | void *cls) | ||
830 | { | ||
831 | struct RequestHandle *handle = cls; | ||
832 | handle->update_strategy = UPDATE_STRATEGY_REPLACE; | ||
833 | namestore_add_or_update (con_handle, url, cls); | ||
834 | } | ||
835 | |||
836 | |||
837 | /** | ||
838 | * Handle namestore POST request | ||
839 | * | ||
840 | * @param con_handle the connection handle | ||
841 | * @param url the url | ||
842 | * @param cls the RequestHandle | ||
843 | */ | ||
844 | void | ||
845 | namestore_add (struct GNUNET_REST_RequestHandle *con_handle, | ||
846 | const char *url, | ||
847 | void *cls) | ||
848 | { | ||
849 | struct RequestHandle *handle = cls; | ||
850 | handle->update_strategy = UPDATE_STRATEGY_APPEND; | ||
851 | namestore_add_or_update (con_handle, url, cls); | ||
852 | } | ||
853 | |||
854 | |||
855 | /** | ||
856 | * Handle namestore DELETE request | ||
857 | * | ||
858 | * @param con_handle the connection handle | ||
859 | * @param url the url | ||
860 | * @param cls the RequestHandle | ||
861 | */ | ||
862 | void | ||
863 | namestore_delete (struct GNUNET_REST_RequestHandle *con_handle, | ||
864 | const char *url, | ||
865 | void *cls) | ||
866 | { | ||
867 | struct RequestHandle *handle = cls; | ||
868 | struct EgoEntry *ego_entry; | ||
869 | char *egoname; | ||
870 | char *labelname; | ||
871 | |||
872 | egoname = NULL; | ||
873 | ego_entry = NULL; | ||
874 | |||
875 | // set zone to name if given | ||
876 | if (strlen (GNUNET_REST_API_NS_NAMESTORE) + 1 >= strlen (handle->url)) | ||
877 | { | ||
878 | handle->response_code = MHD_HTTP_NOT_FOUND; | ||
879 | handle->emsg = GNUNET_strdup (GNUNET_REST_IDENTITY_NOT_FOUND); | ||
880 | GNUNET_SCHEDULER_add_now (&do_error, handle); | ||
881 | return; | ||
882 | } | ||
883 | egoname = &handle->url[strlen (GNUNET_REST_API_NS_NAMESTORE) + 1]; | ||
884 | ego_entry = get_egoentry_namestore (handle, egoname); | ||
885 | if (NULL == ego_entry) | ||
886 | { | ||
887 | handle->response_code = MHD_HTTP_NOT_FOUND; | ||
888 | handle->emsg = GNUNET_strdup (GNUNET_REST_IDENTITY_NOT_FOUND); | ||
889 | GNUNET_SCHEDULER_add_now (&do_error, handle); | ||
890 | return; | ||
891 | } | ||
892 | handle->zone_pkey = GNUNET_IDENTITY_ego_get_private_key (ego_entry->ego); | ||
893 | labelname = &egoname[strlen (ego_entry->identifier)]; | ||
894 | // set zone to name if given | ||
895 | if (1 >= strlen (labelname)) | ||
896 | { | ||
897 | /* label is only "/" */ | ||
898 | handle->response_code = MHD_HTTP_BAD_REQUEST; | ||
899 | handle->emsg = GNUNET_strdup ("Label missing"); | ||
900 | GNUNET_SCHEDULER_add_now (&do_error, handle); | ||
901 | } | ||
902 | |||
903 | handle->record_name = GNUNET_strdup (labelname + 1); | ||
904 | handle->ns_qe = GNUNET_NAMESTORE_records_store (ns_handle, | ||
905 | handle->zone_pkey, | ||
906 | handle->record_name, | ||
907 | 0, | ||
908 | NULL, | ||
909 | &del_finished, | ||
910 | handle); | ||
911 | if (NULL == handle->ns_qe) | ||
912 | { | ||
913 | handle->emsg = GNUNET_strdup (GNUNET_REST_NAMESTORE_FAILED); | ||
914 | GNUNET_SCHEDULER_add_now (&do_error, handle); | ||
915 | return; | ||
916 | } | ||
917 | } | ||
918 | |||
919 | |||
920 | /** | ||
921 | * Respond to OPTIONS request | ||
922 | * | ||
923 | * @param con_handle the connection handle | ||
924 | * @param url the url | ||
925 | * @param cls the RequestHandle | ||
926 | */ | ||
927 | static void | ||
928 | options_cont (struct GNUNET_REST_RequestHandle *con_handle, | ||
929 | const char *url, | ||
930 | void *cls) | ||
931 | { | ||
932 | struct MHD_Response *resp; | ||
933 | struct RequestHandle *handle = cls; | ||
934 | |||
935 | // independent of path return all options | ||
936 | resp = GNUNET_REST_create_response (NULL); | ||
937 | MHD_add_response_header (resp, "Access-Control-Allow-Methods", allow_methods); | ||
938 | handle->proc (handle->proc_cls, resp, MHD_HTTP_OK); | ||
939 | GNUNET_SCHEDULER_add_now (&cleanup_handle, handle); | ||
940 | return; | ||
941 | } | ||
942 | |||
943 | |||
944 | static void | ||
945 | list_ego (void *cls, | ||
946 | struct GNUNET_IDENTITY_Ego *ego, | ||
947 | void **ctx, | ||
948 | const char *identifier) | ||
949 | { | ||
950 | struct EgoEntry *ego_entry; | ||
951 | struct GNUNET_IDENTITY_PublicKey pk; | ||
952 | |||
953 | if ((NULL == ego) && (ID_REST_STATE_INIT == state)) | ||
954 | { | ||
955 | state = ID_REST_STATE_POST_INIT; | ||
956 | return; | ||
957 | } | ||
958 | if (NULL == ego) | ||
959 | { | ||
960 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, | ||
961 | "Called with NULL ego\n"); | ||
962 | return; | ||
963 | } | ||
964 | if (ID_REST_STATE_INIT == state) | ||
965 | { | ||
966 | ego_entry = GNUNET_new (struct EgoEntry); | ||
967 | GNUNET_IDENTITY_ego_get_public_key (ego, &pk); | ||
968 | ego_entry->keystring = GNUNET_IDENTITY_public_key_to_string (&pk); | ||
969 | ego_entry->ego = ego; | ||
970 | ego_entry->identifier = GNUNET_strdup (identifier); | ||
971 | GNUNET_CONTAINER_DLL_insert_tail (ego_head, | ||
972 | ego_tail, | ||
973 | ego_entry); | ||
974 | } | ||
975 | /* Ego renamed or added */ | ||
976 | if (identifier != NULL) | ||
977 | { | ||
978 | for (ego_entry = ego_head; NULL != ego_entry; | ||
979 | ego_entry = ego_entry->next) | ||
980 | { | ||
981 | if (ego_entry->ego == ego) | ||
982 | { | ||
983 | /* Rename */ | ||
984 | GNUNET_free (ego_entry->identifier); | ||
985 | ego_entry->identifier = GNUNET_strdup (identifier); | ||
986 | break; | ||
987 | } | ||
988 | } | ||
989 | if (NULL == ego_entry) | ||
990 | { | ||
991 | /* Add */ | ||
992 | ego_entry = GNUNET_new (struct EgoEntry); | ||
993 | GNUNET_IDENTITY_ego_get_public_key (ego, &pk); | ||
994 | ego_entry->keystring = GNUNET_IDENTITY_public_key_to_string (&pk); | ||
995 | ego_entry->ego = ego; | ||
996 | ego_entry->identifier = GNUNET_strdup (identifier); | ||
997 | GNUNET_CONTAINER_DLL_insert_tail (ego_head, | ||
998 | ego_tail, | ||
999 | ego_entry); | ||
1000 | } | ||
1001 | } | ||
1002 | else | ||
1003 | { | ||
1004 | /* Delete */ | ||
1005 | for (ego_entry = ego_head; NULL != ego_entry; | ||
1006 | ego_entry = ego_entry->next) | ||
1007 | { | ||
1008 | if (ego_entry->ego == ego) | ||
1009 | break; | ||
1010 | } | ||
1011 | if (NULL == ego_entry) | ||
1012 | return; /* Not found */ | ||
1013 | |||
1014 | GNUNET_CONTAINER_DLL_remove (ego_head, | ||
1015 | ego_tail, | ||
1016 | ego_entry); | ||
1017 | GNUNET_free (ego_entry->identifier); | ||
1018 | GNUNET_free (ego_entry->keystring); | ||
1019 | GNUNET_free (ego_entry); | ||
1020 | return; | ||
1021 | } | ||
1022 | |||
1023 | } | ||
1024 | |||
1025 | |||
1026 | /** | ||
1027 | * Function processing the REST call | ||
1028 | * | ||
1029 | * @param method HTTP method | ||
1030 | * @param url URL of the HTTP request | ||
1031 | * @param data body of the HTTP request (optional) | ||
1032 | * @param data_size length of the body | ||
1033 | * @param proc callback function for the result | ||
1034 | * @param proc_cls closure for callback function | ||
1035 | * @return GNUNET_OK if request accepted | ||
1036 | */ | ||
1037 | static enum GNUNET_GenericReturnValue | ||
1038 | rest_process_request (struct GNUNET_REST_RequestHandle *rest_handle, | ||
1039 | GNUNET_REST_ResultProcessor proc, | ||
1040 | void *proc_cls) | ||
1041 | { | ||
1042 | struct RequestHandle *handle = GNUNET_new (struct RequestHandle); | ||
1043 | struct GNUNET_REST_RequestHandlerError err; | ||
1044 | static const struct GNUNET_REST_RequestHandler handlers[] = | ||
1045 | { { MHD_HTTP_METHOD_GET, GNUNET_REST_API_NS_NAMESTORE, &namestore_get }, | ||
1046 | { MHD_HTTP_METHOD_POST, GNUNET_REST_API_NS_NAMESTORE, &namestore_add }, | ||
1047 | { MHD_HTTP_METHOD_PUT, GNUNET_REST_API_NS_NAMESTORE, &namestore_update }, | ||
1048 | { MHD_HTTP_METHOD_DELETE, GNUNET_REST_API_NS_NAMESTORE, &namestore_delete }, | ||
1049 | { MHD_HTTP_METHOD_OPTIONS, GNUNET_REST_API_NS_NAMESTORE, &options_cont }, | ||
1050 | GNUNET_REST_HANDLER_END }; | ||
1051 | |||
1052 | handle->response_code = 0; | ||
1053 | handle->timeout = GNUNET_TIME_UNIT_FOREVER_REL; | ||
1054 | handle->proc_cls = proc_cls; | ||
1055 | handle->proc = proc; | ||
1056 | handle->rest_handle = rest_handle; | ||
1057 | handle->zone_pkey = NULL; | ||
1058 | handle->timeout_task = | ||
1059 | GNUNET_SCHEDULER_add_delayed (handle->timeout, &do_error, handle); | ||
1060 | handle->url = GNUNET_strdup (rest_handle->url); | ||
1061 | if (handle->url[strlen (handle->url) - 1] == '/') | ||
1062 | handle->url[strlen (handle->url) - 1] = '\0'; | ||
1063 | GNUNET_CONTAINER_DLL_insert (requests_head, | ||
1064 | requests_tail, | ||
1065 | handle); | ||
1066 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Connecting...\n"); | ||
1067 | if (GNUNET_NO == | ||
1068 | GNUNET_REST_handle_request (handle->rest_handle, handlers, &err, handle)) | ||
1069 | { | ||
1070 | cleanup_handle (handle); | ||
1071 | return GNUNET_NO; | ||
1072 | } | ||
1073 | |||
1074 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Connected\n"); | ||
1075 | return GNUNET_YES; | ||
1076 | } | ||
1077 | |||
1078 | |||
1079 | /** | ||
1080 | * Entry point for the plugin. | ||
1081 | * | ||
1082 | * @param cls Config info | ||
1083 | * @return NULL on error, otherwise the plugin context | ||
1084 | */ | ||
1085 | void * | ||
1086 | libgnunet_plugin_rest_namestore_init (void *cls) | ||
1087 | { | ||
1088 | static struct Plugin plugin; | ||
1089 | struct GNUNET_REST_Plugin *api; | ||
1090 | |||
1091 | cfg = cls; | ||
1092 | if (NULL != plugin.cfg) | ||
1093 | return NULL; /* can only initialize once! */ | ||
1094 | memset (&plugin, 0, sizeof(struct Plugin)); | ||
1095 | plugin.cfg = cfg; | ||
1096 | api = GNUNET_new (struct GNUNET_REST_Plugin); | ||
1097 | api->cls = &plugin; | ||
1098 | api->name = GNUNET_REST_API_NS_NAMESTORE; | ||
1099 | api->process_request = &rest_process_request; | ||
1100 | state = ID_REST_STATE_INIT; | ||
1101 | GNUNET_asprintf (&allow_methods, | ||
1102 | "%s, %s, %s, %s, %s", | ||
1103 | MHD_HTTP_METHOD_GET, | ||
1104 | MHD_HTTP_METHOD_POST, | ||
1105 | MHD_HTTP_METHOD_PUT, | ||
1106 | MHD_HTTP_METHOD_DELETE, | ||
1107 | MHD_HTTP_METHOD_OPTIONS); | ||
1108 | ns_handle = GNUNET_NAMESTORE_connect (cfg); | ||
1109 | identity_handle = GNUNET_IDENTITY_connect (cfg, &list_ego, NULL); | ||
1110 | |||
1111 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, _ ("Namestore REST API initialized\n")); | ||
1112 | return api; | ||
1113 | } | ||
1114 | |||
1115 | |||
1116 | /** | ||
1117 | * Exit point from the plugin. | ||
1118 | * | ||
1119 | * @param cls the plugin context (as returned by "init") | ||
1120 | * @return always NULL | ||
1121 | */ | ||
1122 | void * | ||
1123 | libgnunet_plugin_rest_namestore_done (void *cls) | ||
1124 | { | ||
1125 | struct GNUNET_REST_Plugin *api = cls; | ||
1126 | struct Plugin *plugin = api->cls; | ||
1127 | struct RequestHandle *request; | ||
1128 | struct EgoEntry *ego_entry; | ||
1129 | struct EgoEntry *ego_tmp; | ||
1130 | |||
1131 | plugin->cfg = NULL; | ||
1132 | while (NULL != (request = requests_head)) | ||
1133 | do_error (request); | ||
1134 | if (NULL != identity_handle) | ||
1135 | GNUNET_IDENTITY_disconnect (identity_handle); | ||
1136 | if (NULL != ns_handle) | ||
1137 | GNUNET_NAMESTORE_disconnect (ns_handle); | ||
1138 | |||
1139 | for (ego_entry = ego_head; NULL != ego_entry;) | ||
1140 | { | ||
1141 | ego_tmp = ego_entry; | ||
1142 | ego_entry = ego_entry->next; | ||
1143 | GNUNET_free (ego_tmp->identifier); | ||
1144 | GNUNET_free (ego_tmp->keystring); | ||
1145 | GNUNET_free (ego_tmp); | ||
1146 | } | ||
1147 | |||
1148 | GNUNET_free (allow_methods); | ||
1149 | GNUNET_free (api); | ||
1150 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Namestore REST plugin is finished\n"); | ||
1151 | return NULL; | ||
1152 | } | ||
1153 | |||
1154 | |||
1155 | /* end of plugin_rest_namestore.c */ | ||
diff --git a/src/namestore/test_common.c b/src/namestore/test_common.c deleted file mode 100644 index 58afb0a32..000000000 --- a/src/namestore/test_common.c +++ /dev/null | |||
@@ -1,80 +0,0 @@ | |||
1 | /* | ||
2 | This file is part of GNUnet. | ||
3 | Copyright (C) 2019 GNUnet e.V. | ||
4 | |||
5 | GNUnet is free software: you can redistribute it and/or modify it | ||
6 | under the terms of the GNU Affero General Public License as published | ||
7 | by the Free Software Foundation, either version 3 of the License, | ||
8 | or (at your option) any later version. | ||
9 | |||
10 | GNUnet is distributed in the hope that it will be useful, but | ||
11 | WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
13 | Affero General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU Affero General Public License | ||
16 | along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
17 | |||
18 | SPDX-License-Identifier: AGPL3.0-or-later | ||
19 | */ | ||
20 | /** | ||
21 | * @file namestore/test_common.c | ||
22 | * @brief common functions for testcase setup | ||
23 | */ | ||
24 | |||
25 | /** | ||
26 | * test if we can load the plugin @a name. | ||
27 | */ | ||
28 | static int | ||
29 | TNC_test_plugin (const char *cfg_name) | ||
30 | { | ||
31 | char *database; | ||
32 | char *db_lib_name; | ||
33 | struct GNUNET_NAMESTORE_PluginFunctions *db; | ||
34 | struct GNUNET_CONFIGURATION_Handle *cfg; | ||
35 | |||
36 | cfg = GNUNET_CONFIGURATION_create (); | ||
37 | if (GNUNET_OK != GNUNET_CONFIGURATION_load (cfg, cfg_name)) | ||
38 | { | ||
39 | GNUNET_break (0); | ||
40 | GNUNET_CONFIGURATION_destroy (cfg); | ||
41 | return GNUNET_SYSERR; | ||
42 | } | ||
43 | if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_string (cfg, | ||
44 | "namestore", | ||
45 | "database", | ||
46 | &database)) | ||
47 | { | ||
48 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "No database backend configured\n"); | ||
49 | GNUNET_CONFIGURATION_destroy (cfg); | ||
50 | return GNUNET_SYSERR; | ||
51 | } | ||
52 | GNUNET_asprintf (&db_lib_name, "libgnunet_plugin_namestore_%s", database); | ||
53 | GNUNET_free (database); | ||
54 | db = GNUNET_PLUGIN_load (db_lib_name, (void *) cfg); | ||
55 | if (NULL != db) | ||
56 | GNUNET_break (NULL == GNUNET_PLUGIN_unload (db_lib_name, db)); | ||
57 | GNUNET_free (db_lib_name); | ||
58 | GNUNET_CONFIGURATION_destroy (cfg); | ||
59 | if (NULL == db) | ||
60 | return GNUNET_NO; | ||
61 | return GNUNET_YES; | ||
62 | } | ||
63 | |||
64 | |||
65 | /** | ||
66 | * General setup logic for starting the tests. Obtains the @a | ||
67 | * plugin_name and initializes the @a cfg_name. | ||
68 | */ | ||
69 | #define SETUP_CFG(plugin_name, cfg_name) \ | ||
70 | do \ | ||
71 | { \ | ||
72 | plugin_name = GNUNET_TESTING_get_testname_from_underscore (argv[0]); \ | ||
73 | GNUNET_asprintf (&cfg_name, "test_namestore_api_%s.conf", plugin_name); \ | ||
74 | if (! TNC_test_plugin (cfg_name)) \ | ||
75 | { \ | ||
76 | GNUNET_free (cfg_name); \ | ||
77 | return 77; \ | ||
78 | } \ | ||
79 | GNUNET_DISK_purge_cfg_dir (cfg_name, "GNUNET_TEST_HOME"); \ | ||
80 | } while (0) | ||
diff --git a/src/namestore/test_hostkey b/src/namestore/test_hostkey deleted file mode 100644 index e69de29bb..000000000 --- a/src/namestore/test_hostkey +++ /dev/null | |||
diff --git a/src/namestore/test_namestore_api.conf b/src/namestore/test_namestore_api.conf deleted file mode 100644 index 3e75c2ded..000000000 --- a/src/namestore/test_namestore_api.conf +++ /dev/null | |||
@@ -1,22 +0,0 @@ | |||
1 | @INLINE@ ../../contrib/conf/gnunet/no_forcestart.conf | ||
2 | @INLINE@ ../../contrib/conf/gnunet/no_autostart_above_core.conf | ||
3 | |||
4 | [PATHS] | ||
5 | GNUNET_TEST_HOME = $GNUNET_TMP/test-gnunet-namestore/ | ||
6 | |||
7 | [namestore] | ||
8 | DATABASE = sqlite | ||
9 | START_ON_DEMAND = YES | ||
10 | |||
11 | [namecache] | ||
12 | DATABASE = sqlite | ||
13 | START_ON_DEMAND = YES | ||
14 | |||
15 | [identity] | ||
16 | START_ON_DEMAND = YES | ||
17 | |||
18 | [nse] | ||
19 | WORKBITS = 0 | ||
20 | |||
21 | [transport] | ||
22 | PLUGINS = | ||
diff --git a/src/namestore/test_namestore_api_flat.conf b/src/namestore/test_namestore_api_flat.conf deleted file mode 100644 index 8460d143c..000000000 --- a/src/namestore/test_namestore_api_flat.conf +++ /dev/null | |||
@@ -1,7 +0,0 @@ | |||
1 | @INLINE@ test_namestore_api.conf | ||
2 | |||
3 | [namestore] | ||
4 | DATABASE = flat | ||
5 | |||
6 | [namestore-heap] | ||
7 | FILENAME = $GNUNET_TEST_HOME/namestore/flat.db | ||
diff --git a/src/namestore/test_namestore_api_lookup_nick.c b/src/namestore/test_namestore_api_lookup_nick.c deleted file mode 100644 index 6ce969c9b..000000000 --- a/src/namestore/test_namestore_api_lookup_nick.c +++ /dev/null | |||
@@ -1,347 +0,0 @@ | |||
1 | /* | ||
2 | This file is part of GNUnet. | ||
3 | Copyright (C) 2012 GNUnet e.V. | ||
4 | |||
5 | GNUnet is free software: you can redistribute it and/or modify it | ||
6 | under the terms of the GNU Affero General Public License as published | ||
7 | by the Free Software Foundation, either version 3 of the License, | ||
8 | or (at your option) any later version. | ||
9 | |||
10 | GNUnet is distributed in the hope that it will be useful, but | ||
11 | WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
13 | Affero General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU Affero General Public License | ||
16 | along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
17 | |||
18 | SPDX-License-Identifier: AGPL3.0-or-later | ||
19 | */ | ||
20 | /** | ||
21 | * @file namestore/test_namestore_api_lookup_nick.c | ||
22 | * @brief testcase for namestore_api.c: NICK records | ||
23 | */ | ||
24 | #include "platform.h" | ||
25 | #include "gnunet_namestore_service.h" | ||
26 | #include "gnunet_gns_service.h" | ||
27 | #include "gnunet_testing_lib.h" | ||
28 | #include "gnunet_dnsparser_lib.h" | ||
29 | |||
30 | #define TEST_RECORD_TYPE GNUNET_DNSPARSER_TYPE_TXT | ||
31 | |||
32 | #define TEST_RECORD_DATALEN 123 | ||
33 | |||
34 | #define TEST_NICK "gnunettestnick" | ||
35 | |||
36 | #define TEST_RECORD_DATA 'a' | ||
37 | |||
38 | #define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 10) | ||
39 | |||
40 | static struct GNUNET_NAMESTORE_Handle *nsh; | ||
41 | |||
42 | static struct GNUNET_SCHEDULER_Task *endbadly_task; | ||
43 | |||
44 | static struct GNUNET_IDENTITY_PrivateKey privkey; | ||
45 | |||
46 | static struct GNUNET_IDENTITY_PublicKey pubkey; | ||
47 | |||
48 | static int res; | ||
49 | |||
50 | static struct GNUNET_GNSRECORD_Data rd_orig; | ||
51 | |||
52 | static struct GNUNET_NAMESTORE_QueueEntry *nsqe; | ||
53 | |||
54 | // static const char * name = "dummy.dummy.gnunet"; | ||
55 | static const char *name = "d"; | ||
56 | |||
57 | static char *record_data; | ||
58 | |||
59 | static void | ||
60 | cleanup () | ||
61 | { | ||
62 | GNUNET_free (record_data); | ||
63 | if (NULL != nsh) | ||
64 | { | ||
65 | GNUNET_NAMESTORE_disconnect (nsh); | ||
66 | nsh = NULL; | ||
67 | } | ||
68 | GNUNET_SCHEDULER_shutdown (); | ||
69 | } | ||
70 | |||
71 | |||
72 | /** | ||
73 | * Re-establish the connection to the service. | ||
74 | * | ||
75 | * @param cls handle to use to re-connect. | ||
76 | * @param tc scheduler context | ||
77 | */ | ||
78 | static void | ||
79 | endbadly (void *cls) | ||
80 | { | ||
81 | if (NULL != nsqe) | ||
82 | { | ||
83 | GNUNET_NAMESTORE_cancel (nsqe); | ||
84 | nsqe = NULL; | ||
85 | } | ||
86 | cleanup (); | ||
87 | res = 1; | ||
88 | } | ||
89 | |||
90 | |||
91 | static void | ||
92 | end (void *cls) | ||
93 | { | ||
94 | cleanup (); | ||
95 | res = 0; | ||
96 | } | ||
97 | |||
98 | |||
99 | static void | ||
100 | lookup_it (void *cls, | ||
101 | const struct GNUNET_IDENTITY_PrivateKey *zone, | ||
102 | const char *label, | ||
103 | unsigned int rd_count, | ||
104 | const struct GNUNET_GNSRECORD_Data *rd) | ||
105 | { | ||
106 | nsqe = NULL; | ||
107 | int c; | ||
108 | int found_record = GNUNET_NO; | ||
109 | int found_nick = GNUNET_NO; | ||
110 | |||
111 | if (0 != GNUNET_memcmp (&privkey, zone)) | ||
112 | { | ||
113 | GNUNET_break (0); | ||
114 | GNUNET_SCHEDULER_cancel (endbadly_task); | ||
115 | endbadly_task = GNUNET_SCHEDULER_add_now (&endbadly, NULL); | ||
116 | return; | ||
117 | } | ||
118 | |||
119 | if (NULL == label) | ||
120 | { | ||
121 | GNUNET_break (0); | ||
122 | GNUNET_SCHEDULER_cancel (endbadly_task); | ||
123 | endbadly_task = GNUNET_SCHEDULER_add_now (&endbadly, NULL); | ||
124 | return; | ||
125 | } | ||
126 | |||
127 | if (0 != strcmp (label, name)) | ||
128 | { | ||
129 | GNUNET_break (0); | ||
130 | GNUNET_SCHEDULER_cancel (endbadly_task); | ||
131 | endbadly_task = GNUNET_SCHEDULER_add_now (&endbadly, NULL); | ||
132 | return; | ||
133 | } | ||
134 | |||
135 | if (2 != rd_count) | ||
136 | { | ||
137 | GNUNET_break (0); | ||
138 | GNUNET_SCHEDULER_cancel (endbadly_task); | ||
139 | endbadly_task = GNUNET_SCHEDULER_add_now (&endbadly, NULL); | ||
140 | return; | ||
141 | } | ||
142 | |||
143 | for (c = 0; c < rd_count; c++) | ||
144 | { | ||
145 | if (GNUNET_GNSRECORD_TYPE_NICK == rd[c].record_type) | ||
146 | { | ||
147 | if (rd[c].data_size != strlen (TEST_NICK) + 1) | ||
148 | { | ||
149 | GNUNET_break (0); | ||
150 | GNUNET_SCHEDULER_cancel (endbadly_task); | ||
151 | endbadly_task = GNUNET_SCHEDULER_add_now (&endbadly, NULL); | ||
152 | return; | ||
153 | } | ||
154 | if (0 != (rd[c].flags & GNUNET_GNSRECORD_RF_PRIVATE)) | ||
155 | { | ||
156 | GNUNET_break (0); | ||
157 | GNUNET_SCHEDULER_cancel (endbadly_task); | ||
158 | endbadly_task = GNUNET_SCHEDULER_add_now (&endbadly, NULL); | ||
159 | return; | ||
160 | } | ||
161 | if (0 != strcmp (rd[c].data, TEST_NICK)) | ||
162 | { | ||
163 | GNUNET_SCHEDULER_cancel (endbadly_task); | ||
164 | endbadly_task = GNUNET_SCHEDULER_add_now (&endbadly, NULL); | ||
165 | return; | ||
166 | } | ||
167 | found_nick = GNUNET_YES; | ||
168 | } | ||
169 | else | ||
170 | { | ||
171 | if (rd[c].record_type != TEST_RECORD_TYPE) | ||
172 | { | ||
173 | GNUNET_break (0); | ||
174 | GNUNET_SCHEDULER_cancel (endbadly_task); | ||
175 | endbadly_task = GNUNET_SCHEDULER_add_now (&endbadly, NULL); | ||
176 | return; | ||
177 | } | ||
178 | if (rd[c].data_size != TEST_RECORD_DATALEN) | ||
179 | { | ||
180 | GNUNET_break (0); | ||
181 | GNUNET_SCHEDULER_cancel (endbadly_task); | ||
182 | endbadly_task = GNUNET_SCHEDULER_add_now (&endbadly, NULL); | ||
183 | return; | ||
184 | } | ||
185 | if (0 != memcmp (rd[c].data, rd_orig.data, TEST_RECORD_DATALEN)) | ||
186 | { | ||
187 | GNUNET_break (0); | ||
188 | GNUNET_SCHEDULER_cancel (endbadly_task); | ||
189 | endbadly_task = GNUNET_SCHEDULER_add_now (&endbadly, NULL); | ||
190 | return; | ||
191 | } | ||
192 | if (rd[c].flags != rd->flags) | ||
193 | { | ||
194 | GNUNET_break (0); | ||
195 | GNUNET_SCHEDULER_cancel (endbadly_task); | ||
196 | endbadly_task = GNUNET_SCHEDULER_add_now (&endbadly, NULL); | ||
197 | return; | ||
198 | } | ||
199 | found_record = GNUNET_YES; | ||
200 | } | ||
201 | } | ||
202 | |||
203 | /* Done */ | ||
204 | if ((GNUNET_YES == found_nick) && (GNUNET_YES == found_record)) | ||
205 | { | ||
206 | GNUNET_SCHEDULER_cancel (endbadly_task); | ||
207 | endbadly_task = NULL; | ||
208 | GNUNET_SCHEDULER_add_now (&end, NULL); | ||
209 | } | ||
210 | else | ||
211 | { | ||
212 | GNUNET_break (0); | ||
213 | GNUNET_SCHEDULER_cancel (endbadly_task); | ||
214 | endbadly_task = NULL; | ||
215 | GNUNET_SCHEDULER_add_now (&endbadly, NULL); | ||
216 | } | ||
217 | } | ||
218 | |||
219 | |||
220 | static void | ||
221 | fail_cb (void *cls) | ||
222 | { | ||
223 | GNUNET_assert (0); | ||
224 | } | ||
225 | |||
226 | |||
227 | static void | ||
228 | put_cont (void *cls, int32_t success, const char *emsg) | ||
229 | { | ||
230 | const char *name = cls; | ||
231 | |||
232 | nsqe = NULL; | ||
233 | GNUNET_assert (NULL != cls); | ||
234 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
235 | "Name store added record for `%s': %s\n", | ||
236 | name, | ||
237 | (success == GNUNET_OK) ? "SUCCESS" : "FAIL"); | ||
238 | |||
239 | if (GNUNET_OK != success) | ||
240 | { | ||
241 | GNUNET_SCHEDULER_cancel (endbadly_task); | ||
242 | endbadly_task = GNUNET_SCHEDULER_add_now (&endbadly, NULL); | ||
243 | return; | ||
244 | } | ||
245 | /* Lookup */ | ||
246 | nsqe = GNUNET_NAMESTORE_records_lookup (nsh, | ||
247 | &privkey, | ||
248 | name, | ||
249 | &fail_cb, | ||
250 | NULL, | ||
251 | &lookup_it, | ||
252 | NULL); | ||
253 | } | ||
254 | |||
255 | |||
256 | static void | ||
257 | nick_cont (void *cls, int32_t success, const char *emsg) | ||
258 | { | ||
259 | const char *name = cls; | ||
260 | |||
261 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
262 | "Nick added : %s\n", | ||
263 | (success == GNUNET_OK) ? "SUCCESS" : "FAIL"); | ||
264 | |||
265 | rd_orig.expiration_time = GNUNET_TIME_absolute_get ().abs_value_us; | ||
266 | rd_orig.record_type = TEST_RECORD_TYPE; | ||
267 | rd_orig.data_size = TEST_RECORD_DATALEN; | ||
268 | record_data = GNUNET_malloc (TEST_RECORD_DATALEN); | ||
269 | rd_orig.data = record_data; | ||
270 | rd_orig.flags = 0; | ||
271 | memset ((char *) rd_orig.data, 'a', TEST_RECORD_DATALEN); | ||
272 | |||
273 | nsqe = GNUNET_NAMESTORE_records_store (nsh, &privkey, | ||
274 | name, | ||
275 | 1, | ||
276 | &rd_orig, | ||
277 | &put_cont, (void *) name); | ||
278 | } | ||
279 | |||
280 | |||
281 | static void | ||
282 | run (void *cls, | ||
283 | const struct GNUNET_CONFIGURATION_Handle *cfg, | ||
284 | struct GNUNET_TESTING_Peer *peer) | ||
285 | { | ||
286 | struct GNUNET_GNSRECORD_Data rd; | ||
287 | |||
288 | endbadly_task = GNUNET_SCHEDULER_add_delayed (TIMEOUT, | ||
289 | &endbadly, | ||
290 | NULL); | ||
291 | privkey.type = htonl (GNUNET_GNSRECORD_TYPE_PKEY); | ||
292 | GNUNET_CRYPTO_ecdsa_key_create (&privkey.ecdsa_key); | ||
293 | GNUNET_IDENTITY_key_get_public (&privkey, | ||
294 | &pubkey); | ||
295 | |||
296 | nsh = GNUNET_NAMESTORE_connect (cfg); | ||
297 | GNUNET_break (NULL != nsh); | ||
298 | |||
299 | memset (&rd, 0, sizeof(rd)); | ||
300 | rd.data = TEST_NICK; | ||
301 | rd.data_size = strlen (TEST_NICK) + 1; | ||
302 | rd.record_type = GNUNET_GNSRECORD_TYPE_NICK; | ||
303 | rd.expiration_time = GNUNET_TIME_UNIT_FOREVER_ABS.abs_value_us; | ||
304 | rd.flags |= GNUNET_GNSRECORD_RF_PRIVATE; | ||
305 | nsqe = GNUNET_NAMESTORE_records_store (nsh, | ||
306 | &privkey, | ||
307 | GNUNET_GNS_EMPTY_LABEL_AT, | ||
308 | 1, | ||
309 | &rd, | ||
310 | &nick_cont, | ||
311 | (void *) name); | ||
312 | |||
313 | if (NULL == nsqe) | ||
314 | { | ||
315 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
316 | _ ("Namestore cannot store no block\n")); | ||
317 | } | ||
318 | } | ||
319 | |||
320 | |||
321 | #include "test_common.c" | ||
322 | |||
323 | |||
324 | int | ||
325 | main (int argc, char *argv[]) | ||
326 | { | ||
327 | const char *plugin_name; | ||
328 | char *cfg_name; | ||
329 | |||
330 | SETUP_CFG (plugin_name, cfg_name); | ||
331 | res = 1; | ||
332 | if (0 != | ||
333 | GNUNET_TESTING_peer_run ("test-namestore-api-lookup-nick", | ||
334 | cfg_name, | ||
335 | &run, | ||
336 | NULL)) | ||
337 | { | ||
338 | res = 1; | ||
339 | } | ||
340 | GNUNET_DISK_purge_cfg_dir (cfg_name, | ||
341 | "GNUNET_TEST_HOME"); | ||
342 | GNUNET_free (cfg_name); | ||
343 | return res; | ||
344 | } | ||
345 | |||
346 | |||
347 | /* end of test_namestore_api_store.c */ | ||
diff --git a/src/namestore/test_namestore_api_lookup_private.c b/src/namestore/test_namestore_api_lookup_private.c deleted file mode 100644 index 67cf54582..000000000 --- a/src/namestore/test_namestore_api_lookup_private.c +++ /dev/null | |||
@@ -1,246 +0,0 @@ | |||
1 | /* | ||
2 | This file is part of GNUnet. | ||
3 | Copyright (C) 2012 GNUnet e.V. | ||
4 | |||
5 | GNUnet is free software: you can redistribute it and/or modify it | ||
6 | under the terms of the GNU Affero General Public License as published | ||
7 | by the Free Software Foundation, either version 3 of the License, | ||
8 | or (at your option) any later version. | ||
9 | |||
10 | GNUnet is distributed in the hope that it will be useful, but | ||
11 | WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
13 | Affero General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU Affero General Public License | ||
16 | along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
17 | |||
18 | SPDX-License-Identifier: AGPL3.0-or-later | ||
19 | */ | ||
20 | /** | ||
21 | * @file namestore/test_namestore_api_store.c | ||
22 | * @brief testcase for namestore_api.c: store a record | ||
23 | */ | ||
24 | #include "platform.h" | ||
25 | #include "gnunet_namestore_service.h" | ||
26 | #include "gnunet_testing_lib.h" | ||
27 | #include "gnunet_dnsparser_lib.h" | ||
28 | |||
29 | #define TEST_RECORD_TYPE GNUNET_DNSPARSER_TYPE_TXT | ||
30 | |||
31 | #define TEST_RECORD_DATALEN 123 | ||
32 | |||
33 | #define TEST_RECORD_DATA 'a' | ||
34 | |||
35 | #define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 5) | ||
36 | |||
37 | static struct GNUNET_NAMESTORE_Handle *nsh; | ||
38 | |||
39 | static struct GNUNET_SCHEDULER_Task *endbadly_task; | ||
40 | |||
41 | static struct GNUNET_IDENTITY_PrivateKey privkey; | ||
42 | |||
43 | static struct GNUNET_IDENTITY_PublicKey pubkey; | ||
44 | |||
45 | static int res; | ||
46 | |||
47 | static struct GNUNET_NAMESTORE_QueueEntry *nsqe; | ||
48 | |||
49 | // static const char * name = "dummy.dummy.gnunet"; | ||
50 | static const char *name = "d"; | ||
51 | |||
52 | |||
53 | static void | ||
54 | cleanup () | ||
55 | { | ||
56 | if (NULL != nsh) | ||
57 | { | ||
58 | GNUNET_NAMESTORE_disconnect (nsh); | ||
59 | nsh = NULL; | ||
60 | } | ||
61 | GNUNET_SCHEDULER_shutdown (); | ||
62 | } | ||
63 | |||
64 | |||
65 | /** | ||
66 | * Re-establish the connection to the service. | ||
67 | * | ||
68 | * @param cls handle to use to re-connect. | ||
69 | */ | ||
70 | static void | ||
71 | endbadly (void *cls) | ||
72 | { | ||
73 | endbadly_task = NULL; | ||
74 | if (NULL != nsqe) | ||
75 | { | ||
76 | GNUNET_NAMESTORE_cancel (nsqe); | ||
77 | nsqe = NULL; | ||
78 | } | ||
79 | cleanup (); | ||
80 | res = 1; | ||
81 | } | ||
82 | |||
83 | |||
84 | static void | ||
85 | end (void *cls) | ||
86 | { | ||
87 | cleanup (); | ||
88 | res = 0; | ||
89 | } | ||
90 | |||
91 | |||
92 | static void | ||
93 | lookup_it (void *cls, | ||
94 | const struct GNUNET_IDENTITY_PrivateKey *zone, | ||
95 | const char *label, | ||
96 | unsigned int rd_count, | ||
97 | const struct GNUNET_GNSRECORD_Data *rd) | ||
98 | { | ||
99 | nsqe = NULL; | ||
100 | |||
101 | if (0 != GNUNET_memcmp (&privkey, | ||
102 | zone)) | ||
103 | { | ||
104 | GNUNET_break (0); | ||
105 | GNUNET_SCHEDULER_cancel (endbadly_task); | ||
106 | endbadly_task = GNUNET_SCHEDULER_add_now (&endbadly, NULL); | ||
107 | return; | ||
108 | } | ||
109 | |||
110 | |||
111 | if (NULL == label) | ||
112 | { | ||
113 | GNUNET_break (0); | ||
114 | GNUNET_SCHEDULER_cancel (endbadly_task); | ||
115 | endbadly_task = GNUNET_SCHEDULER_add_now (&endbadly, NULL); | ||
116 | return; | ||
117 | } | ||
118 | |||
119 | if (0 != strcmp (label, name)) | ||
120 | { | ||
121 | GNUNET_break (0); | ||
122 | GNUNET_SCHEDULER_cancel (endbadly_task); | ||
123 | endbadly_task = GNUNET_SCHEDULER_add_now (&endbadly, NULL); | ||
124 | return; | ||
125 | } | ||
126 | |||
127 | if (1 != rd_count) | ||
128 | { | ||
129 | GNUNET_break (0); | ||
130 | GNUNET_SCHEDULER_cancel (endbadly_task); | ||
131 | endbadly_task = GNUNET_SCHEDULER_add_now (&endbadly, NULL); | ||
132 | return; | ||
133 | } | ||
134 | |||
135 | /* Done */ | ||
136 | GNUNET_SCHEDULER_cancel (endbadly_task); | ||
137 | endbadly_task = NULL; | ||
138 | GNUNET_SCHEDULER_add_now (&end, NULL); | ||
139 | } | ||
140 | |||
141 | |||
142 | static void | ||
143 | fail_cb (void *cls) | ||
144 | { | ||
145 | GNUNET_assert (0); | ||
146 | } | ||
147 | |||
148 | |||
149 | static void | ||
150 | put_cont (void *cls, | ||
151 | int32_t success, | ||
152 | const char *emsg) | ||
153 | { | ||
154 | const char *name = cls; | ||
155 | |||
156 | nsqe = NULL; | ||
157 | GNUNET_assert (NULL != cls); | ||
158 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
159 | "Name store added record for `%s': %s\n", | ||
160 | name, | ||
161 | (success == GNUNET_OK) ? "SUCCESS" : "FAIL"); | ||
162 | |||
163 | if (GNUNET_OK != success) | ||
164 | { | ||
165 | GNUNET_SCHEDULER_cancel (endbadly_task); | ||
166 | endbadly_task = GNUNET_SCHEDULER_add_now (&endbadly, NULL); | ||
167 | return; | ||
168 | } | ||
169 | /* Lookup */ | ||
170 | nsqe = GNUNET_NAMESTORE_records_lookup (nsh, | ||
171 | &privkey, | ||
172 | name, | ||
173 | &fail_cb, | ||
174 | NULL, | ||
175 | &lookup_it, | ||
176 | NULL); | ||
177 | } | ||
178 | |||
179 | |||
180 | static void | ||
181 | run (void *cls, | ||
182 | const struct GNUNET_CONFIGURATION_Handle *cfg, | ||
183 | struct GNUNET_TESTING_Peer *peer) | ||
184 | { | ||
185 | struct GNUNET_GNSRECORD_Data rd; | ||
186 | |||
187 | endbadly_task = GNUNET_SCHEDULER_add_delayed (TIMEOUT, | ||
188 | &endbadly, | ||
189 | NULL); | ||
190 | privkey.type = htonl (GNUNET_GNSRECORD_TYPE_PKEY); | ||
191 | GNUNET_CRYPTO_ecdsa_key_create (&privkey.ecdsa_key); | ||
192 | GNUNET_IDENTITY_key_get_public (&privkey, &pubkey); | ||
193 | |||
194 | rd.expiration_time = GNUNET_TIME_absolute_get ().abs_value_us; | ||
195 | rd.record_type = TEST_RECORD_TYPE; | ||
196 | rd.data_size = TEST_RECORD_DATALEN; | ||
197 | rd.data = GNUNET_malloc (TEST_RECORD_DATALEN); | ||
198 | rd.flags = 0; | ||
199 | memset ((char *) rd.data, 'a', TEST_RECORD_DATALEN); | ||
200 | |||
201 | nsh = GNUNET_NAMESTORE_connect (cfg); | ||
202 | GNUNET_break (NULL != nsh); | ||
203 | nsqe = GNUNET_NAMESTORE_records_store (nsh, | ||
204 | &privkey, | ||
205 | name, | ||
206 | 1, | ||
207 | &rd, | ||
208 | &put_cont, | ||
209 | (void *) name); | ||
210 | if (NULL == nsqe) | ||
211 | { | ||
212 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
213 | _ ("Namestore cannot store no block\n")); | ||
214 | } | ||
215 | |||
216 | GNUNET_free_nz ((void *) rd.data); | ||
217 | } | ||
218 | |||
219 | |||
220 | #include "test_common.c" | ||
221 | |||
222 | |||
223 | int | ||
224 | main (int argc, char *argv[]) | ||
225 | { | ||
226 | const char *plugin_name; | ||
227 | char *cfg_name; | ||
228 | |||
229 | SETUP_CFG (plugin_name, cfg_name); | ||
230 | res = 1; | ||
231 | if (0 != | ||
232 | GNUNET_TESTING_peer_run ("test-namestore-api-lookup-private", | ||
233 | cfg_name, | ||
234 | &run, | ||
235 | NULL)) | ||
236 | { | ||
237 | res = 1; | ||
238 | } | ||
239 | GNUNET_DISK_purge_cfg_dir (cfg_name, | ||
240 | "GNUNET_TEST_HOME"); | ||
241 | GNUNET_free (cfg_name); | ||
242 | return res; | ||
243 | } | ||
244 | |||
245 | |||
246 | /* end of test_namestore_api_lookup_private.c */ | ||
diff --git a/src/namestore/test_namestore_api_lookup_public.c b/src/namestore/test_namestore_api_lookup_public.c deleted file mode 100644 index 5e3e7bbd8..000000000 --- a/src/namestore/test_namestore_api_lookup_public.c +++ /dev/null | |||
@@ -1,255 +0,0 @@ | |||
1 | /* | ||
2 | This file is part of GNUnet. | ||
3 | Copyright (C) 2012 GNUnet e.V. | ||
4 | |||
5 | GNUnet is free software: you can redistribute it and/or modify it | ||
6 | under the terms of the GNU Affero General Public License as published | ||
7 | by the Free Software Foundation, either version 3 of the License, | ||
8 | or (at your option) any later version. | ||
9 | |||
10 | GNUnet is distributed in the hope that it will be useful, but | ||
11 | WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
13 | Affero General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU Affero General Public License | ||
16 | along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
17 | |||
18 | SPDX-License-Identifier: AGPL3.0-or-later | ||
19 | */ | ||
20 | /** | ||
21 | * @file namestore/test_namestore_api.c | ||
22 | * @brief testcase for namestore_api.c: store a record and perform a lookup | ||
23 | */ | ||
24 | #include "platform.h" | ||
25 | #include "gnunet_namecache_service.h" | ||
26 | #include "gnunet_namestore_service.h" | ||
27 | #include "gnunet_testing_lib.h" | ||
28 | #include "gnunet_dnsparser_lib.h" | ||
29 | |||
30 | #define TEST_RECORD_TYPE GNUNET_DNSPARSER_TYPE_TXT | ||
31 | |||
32 | #define TEST_RECORD_DATALEN 123 | ||
33 | |||
34 | #define TEST_RECORD_DATA 'a' | ||
35 | |||
36 | #define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 100) | ||
37 | |||
38 | |||
39 | static struct GNUNET_NAMESTORE_Handle *nsh; | ||
40 | |||
41 | static struct GNUNET_NAMECACHE_Handle *nch; | ||
42 | |||
43 | static struct GNUNET_SCHEDULER_Task *endbadly_task; | ||
44 | |||
45 | static struct GNUNET_IDENTITY_PrivateKey privkey; | ||
46 | |||
47 | static struct GNUNET_IDENTITY_PublicKey pubkey; | ||
48 | |||
49 | static int res; | ||
50 | |||
51 | static struct GNUNET_NAMESTORE_QueueEntry *nsqe; | ||
52 | |||
53 | static struct GNUNET_NAMECACHE_QueueEntry *ncqe; | ||
54 | |||
55 | |||
56 | static void | ||
57 | cleanup () | ||
58 | { | ||
59 | if (NULL != nsh) | ||
60 | { | ||
61 | GNUNET_NAMESTORE_disconnect (nsh); | ||
62 | nsh = NULL; | ||
63 | } | ||
64 | if (NULL != nch) | ||
65 | { | ||
66 | GNUNET_NAMECACHE_disconnect (nch); | ||
67 | nch = NULL; | ||
68 | } | ||
69 | GNUNET_SCHEDULER_shutdown (); | ||
70 | } | ||
71 | |||
72 | |||
73 | /** | ||
74 | * Re-establish the connection to the service. | ||
75 | * | ||
76 | * @param cls handle to use to re-connect. | ||
77 | */ | ||
78 | static void | ||
79 | endbadly (void *cls) | ||
80 | { | ||
81 | if (NULL != nsqe) | ||
82 | { | ||
83 | GNUNET_NAMESTORE_cancel (nsqe); | ||
84 | nsqe = NULL; | ||
85 | } | ||
86 | if (NULL != ncqe) | ||
87 | { | ||
88 | GNUNET_NAMECACHE_cancel (ncqe); | ||
89 | ncqe = NULL; | ||
90 | } | ||
91 | cleanup (); | ||
92 | res = 1; | ||
93 | } | ||
94 | |||
95 | |||
96 | static void | ||
97 | end (void *cls) | ||
98 | { | ||
99 | cleanup (); | ||
100 | res = 0; | ||
101 | } | ||
102 | |||
103 | |||
104 | static void | ||
105 | rd_decrypt_cb (void *cls, | ||
106 | unsigned int rd_count, | ||
107 | const struct GNUNET_GNSRECORD_Data *rd) | ||
108 | { | ||
109 | char rd_cmp_data[TEST_RECORD_DATALEN]; | ||
110 | |||
111 | GNUNET_assert (1 == rd_count); | ||
112 | GNUNET_assert (NULL != rd); | ||
113 | |||
114 | memset (rd_cmp_data, 'a', TEST_RECORD_DATALEN); | ||
115 | |||
116 | GNUNET_assert (TEST_RECORD_TYPE == rd[0].record_type); | ||
117 | GNUNET_assert (TEST_RECORD_DATALEN == rd[0].data_size); | ||
118 | GNUNET_assert (0 == memcmp (&rd_cmp_data, rd[0].data, TEST_RECORD_DATALEN)); | ||
119 | |||
120 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
121 | "Block was decrypted successfully \n"); | ||
122 | |||
123 | GNUNET_SCHEDULER_add_now (&end, NULL); | ||
124 | } | ||
125 | |||
126 | |||
127 | static void | ||
128 | name_lookup_proc (void *cls, | ||
129 | const struct GNUNET_GNSRECORD_Block *block) | ||
130 | { | ||
131 | const char *name = cls; | ||
132 | |||
133 | ncqe = NULL; | ||
134 | GNUNET_assert (NULL != cls); | ||
135 | |||
136 | if (endbadly_task != NULL) | ||
137 | { | ||
138 | GNUNET_SCHEDULER_cancel (endbadly_task); | ||
139 | endbadly_task = NULL; | ||
140 | } | ||
141 | |||
142 | if (NULL == block) | ||
143 | { | ||
144 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
145 | _ ("Namestore returned no block\n")); | ||
146 | if (endbadly_task != NULL) | ||
147 | GNUNET_SCHEDULER_cancel (endbadly_task); | ||
148 | endbadly_task = GNUNET_SCHEDULER_add_now (&endbadly, NULL); | ||
149 | return; | ||
150 | } | ||
151 | |||
152 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
153 | "Namestore returned block, decrypting \n"); | ||
154 | GNUNET_assert (GNUNET_OK == GNUNET_GNSRECORD_block_decrypt (block, | ||
155 | &pubkey, name, | ||
156 | &rd_decrypt_cb, | ||
157 | (void *) name)); | ||
158 | } | ||
159 | |||
160 | |||
161 | static void | ||
162 | put_cont (void *cls, int32_t success, const char *emsg) | ||
163 | { | ||
164 | const char *name = cls; | ||
165 | struct GNUNET_HashCode derived_hash; | ||
166 | struct GNUNET_IDENTITY_PublicKey pubkey; | ||
167 | |||
168 | nsqe = NULL; | ||
169 | GNUNET_assert (NULL != cls); | ||
170 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
171 | "Name store added record for `%s': %s\n", | ||
172 | name, | ||
173 | (success == GNUNET_OK) ? "SUCCESS" : "FAIL"); | ||
174 | |||
175 | /* Create derived hash */ | ||
176 | GNUNET_IDENTITY_key_get_public (&privkey, | ||
177 | &pubkey); | ||
178 | GNUNET_GNSRECORD_query_from_public_key (&pubkey, name, &derived_hash); | ||
179 | |||
180 | ncqe = GNUNET_NAMECACHE_lookup_block (nch, &derived_hash, | ||
181 | &name_lookup_proc, (void *) name); | ||
182 | } | ||
183 | |||
184 | |||
185 | static void | ||
186 | run (void *cls, | ||
187 | const struct GNUNET_CONFIGURATION_Handle *cfg, | ||
188 | struct GNUNET_TESTING_Peer *peer) | ||
189 | { | ||
190 | struct GNUNET_GNSRECORD_Data rd; | ||
191 | const char *name = "dummy.dummy.gnunet"; | ||
192 | |||
193 | endbadly_task = GNUNET_SCHEDULER_add_delayed (TIMEOUT, | ||
194 | &endbadly, | ||
195 | NULL); | ||
196 | privkey.type = htonl (GNUNET_GNSRECORD_TYPE_PKEY); | ||
197 | GNUNET_CRYPTO_ecdsa_key_create (&privkey.ecdsa_key); | ||
198 | GNUNET_IDENTITY_key_get_public (&privkey, | ||
199 | &pubkey); | ||
200 | |||
201 | rd.expiration_time = GNUNET_TIME_absolute_get ().abs_value_us + 1000000000; | ||
202 | rd.record_type = TEST_RECORD_TYPE; | ||
203 | rd.data_size = TEST_RECORD_DATALEN; | ||
204 | rd.data = GNUNET_malloc (TEST_RECORD_DATALEN); | ||
205 | rd.flags = 0; | ||
206 | memset ((char *) rd.data, 'a', TEST_RECORD_DATALEN); | ||
207 | |||
208 | nsh = GNUNET_NAMESTORE_connect (cfg); | ||
209 | nch = GNUNET_NAMECACHE_connect (cfg); | ||
210 | GNUNET_break (NULL != nsh); | ||
211 | GNUNET_break (NULL != nch); | ||
212 | nsqe = GNUNET_NAMESTORE_records_store (nsh, | ||
213 | &privkey, | ||
214 | name, | ||
215 | 1, | ||
216 | &rd, | ||
217 | &put_cont, | ||
218 | (void *) name); | ||
219 | if (NULL == nsqe) | ||
220 | { | ||
221 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
222 | _ ("Namestore cannot store no block\n")); | ||
223 | } | ||
224 | |||
225 | GNUNET_free_nz ((void *) rd.data); | ||
226 | } | ||
227 | |||
228 | |||
229 | #include "test_common.c" | ||
230 | |||
231 | |||
232 | int | ||
233 | main (int argc, char *argv[]) | ||
234 | { | ||
235 | const char *plugin_name; | ||
236 | char *cfg_name; | ||
237 | |||
238 | SETUP_CFG (plugin_name, cfg_name); | ||
239 | res = 1; | ||
240 | if (0 != | ||
241 | GNUNET_TESTING_peer_run ("test-namestore-api", | ||
242 | cfg_name, | ||
243 | &run, | ||
244 | NULL)) | ||
245 | { | ||
246 | res = 1; | ||
247 | } | ||
248 | GNUNET_DISK_purge_cfg_dir (cfg_name, | ||
249 | "GNUNET_TEST_HOME"); | ||
250 | GNUNET_free (cfg_name); | ||
251 | return res; | ||
252 | } | ||
253 | |||
254 | |||
255 | /* end of test_namestore_api_lookup_public.c */ | ||
diff --git a/src/namestore/test_namestore_api_lookup_shadow.c b/src/namestore/test_namestore_api_lookup_shadow.c deleted file mode 100644 index 79fa4c9c6..000000000 --- a/src/namestore/test_namestore_api_lookup_shadow.c +++ /dev/null | |||
@@ -1,288 +0,0 @@ | |||
1 | /* | ||
2 | This file is part of GNUnet. | ||
3 | Copyright (C) 2012 GNUnet e.V. | ||
4 | |||
5 | GNUnet is free software: you can redistribute it and/or modify it | ||
6 | under the terms of the GNU Affero General Public License as published | ||
7 | by the Free Software Foundation, either version 3 of the License, | ||
8 | or (at your option) any later version. | ||
9 | |||
10 | GNUnet is distributed in the hope that it will be useful, but | ||
11 | WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
13 | Affero General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU Affero General Public License | ||
16 | along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
17 | |||
18 | SPDX-License-Identifier: AGPL3.0-or-later | ||
19 | */ | ||
20 | /** | ||
21 | * @file namestore/test_namestore_api_lookup_shadow.c | ||
22 | * @brief testcase for namestore_api.c: store a shadow record and perform a lookup | ||
23 | * test passes if test returns the record but without the shadow flag since no | ||
24 | * other valid record is available | ||
25 | */ | ||
26 | #include "platform.h" | ||
27 | #include "gnunet_namecache_service.h" | ||
28 | #include "gnunet_namestore_service.h" | ||
29 | #include "gnunet_testing_lib.h" | ||
30 | #include "gnunet_dnsparser_lib.h" | ||
31 | |||
32 | #define TEST_RECORD_TYPE GNUNET_DNSPARSER_TYPE_TXT | ||
33 | |||
34 | #define TEST_RECORD_DATALEN 123 | ||
35 | |||
36 | #define TEST_RECORD_DATA 'a' | ||
37 | |||
38 | #define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 100) | ||
39 | |||
40 | |||
41 | static struct GNUNET_NAMESTORE_Handle *nsh; | ||
42 | |||
43 | static struct GNUNET_NAMECACHE_Handle *nch; | ||
44 | |||
45 | static struct GNUNET_SCHEDULER_Task *endbadly_task; | ||
46 | |||
47 | static struct GNUNET_IDENTITY_PrivateKey privkey; | ||
48 | |||
49 | static struct GNUNET_IDENTITY_PublicKey pubkey; | ||
50 | |||
51 | static int res; | ||
52 | |||
53 | static struct GNUNET_NAMESTORE_QueueEntry *nsqe; | ||
54 | |||
55 | static struct GNUNET_NAMECACHE_QueueEntry *ncqe; | ||
56 | |||
57 | |||
58 | static void | ||
59 | cleanup () | ||
60 | { | ||
61 | if (NULL != nsh) | ||
62 | { | ||
63 | GNUNET_NAMESTORE_disconnect (nsh); | ||
64 | nsh = NULL; | ||
65 | } | ||
66 | if (NULL != nch) | ||
67 | { | ||
68 | GNUNET_NAMECACHE_disconnect (nch); | ||
69 | nch = NULL; | ||
70 | } | ||
71 | GNUNET_SCHEDULER_shutdown (); | ||
72 | } | ||
73 | |||
74 | |||
75 | /** | ||
76 | * Re-establish the connection to the service. | ||
77 | * | ||
78 | * @param cls handle to use to re-connect. | ||
79 | */ | ||
80 | static void | ||
81 | endbadly (void *cls) | ||
82 | { | ||
83 | if (NULL != nsqe) | ||
84 | { | ||
85 | GNUNET_NAMESTORE_cancel (nsqe); | ||
86 | nsqe = NULL; | ||
87 | } | ||
88 | if (NULL != ncqe) | ||
89 | { | ||
90 | GNUNET_NAMECACHE_cancel (ncqe); | ||
91 | ncqe = NULL; | ||
92 | } | ||
93 | cleanup (); | ||
94 | res = 1; | ||
95 | } | ||
96 | |||
97 | |||
98 | static void | ||
99 | end (void *cls) | ||
100 | { | ||
101 | cleanup (); | ||
102 | res = 0; | ||
103 | } | ||
104 | |||
105 | |||
106 | static void | ||
107 | rd_decrypt_cb (void *cls, | ||
108 | unsigned int rd_count, | ||
109 | const struct GNUNET_GNSRECORD_Data *rd) | ||
110 | { | ||
111 | char rd_cmp_data[TEST_RECORD_DATALEN]; | ||
112 | |||
113 | if (1 != rd_count) | ||
114 | { | ||
115 | GNUNET_SCHEDULER_add_now (&endbadly, NULL); | ||
116 | GNUNET_break (0); | ||
117 | return; | ||
118 | } | ||
119 | if (NULL == rd) | ||
120 | { | ||
121 | GNUNET_SCHEDULER_add_now (&endbadly, NULL); | ||
122 | GNUNET_break (0); | ||
123 | return; | ||
124 | } | ||
125 | memset (rd_cmp_data, 'a', TEST_RECORD_DATALEN); | ||
126 | |||
127 | if (TEST_RECORD_TYPE != rd[0].record_type) | ||
128 | { | ||
129 | GNUNET_SCHEDULER_add_now (&endbadly, NULL); | ||
130 | GNUNET_break (0); | ||
131 | return; | ||
132 | } | ||
133 | if (TEST_RECORD_DATALEN != rd[0].data_size) | ||
134 | { | ||
135 | GNUNET_SCHEDULER_add_now (&endbadly, NULL); | ||
136 | GNUNET_break (0); | ||
137 | return; | ||
138 | } | ||
139 | if (0 != memcmp (&rd_cmp_data, rd[0].data, TEST_RECORD_DATALEN)) | ||
140 | { | ||
141 | GNUNET_SCHEDULER_add_now (&endbadly, NULL); | ||
142 | GNUNET_break (0); | ||
143 | return; | ||
144 | } | ||
145 | if (0 != (GNUNET_GNSRECORD_RF_SHADOW_RECORD & rd[0].flags)) | ||
146 | { | ||
147 | GNUNET_SCHEDULER_add_now (&endbadly, NULL); | ||
148 | GNUNET_break (0); | ||
149 | return; | ||
150 | } | ||
151 | |||
152 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
153 | "Block was decrypted successfully \n"); | ||
154 | |||
155 | GNUNET_SCHEDULER_add_now (&end, NULL); | ||
156 | } | ||
157 | |||
158 | |||
159 | static void | ||
160 | name_lookup_proc (void *cls, | ||
161 | const struct GNUNET_GNSRECORD_Block *block) | ||
162 | { | ||
163 | const char *name = cls; | ||
164 | |||
165 | ncqe = NULL; | ||
166 | GNUNET_assert (NULL != cls); | ||
167 | |||
168 | if (endbadly_task != NULL) | ||
169 | { | ||
170 | GNUNET_SCHEDULER_cancel (endbadly_task); | ||
171 | endbadly_task = NULL; | ||
172 | } | ||
173 | |||
174 | if (NULL == block) | ||
175 | { | ||
176 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
177 | _ ("Namestore returned no block\n")); | ||
178 | if (endbadly_task != NULL) | ||
179 | GNUNET_SCHEDULER_cancel (endbadly_task); | ||
180 | endbadly_task = GNUNET_SCHEDULER_add_now (&endbadly, NULL); | ||
181 | return; | ||
182 | } | ||
183 | |||
184 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
185 | "Namestore returned block, decrypting \n"); | ||
186 | GNUNET_assert (GNUNET_OK == GNUNET_GNSRECORD_block_decrypt (block, | ||
187 | &pubkey, name, | ||
188 | &rd_decrypt_cb, | ||
189 | (void *) name)); | ||
190 | } | ||
191 | |||
192 | |||
193 | static void | ||
194 | put_cont (void *cls, int32_t success, const char *emsg) | ||
195 | { | ||
196 | const char *name = cls; | ||
197 | struct GNUNET_HashCode derived_hash; | ||
198 | struct GNUNET_IDENTITY_PublicKey pubkey; | ||
199 | |||
200 | nsqe = NULL; | ||
201 | GNUNET_assert (NULL != cls); | ||
202 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
203 | "Name store added record for `%s': %s\n", | ||
204 | name, | ||
205 | (success == GNUNET_OK) ? "SUCCESS" : "FAIL"); | ||
206 | |||
207 | /* Create derived hash */ | ||
208 | GNUNET_IDENTITY_key_get_public (&privkey, | ||
209 | &pubkey); | ||
210 | GNUNET_GNSRECORD_query_from_public_key (&pubkey, | ||
211 | name, | ||
212 | &derived_hash); | ||
213 | |||
214 | ncqe = GNUNET_NAMECACHE_lookup_block (nch, | ||
215 | &derived_hash, | ||
216 | &name_lookup_proc, (void *) name); | ||
217 | } | ||
218 | |||
219 | |||
220 | static void | ||
221 | run (void *cls, | ||
222 | const struct GNUNET_CONFIGURATION_Handle *cfg, | ||
223 | struct GNUNET_TESTING_Peer *peer) | ||
224 | { | ||
225 | struct GNUNET_GNSRECORD_Data rd; | ||
226 | const char *name = "dummy.dummy.gnunet"; | ||
227 | |||
228 | endbadly_task = GNUNET_SCHEDULER_add_delayed (TIMEOUT, | ||
229 | &endbadly, | ||
230 | NULL); | ||
231 | privkey.type = htonl (GNUNET_GNSRECORD_TYPE_PKEY); | ||
232 | GNUNET_CRYPTO_ecdsa_key_create (&privkey.ecdsa_key); | ||
233 | GNUNET_IDENTITY_key_get_public (&privkey, | ||
234 | &pubkey); | ||
235 | rd.expiration_time = GNUNET_TIME_absolute_get ().abs_value_us + 1000000000; | ||
236 | rd.record_type = TEST_RECORD_TYPE; | ||
237 | rd.data_size = TEST_RECORD_DATALEN; | ||
238 | rd.data = GNUNET_malloc (TEST_RECORD_DATALEN); | ||
239 | rd.flags = GNUNET_GNSRECORD_RF_SHADOW_RECORD; | ||
240 | memset ((char *) rd.data, 'a', TEST_RECORD_DATALEN); | ||
241 | |||
242 | nsh = GNUNET_NAMESTORE_connect (cfg); | ||
243 | nch = GNUNET_NAMECACHE_connect (cfg); | ||
244 | GNUNET_break (NULL != nsh); | ||
245 | GNUNET_break (NULL != nch); | ||
246 | nsqe = GNUNET_NAMESTORE_records_store (nsh, | ||
247 | &privkey, | ||
248 | name, | ||
249 | 1, | ||
250 | &rd, | ||
251 | &put_cont, | ||
252 | (void *) name); | ||
253 | if (NULL == nsqe) | ||
254 | { | ||
255 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
256 | _ ("Namestore cannot store no block\n")); | ||
257 | } | ||
258 | GNUNET_free_nz ((void *) rd.data); | ||
259 | } | ||
260 | |||
261 | |||
262 | #include "test_common.c" | ||
263 | |||
264 | |||
265 | int | ||
266 | main (int argc, char *argv[]) | ||
267 | { | ||
268 | const char *plugin_name; | ||
269 | char *cfg_name; | ||
270 | |||
271 | SETUP_CFG (plugin_name, cfg_name); | ||
272 | res = 1; | ||
273 | if (0 != | ||
274 | GNUNET_TESTING_peer_run ("test-namestore-api-lookup-shadow", | ||
275 | cfg_name, | ||
276 | &run, | ||
277 | NULL)) | ||
278 | { | ||
279 | res = 1; | ||
280 | } | ||
281 | GNUNET_DISK_purge_cfg_dir (cfg_name, | ||
282 | "GNUNET_TEST_HOME"); | ||
283 | GNUNET_free (cfg_name); | ||
284 | return res; | ||
285 | } | ||
286 | |||
287 | |||
288 | /* end of test_namestore_api_lookup_shadow.c */ | ||
diff --git a/src/namestore/test_namestore_api_lookup_shadow_filter.c b/src/namestore/test_namestore_api_lookup_shadow_filter.c deleted file mode 100644 index 4fc197750..000000000 --- a/src/namestore/test_namestore_api_lookup_shadow_filter.c +++ /dev/null | |||
@@ -1,371 +0,0 @@ | |||
1 | /* | ||
2 | This file is part of GNUnet. | ||
3 | Copyright (C) 2012 GNUnet e.V. | ||
4 | |||
5 | GNUnet is free software: you can redistribute it and/or modify it | ||
6 | under the terms of the GNU Affero General Public License as published | ||
7 | by the Free Software Foundation, either version 3 of the License, | ||
8 | or (at your option) any later version. | ||
9 | |||
10 | GNUnet is distributed in the hope that it will be useful, but | ||
11 | WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
13 | Affero General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU Affero General Public License | ||
16 | along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
17 | |||
18 | SPDX-License-Identifier: AGPL3.0-or-later | ||
19 | */ | ||
20 | /** | ||
21 | * @file namestore/test_namestore_api_lookup_shadow_filter.c | ||
22 | * @brief testcase for namestore_api.c: store a record with short expiration | ||
23 | * and a shadow record, perform lookup: | ||
24 | * - when active record is valid, expect only active record | ||
25 | * - when active record is expired, expect shadow record only | ||
26 | */ | ||
27 | #include "platform.h" | ||
28 | #include "gnunet_namecache_service.h" | ||
29 | #include "gnunet_namestore_service.h" | ||
30 | #include "gnunet_testing_lib.h" | ||
31 | #include "gnunet_dnsparser_lib.h" | ||
32 | |||
33 | #define TEST_RECORD_TYPE GNUNET_DNSPARSER_TYPE_TXT | ||
34 | |||
35 | #define TEST_NAME "dummy.dummy.gnunet" | ||
36 | #define TEST_RECORD_DATALEN 123 | ||
37 | #define TEST_RECORD_DATA 'a' | ||
38 | #define TEST_SHADOW_RECORD_DATA 'b' | ||
39 | |||
40 | #define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 100) | ||
41 | #define EXPIRATION GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 5) | ||
42 | |||
43 | static struct GNUNET_NAMESTORE_Handle *nsh; | ||
44 | |||
45 | static struct GNUNET_NAMECACHE_Handle *nch; | ||
46 | |||
47 | static struct GNUNET_SCHEDULER_Task *endbadly_task; | ||
48 | |||
49 | static struct GNUNET_SCHEDULER_Task *delayed_lookup_task; | ||
50 | |||
51 | static struct GNUNET_IDENTITY_PrivateKey privkey; | ||
52 | |||
53 | static struct GNUNET_IDENTITY_PublicKey pubkey; | ||
54 | |||
55 | static int res; | ||
56 | |||
57 | static struct GNUNET_NAMESTORE_QueueEntry *nsqe; | ||
58 | |||
59 | static struct GNUNET_NAMECACHE_QueueEntry *ncqe; | ||
60 | |||
61 | static struct GNUNET_NAMECACHE_QueueEntry *ncqe_shadow; | ||
62 | |||
63 | static struct GNUNET_GNSRECORD_Data records[2]; | ||
64 | |||
65 | static struct GNUNET_TIME_Absolute record_expiration; | ||
66 | |||
67 | static struct GNUNET_HashCode derived_hash; | ||
68 | |||
69 | static struct GNUNET_IDENTITY_PublicKey pubkey; | ||
70 | |||
71 | |||
72 | static void | ||
73 | cleanup () | ||
74 | { | ||
75 | if (NULL != nsh) | ||
76 | { | ||
77 | GNUNET_NAMESTORE_disconnect (nsh); | ||
78 | nsh = NULL; | ||
79 | } | ||
80 | if (NULL != nch) | ||
81 | { | ||
82 | GNUNET_NAMECACHE_disconnect (nch); | ||
83 | nch = NULL; | ||
84 | } | ||
85 | GNUNET_SCHEDULER_shutdown (); | ||
86 | } | ||
87 | |||
88 | |||
89 | /** | ||
90 | * Re-establish the connection to the service. | ||
91 | * | ||
92 | * @param cls handle to use to re-connect. | ||
93 | */ | ||
94 | static void | ||
95 | endbadly (void *cls) | ||
96 | { | ||
97 | if (NULL != delayed_lookup_task) | ||
98 | { | ||
99 | GNUNET_SCHEDULER_cancel (delayed_lookup_task); | ||
100 | delayed_lookup_task = NULL; | ||
101 | } | ||
102 | if (NULL != nsqe) | ||
103 | { | ||
104 | GNUNET_NAMESTORE_cancel (nsqe); | ||
105 | nsqe = NULL; | ||
106 | } | ||
107 | if (NULL != ncqe) | ||
108 | { | ||
109 | GNUNET_NAMECACHE_cancel (ncqe); | ||
110 | ncqe = NULL; | ||
111 | } | ||
112 | cleanup (); | ||
113 | res = 1; | ||
114 | } | ||
115 | |||
116 | |||
117 | static void | ||
118 | end (void *cls) | ||
119 | { | ||
120 | cleanup (); | ||
121 | res = 0; | ||
122 | } | ||
123 | |||
124 | |||
125 | static void | ||
126 | rd_decrypt_cb (void *cls, | ||
127 | unsigned int rd_count, | ||
128 | const struct GNUNET_GNSRECORD_Data *rd) | ||
129 | { | ||
130 | struct GNUNET_GNSRECORD_Data *expected_rd = cls; | ||
131 | char rd_cmp_data[TEST_RECORD_DATALEN]; | ||
132 | |||
133 | if (1 != rd_count) | ||
134 | { | ||
135 | GNUNET_SCHEDULER_add_now (&endbadly, NULL); | ||
136 | GNUNET_break (0); | ||
137 | return; | ||
138 | } | ||
139 | if (NULL == rd) | ||
140 | { | ||
141 | GNUNET_SCHEDULER_add_now (&endbadly, NULL); | ||
142 | GNUNET_break (0); | ||
143 | return; | ||
144 | } | ||
145 | if (expected_rd == &records[0]) | ||
146 | { | ||
147 | /* Expecting active record */ | ||
148 | memset (rd_cmp_data, TEST_RECORD_DATA, TEST_RECORD_DATALEN); | ||
149 | if (TEST_RECORD_TYPE != rd[0].record_type) | ||
150 | { | ||
151 | GNUNET_SCHEDULER_add_now (&endbadly, NULL); | ||
152 | GNUNET_break (0); | ||
153 | return; | ||
154 | } | ||
155 | if (TEST_RECORD_DATALEN != rd[0].data_size) | ||
156 | { | ||
157 | GNUNET_SCHEDULER_add_now (&endbadly, NULL); | ||
158 | GNUNET_break (0); | ||
159 | return; | ||
160 | } | ||
161 | if (0 != memcmp (&rd_cmp_data, rd[0].data, TEST_RECORD_DATALEN)) | ||
162 | { | ||
163 | GNUNET_SCHEDULER_add_now (&endbadly, NULL); | ||
164 | GNUNET_break (0); | ||
165 | return; | ||
166 | } | ||
167 | if (0 != (GNUNET_GNSRECORD_RF_SHADOW_RECORD & rd[0].flags)) | ||
168 | { | ||
169 | GNUNET_SCHEDULER_add_now (&endbadly, NULL); | ||
170 | GNUNET_break (0); | ||
171 | return; | ||
172 | } | ||
173 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, | ||
174 | "Block was decrypted successfully with active record\n"); | ||
175 | } | ||
176 | if (expected_rd == &records[1]) | ||
177 | { | ||
178 | /* Expecting shadow record but without shadow flag*/ | ||
179 | memset (rd_cmp_data, TEST_SHADOW_RECORD_DATA, TEST_RECORD_DATALEN); | ||
180 | if (TEST_RECORD_TYPE != rd[0].record_type) | ||
181 | { | ||
182 | GNUNET_SCHEDULER_add_now (&endbadly, NULL); | ||
183 | GNUNET_break (0); | ||
184 | return; | ||
185 | } | ||
186 | if (TEST_RECORD_DATALEN != rd[0].data_size) | ||
187 | { | ||
188 | GNUNET_SCHEDULER_add_now (&endbadly, NULL); | ||
189 | GNUNET_break (0); | ||
190 | return; | ||
191 | } | ||
192 | if (0 != memcmp (&rd_cmp_data, rd[0].data, TEST_RECORD_DATALEN)) | ||
193 | { | ||
194 | GNUNET_SCHEDULER_add_now (&endbadly, NULL); | ||
195 | GNUNET_break (0); | ||
196 | return; | ||
197 | } | ||
198 | if (0 != (GNUNET_GNSRECORD_RF_SHADOW_RECORD & rd[0].flags)) | ||
199 | { | ||
200 | GNUNET_SCHEDULER_add_now (&endbadly, NULL); | ||
201 | GNUNET_break (0); | ||
202 | return; | ||
203 | } | ||
204 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, | ||
205 | "Block was decrypted successfully with former shadow record \n"); | ||
206 | GNUNET_SCHEDULER_add_now (&end, NULL); | ||
207 | } | ||
208 | } | ||
209 | |||
210 | |||
211 | static void | ||
212 | name_lookup_active_proc (void *cls, | ||
213 | const struct GNUNET_GNSRECORD_Block *block) | ||
214 | { | ||
215 | struct GNUNET_GNSRECORD_Data *expected_rd = cls; | ||
216 | |||
217 | GNUNET_assert (NULL != expected_rd); | ||
218 | |||
219 | ncqe = NULL; | ||
220 | ncqe_shadow = NULL; | ||
221 | if (endbadly_task != NULL) | ||
222 | { | ||
223 | GNUNET_SCHEDULER_cancel (endbadly_task); | ||
224 | endbadly_task = NULL; | ||
225 | } | ||
226 | |||
227 | if (NULL == block) | ||
228 | { | ||
229 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
230 | _ ("Namestore returned no block\n")); | ||
231 | if (endbadly_task != NULL) | ||
232 | GNUNET_SCHEDULER_cancel (endbadly_task); | ||
233 | endbadly_task = GNUNET_SCHEDULER_add_now (&endbadly, NULL); | ||
234 | return; | ||
235 | } | ||
236 | |||
237 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
238 | "Namestore returned block, decrypting \n"); | ||
239 | GNUNET_assert (GNUNET_OK == GNUNET_GNSRECORD_block_decrypt (block, | ||
240 | &pubkey, | ||
241 | TEST_NAME, | ||
242 | &rd_decrypt_cb, | ||
243 | expected_rd)); | ||
244 | } | ||
245 | |||
246 | |||
247 | static void | ||
248 | name_lookup_shadow (void *cls) | ||
249 | { | ||
250 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
251 | "Performing lookup for shadow record \n"); | ||
252 | delayed_lookup_task = NULL; | ||
253 | ncqe_shadow = GNUNET_NAMECACHE_lookup_block (nch, &derived_hash, | ||
254 | &name_lookup_active_proc, | ||
255 | &records[1]); | ||
256 | } | ||
257 | |||
258 | |||
259 | static void | ||
260 | put_cont (void *cls, int32_t success, const char *emsg) | ||
261 | { | ||
262 | nsqe = NULL; | ||
263 | |||
264 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
265 | "Name store added record for `%s': %s\n", | ||
266 | TEST_NAME, | ||
267 | (success == GNUNET_OK) ? "SUCCESS" : "FAIL"); | ||
268 | |||
269 | /* Create derived hash */ | ||
270 | GNUNET_IDENTITY_key_get_public (&privkey, | ||
271 | &pubkey); | ||
272 | GNUNET_GNSRECORD_query_from_public_key (&pubkey, TEST_NAME, &derived_hash); | ||
273 | |||
274 | if (0 == GNUNET_TIME_absolute_get_remaining (record_expiration).rel_value_us) | ||
275 | { | ||
276 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
277 | "Test to too long to store records, cannot run test!\n"); | ||
278 | GNUNET_SCHEDULER_add_now (&end, NULL); | ||
279 | return; | ||
280 | } | ||
281 | /* Lookup active record now */ | ||
282 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, | ||
283 | "Performing lookup for active record \n"); | ||
284 | ncqe = GNUNET_NAMECACHE_lookup_block (nch, &derived_hash, | ||
285 | &name_lookup_active_proc, &records[0]); | ||
286 | |||
287 | delayed_lookup_task = GNUNET_SCHEDULER_add_delayed ( | ||
288 | GNUNET_TIME_relative_multiply (EXPIRATION, 2), &name_lookup_shadow, NULL); | ||
289 | } | ||
290 | |||
291 | |||
292 | static void | ||
293 | run (void *cls, | ||
294 | const struct GNUNET_CONFIGURATION_Handle *cfg, | ||
295 | struct GNUNET_TESTING_Peer *peer) | ||
296 | { | ||
297 | endbadly_task = GNUNET_SCHEDULER_add_delayed (TIMEOUT, | ||
298 | &endbadly, | ||
299 | NULL); | ||
300 | privkey.type = htonl (GNUNET_GNSRECORD_TYPE_PKEY); | ||
301 | GNUNET_CRYPTO_ecdsa_key_create (&privkey.ecdsa_key); | ||
302 | GNUNET_IDENTITY_key_get_public (&privkey, | ||
303 | &pubkey); | ||
304 | |||
305 | record_expiration = GNUNET_TIME_absolute_add (GNUNET_TIME_absolute_get (), | ||
306 | EXPIRATION); | ||
307 | records[0].expiration_time = record_expiration.abs_value_us; | ||
308 | records[0].record_type = TEST_RECORD_TYPE; | ||
309 | records[0].data_size = TEST_RECORD_DATALEN; | ||
310 | records[0].data = GNUNET_malloc (TEST_RECORD_DATALEN); | ||
311 | records[0].flags = GNUNET_GNSRECORD_RF_NONE; | ||
312 | memset ((char *) records[0].data, TEST_RECORD_DATA, TEST_RECORD_DATALEN); | ||
313 | |||
314 | records[1].expiration_time = GNUNET_TIME_absolute_get ().abs_value_us | ||
315 | + 1000000000; | ||
316 | records[1].record_type = TEST_RECORD_TYPE; | ||
317 | records[1].data_size = TEST_RECORD_DATALEN; | ||
318 | records[1].data = GNUNET_malloc (TEST_RECORD_DATALEN); | ||
319 | records[1].flags = GNUNET_GNSRECORD_RF_SHADOW_RECORD; | ||
320 | memset ((char *) records[1].data, TEST_SHADOW_RECORD_DATA, | ||
321 | TEST_RECORD_DATALEN); | ||
322 | |||
323 | nsh = GNUNET_NAMESTORE_connect (cfg); | ||
324 | nch = GNUNET_NAMECACHE_connect (cfg); | ||
325 | GNUNET_break (NULL != nsh); | ||
326 | GNUNET_break (NULL != nch); | ||
327 | nsqe = GNUNET_NAMESTORE_records_store (nsh, | ||
328 | &privkey, | ||
329 | TEST_NAME, | ||
330 | 2, | ||
331 | records, | ||
332 | &put_cont, | ||
333 | NULL); | ||
334 | if (NULL == nsqe) | ||
335 | { | ||
336 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
337 | _ ("Namestore cannot store no block\n")); | ||
338 | } | ||
339 | |||
340 | GNUNET_free_nz ((void *) records[0].data); | ||
341 | GNUNET_free_nz ((void *) records[1].data); | ||
342 | } | ||
343 | |||
344 | |||
345 | #include "test_common.c" | ||
346 | |||
347 | |||
348 | int | ||
349 | main (int argc, char *argv[]) | ||
350 | { | ||
351 | const char *plugin_name; | ||
352 | char *cfg_name; | ||
353 | |||
354 | SETUP_CFG (plugin_name, cfg_name); | ||
355 | res = 1; | ||
356 | if (0 != | ||
357 | GNUNET_TESTING_peer_run ("test-namestore-api-lookup-shadow-filter", | ||
358 | cfg_name, | ||
359 | &run, | ||
360 | NULL)) | ||
361 | { | ||
362 | res = 1; | ||
363 | } | ||
364 | GNUNET_DISK_purge_cfg_dir (cfg_name, | ||
365 | "GNUNET_TEST_HOME"); | ||
366 | GNUNET_free (cfg_name); | ||
367 | return res; | ||
368 | } | ||
369 | |||
370 | |||
371 | /* end of test_namestore_api_lookup_shadow_filter.c */ | ||
diff --git a/src/namestore/test_namestore_api_monitoring.c b/src/namestore/test_namestore_api_monitoring.c deleted file mode 100644 index df0c38608..000000000 --- a/src/namestore/test_namestore_api_monitoring.c +++ /dev/null | |||
@@ -1,379 +0,0 @@ | |||
1 | /* | ||
2 | This file is part of GNUnet. | ||
3 | Copyright (C) 2013, 2018 GNUnet e.V. | ||
4 | |||
5 | GNUnet is free software: you can redistribute it and/or modify it | ||
6 | under the terms of the GNU Affero General Public License as published | ||
7 | by the Free Software Foundation, either version 3 of the License, | ||
8 | or (at your option) any later version. | ||
9 | |||
10 | GNUnet is distributed in the hope that it will be useful, but | ||
11 | WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
13 | Affero General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU Affero General Public License | ||
16 | along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
17 | |||
18 | SPDX-License-Identifier: AGPL3.0-or-later | ||
19 | */ | ||
20 | /** | ||
21 | * @file namestore/test_namestore_api_monitoring.c | ||
22 | * @brief testcase for zone monitoring functionality: monitor first, then add records | ||
23 | */ | ||
24 | #include "platform.h" | ||
25 | #include "gnunet_namestore_service.h" | ||
26 | #include "gnunet_testing_lib.h" | ||
27 | #include "namestore.h" | ||
28 | #include "gnunet_dnsparser_lib.h" | ||
29 | |||
30 | #define TEST_RECORD_TYPE GNUNET_DNSPARSER_TYPE_TXT | ||
31 | |||
32 | |||
33 | #define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 100) | ||
34 | |||
35 | |||
36 | static struct GNUNET_NAMESTORE_Handle *nsh; | ||
37 | |||
38 | static struct GNUNET_SCHEDULER_Task *endbadly_task; | ||
39 | |||
40 | static struct GNUNET_IDENTITY_PrivateKey privkey; | ||
41 | |||
42 | static struct GNUNET_IDENTITY_PrivateKey privkey2; | ||
43 | |||
44 | static struct GNUNET_NAMESTORE_ZoneMonitor *zm; | ||
45 | |||
46 | static int res; | ||
47 | |||
48 | static char *s_name_1; | ||
49 | |||
50 | static struct GNUNET_GNSRECORD_Data *s_rd_1; | ||
51 | |||
52 | static char *s_name_2; | ||
53 | |||
54 | static struct GNUNET_GNSRECORD_Data *s_rd_2; | ||
55 | |||
56 | static 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 | static void | ||
64 | do_shutdown () | ||
65 | { | ||
66 | if (NULL != zm) | ||
67 | { | ||
68 | GNUNET_NAMESTORE_zone_monitor_stop (zm); | ||
69 | zm = NULL; | ||
70 | } | ||
71 | if (NULL != ns_ops[0]) | ||
72 | { | ||
73 | GNUNET_NAMESTORE_cancel (ns_ops[0]); | ||
74 | ns_ops[0] = NULL; | ||
75 | } | ||
76 | if (NULL != ns_ops[1]) | ||
77 | { | ||
78 | GNUNET_NAMESTORE_cancel (ns_ops[1]); | ||
79 | ns_ops[1] = NULL; | ||
80 | } | ||
81 | if (NULL != ns_ops[2]) | ||
82 | { | ||
83 | GNUNET_NAMESTORE_cancel (ns_ops[2]); | ||
84 | ns_ops[2] = NULL; | ||
85 | } | ||
86 | if (NULL != nsh) | ||
87 | { | ||
88 | GNUNET_NAMESTORE_disconnect (nsh); | ||
89 | nsh = NULL; | ||
90 | } | ||
91 | GNUNET_free (s_name_1); | ||
92 | GNUNET_free (s_name_2); | ||
93 | GNUNET_free (s_name_3); | ||
94 | |||
95 | if (s_rd_1 != NULL) | ||
96 | { | ||
97 | GNUNET_free_nz ((void *) s_rd_1->data); | ||
98 | GNUNET_free (s_rd_1); | ||
99 | } | ||
100 | if (s_rd_2 != NULL) | ||
101 | { | ||
102 | GNUNET_free_nz ((void *) s_rd_2->data); | ||
103 | GNUNET_free (s_rd_2); | ||
104 | } | ||
105 | if (s_rd_3 != NULL) | ||
106 | { | ||
107 | GNUNET_free_nz ((void *) s_rd_3->data); | ||
108 | GNUNET_free (s_rd_3); | ||
109 | } | ||
110 | } | ||
111 | |||
112 | |||
113 | /** | ||
114 | * Re-establish the connection to the service. | ||
115 | * | ||
116 | * @param cls handle to use to re-connect. | ||
117 | */ | ||
118 | static void | ||
119 | endbadly (void *cls) | ||
120 | { | ||
121 | do_shutdown (); | ||
122 | res = 1; | ||
123 | } | ||
124 | |||
125 | |||
126 | static void | ||
127 | end (void *cls) | ||
128 | { | ||
129 | do_shutdown (); | ||
130 | res = 0; | ||
131 | } | ||
132 | |||
133 | |||
134 | static void | ||
135 | zone_proc (void *cls, | ||
136 | const struct GNUNET_IDENTITY_PrivateKey *zone_key, | ||
137 | const char *name, | ||
138 | unsigned int rd_count, | ||
139 | const struct GNUNET_GNSRECORD_Data *rd) | ||
140 | { | ||
141 | static int returned_records; | ||
142 | static int fail = GNUNET_NO; | ||
143 | |||
144 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
145 | "Comparing results name %s\n", | ||
146 | name); | ||
147 | if (0 != GNUNET_memcmp (zone_key, | ||
148 | &privkey)) | ||
149 | { | ||
150 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
151 | "Monitoring returned wrong zone key\n"); | ||
152 | GNUNET_break (0); | ||
153 | GNUNET_SCHEDULER_cancel (endbadly_task); | ||
154 | endbadly_task = GNUNET_SCHEDULER_add_now (&endbadly, NULL); | ||
155 | return; | ||
156 | } | ||
157 | |||
158 | if (0 == strcmp (name, s_name_1)) | ||
159 | { | ||
160 | if (GNUNET_YES != GNUNET_GNSRECORD_records_cmp (rd, s_rd_1)) | ||
161 | { | ||
162 | GNUNET_break (0); | ||
163 | fail = GNUNET_YES; | ||
164 | } | ||
165 | } | ||
166 | else if (0 == strcmp (name, s_name_2)) | ||
167 | { | ||
168 | if (GNUNET_YES != GNUNET_GNSRECORD_records_cmp (rd, s_rd_2)) | ||
169 | { | ||
170 | GNUNET_break (0); | ||
171 | fail = GNUNET_YES; | ||
172 | } | ||
173 | } | ||
174 | else | ||
175 | { | ||
176 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
177 | "Invalid name %s\n", | ||
178 | name); | ||
179 | GNUNET_break (0); | ||
180 | fail = GNUNET_YES; | ||
181 | } | ||
182 | GNUNET_NAMESTORE_zone_monitor_next (zm, | ||
183 | 1); | ||
184 | if (2 == ++returned_records) | ||
185 | { | ||
186 | if (endbadly_task != NULL) | ||
187 | { | ||
188 | GNUNET_SCHEDULER_cancel (endbadly_task); | ||
189 | endbadly_task = NULL; | ||
190 | } | ||
191 | if (GNUNET_YES == fail) | ||
192 | GNUNET_SCHEDULER_add_now (&endbadly, NULL); | ||
193 | else | ||
194 | GNUNET_SCHEDULER_add_now (&end, NULL); | ||
195 | } | ||
196 | } | ||
197 | |||
198 | |||
199 | static void | ||
200 | put_cont (void *cls, | ||
201 | int32_t success, | ||
202 | const char *emsg) | ||
203 | { | ||
204 | static int c = 0; | ||
205 | char *label = cls; | ||
206 | |||
207 | if (0 == strcmp (label, s_name_1)) | ||
208 | ns_ops[0] = NULL; | ||
209 | else if (0 == strcmp (label, s_name_2)) | ||
210 | ns_ops[1] = NULL; | ||
211 | else if (0 == strcmp (label, s_name_3)) | ||
212 | ns_ops[2] = NULL; | ||
213 | |||
214 | if (success == GNUNET_OK) | ||
215 | { | ||
216 | c++; | ||
217 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
218 | "Created record %u: `%s'\n", | ||
219 | c, | ||
220 | label); | ||
221 | } | ||
222 | else | ||
223 | { | ||
224 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
225 | "Failed to create record `%s'\n", | ||
226 | label); | ||
227 | GNUNET_break (0); | ||
228 | GNUNET_SCHEDULER_cancel (endbadly_task); | ||
229 | endbadly_task = GNUNET_SCHEDULER_add_now (&endbadly, | ||
230 | NULL); | ||
231 | } | ||
232 | } | ||
233 | |||
234 | |||
235 | static struct GNUNET_GNSRECORD_Data * | ||
236 | create_record (unsigned int count) | ||
237 | { | ||
238 | struct GNUNET_GNSRECORD_Data *rd; | ||
239 | |||
240 | rd = GNUNET_new_array (count, | ||
241 | struct GNUNET_GNSRECORD_Data); | ||
242 | for (unsigned int c = 0; c < count; c++) | ||
243 | { | ||
244 | rd[c].expiration_time = GNUNET_TIME_relative_to_absolute ( | ||
245 | GNUNET_TIME_UNIT_HOURS).abs_value_us; | ||
246 | rd[c].record_type = TEST_RECORD_TYPE; | ||
247 | rd[c].data_size = 50; | ||
248 | rd[c].data = GNUNET_malloc (50); | ||
249 | rd[c].flags = 0; | ||
250 | memset ((char *) rd[c].data, 'a', 50); | ||
251 | } | ||
252 | return rd; | ||
253 | } | ||
254 | |||
255 | |||
256 | static void | ||
257 | fail_cb (void *cls) | ||
258 | { | ||
259 | GNUNET_assert (0); | ||
260 | } | ||
261 | |||
262 | |||
263 | static void | ||
264 | sync_cb (void *cls) | ||
265 | { | ||
266 | /* do nothing */ | ||
267 | } | ||
268 | |||
269 | |||
270 | static void | ||
271 | run (void *cls, | ||
272 | const struct GNUNET_CONFIGURATION_Handle *cfg, | ||
273 | struct GNUNET_TESTING_Peer *peer) | ||
274 | { | ||
275 | res = 1; | ||
276 | privkey.type = htonl (GNUNET_GNSRECORD_TYPE_PKEY); | ||
277 | GNUNET_CRYPTO_ecdsa_key_create (&privkey.ecdsa_key); | ||
278 | /* Start monitoring */ | ||
279 | zm = GNUNET_NAMESTORE_zone_monitor_start (cfg, | ||
280 | &privkey, | ||
281 | GNUNET_YES, | ||
282 | &fail_cb, | ||
283 | NULL, | ||
284 | &zone_proc, | ||
285 | NULL, | ||
286 | &sync_cb, | ||
287 | NULL); | ||
288 | if (NULL == zm) | ||
289 | { | ||
290 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
291 | "Failed to create zone monitor\n"); | ||
292 | GNUNET_break (0); | ||
293 | endbadly_task = GNUNET_SCHEDULER_add_now (&endbadly, NULL); | ||
294 | return; | ||
295 | } | ||
296 | |||
297 | endbadly_task = GNUNET_SCHEDULER_add_delayed (TIMEOUT, &endbadly, NULL); | ||
298 | /* Connect to namestore */ | ||
299 | nsh = GNUNET_NAMESTORE_connect (cfg); | ||
300 | if (NULL == nsh) | ||
301 | { | ||
302 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Connect to namestore\n"); | ||
303 | GNUNET_break (0); | ||
304 | endbadly_task = GNUNET_SCHEDULER_add_now (&endbadly, NULL); | ||
305 | return; | ||
306 | } | ||
307 | |||
308 | privkey2.type = htonl (GNUNET_GNSRECORD_TYPE_PKEY); | ||
309 | GNUNET_CRYPTO_ecdsa_key_create (&privkey2.ecdsa_key); | ||
310 | |||
311 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
312 | "Created record 3\n"); | ||
313 | /* name in different zone */ | ||
314 | GNUNET_asprintf (&s_name_3, "dummy3"); | ||
315 | s_rd_3 = create_record (1); | ||
316 | GNUNET_assert (NULL != (ns_ops[2] = | ||
317 | GNUNET_NAMESTORE_records_store (nsh, | ||
318 | &privkey2, | ||
319 | s_name_3, | ||
320 | 1, | ||
321 | s_rd_3, | ||
322 | &put_cont, | ||
323 | s_name_3))); | ||
324 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
325 | "Created record 1\n"); | ||
326 | GNUNET_asprintf (&s_name_1, "dummy1"); | ||
327 | s_rd_1 = create_record (1); | ||
328 | GNUNET_assert (NULL != (ns_ops[0] = | ||
329 | GNUNET_NAMESTORE_records_store (nsh, | ||
330 | &privkey, | ||
331 | s_name_1, | ||
332 | 1, | ||
333 | s_rd_1, | ||
334 | &put_cont, | ||
335 | s_name_1))); | ||
336 | |||
337 | |||
338 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Created record 2 \n"); | ||
339 | GNUNET_asprintf (&s_name_2, "dummy2"); | ||
340 | s_rd_2 = create_record (1); | ||
341 | GNUNET_assert (NULL != (ns_ops[1] = | ||
342 | GNUNET_NAMESTORE_records_store (nsh, | ||
343 | &privkey, | ||
344 | s_name_2, | ||
345 | 1, | ||
346 | s_rd_2, | ||
347 | &put_cont, | ||
348 | s_name_2))); | ||
349 | } | ||
350 | |||
351 | |||
352 | #include "test_common.c" | ||
353 | |||
354 | |||
355 | int | ||
356 | main (int argc, | ||
357 | char *argv[]) | ||
358 | { | ||
359 | const char *plugin_name; | ||
360 | char *cfg_name; | ||
361 | |||
362 | SETUP_CFG (plugin_name, cfg_name); | ||
363 | res = 1; | ||
364 | if (0 != | ||
365 | GNUNET_TESTING_peer_run ("test-namestore-api-monitoring", | ||
366 | cfg_name, | ||
367 | &run, | ||
368 | NULL)) | ||
369 | { | ||
370 | res = 1; | ||
371 | } | ||
372 | GNUNET_DISK_purge_cfg_dir (cfg_name, | ||
373 | "GNUNET_TEST_HOME"); | ||
374 | GNUNET_free (cfg_name); | ||
375 | return res; | ||
376 | } | ||
377 | |||
378 | |||
379 | /* end of test_namestore_api_monitoring.c */ | ||
diff --git a/src/namestore/test_namestore_api_monitoring_existing.c b/src/namestore/test_namestore_api_monitoring_existing.c deleted file mode 100644 index 366f5739f..000000000 --- a/src/namestore/test_namestore_api_monitoring_existing.c +++ /dev/null | |||
@@ -1,397 +0,0 @@ | |||
1 | /* | ||
2 | This file is part of GNUnet. | ||
3 | Copyright (C) 2013, 2018 GNUnet e.V. | ||
4 | |||
5 | GNUnet is free software: you can redistribute it and/or modify it | ||
6 | under the terms of the GNU Affero General Public License as published | ||
7 | by the Free Software Foundation, either version 3 of the License, | ||
8 | or (at your option) any later version. | ||
9 | |||
10 | GNUnet is distributed in the hope that it will be useful, but | ||
11 | WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
13 | Affero General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU Affero General Public License | ||
16 | along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
17 | |||
18 | SPDX-License-Identifier: AGPL3.0-or-later | ||
19 | */ | ||
20 | /** | ||
21 | * @file namestore/test_namestore_api_monitoring_existing.c | ||
22 | * @brief testcase for zone monitoring functionality: add records first, then monitor | ||
23 | */ | ||
24 | #include "platform.h" | ||
25 | #include "gnunet_namestore_service.h" | ||
26 | #include "gnunet_testing_lib.h" | ||
27 | #include "namestore.h" | ||
28 | #include "gnunet_dnsparser_lib.h" | ||
29 | |||
30 | #define TEST_RECORD_TYPE GNUNET_DNSPARSER_TYPE_TXT | ||
31 | |||
32 | |||
33 | #define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 10) | ||
34 | |||
35 | static const struct GNUNET_CONFIGURATION_Handle *cfg; | ||
36 | |||
37 | static struct GNUNET_NAMESTORE_Handle *nsh; | ||
38 | |||
39 | static struct GNUNET_SCHEDULER_Task *endbadly_task; | ||
40 | |||
41 | static struct GNUNET_IDENTITY_PrivateKey privkey; | ||
42 | |||
43 | static struct GNUNET_IDENTITY_PrivateKey privkey2; | ||
44 | |||
45 | static struct GNUNET_NAMESTORE_ZoneMonitor *zm; | ||
46 | |||
47 | static int res; | ||
48 | |||
49 | static const char *s_name_1; | ||
50 | |||
51 | static struct GNUNET_GNSRECORD_Data *s_rd_1; | ||
52 | |||
53 | static const char *s_name_2; | ||
54 | |||
55 | static struct GNUNET_GNSRECORD_Data *s_rd_2; | ||
56 | |||
57 | static const char *s_name_3; | ||
58 | |||
59 | static struct GNUNET_GNSRECORD_Data *s_rd_3; | ||
60 | |||
61 | struct GNUNET_NAMESTORE_QueueEntry *ns_ops[3]; | ||
62 | |||
63 | |||
64 | /** | ||
65 | * Re-establish the connection to the service. | ||
66 | * | ||
67 | * @param cls handle to use to re-connect. | ||
68 | */ | ||
69 | static void | ||
70 | endbadly (void *cls) | ||
71 | { | ||
72 | endbadly_task = NULL; | ||
73 | GNUNET_break (0); | ||
74 | GNUNET_SCHEDULER_shutdown (); | ||
75 | res = 1; | ||
76 | } | ||
77 | |||
78 | |||
79 | static void | ||
80 | end (void *cls) | ||
81 | { | ||
82 | if (NULL != zm) | ||
83 | { | ||
84 | GNUNET_NAMESTORE_zone_monitor_stop (zm); | ||
85 | zm = NULL; | ||
86 | } | ||
87 | if (NULL != ns_ops[0]) | ||
88 | { | ||
89 | GNUNET_NAMESTORE_cancel (ns_ops[0]); | ||
90 | ns_ops[0] = NULL; | ||
91 | } | ||
92 | if (NULL != ns_ops[1]) | ||
93 | { | ||
94 | GNUNET_NAMESTORE_cancel (ns_ops[1]); | ||
95 | ns_ops[1] = NULL; | ||
96 | } | ||
97 | if (NULL != ns_ops[2]) | ||
98 | { | ||
99 | GNUNET_NAMESTORE_cancel (ns_ops[2]); | ||
100 | ns_ops[2] = NULL; | ||
101 | } | ||
102 | if (NULL != endbadly_task) | ||
103 | { | ||
104 | GNUNET_SCHEDULER_cancel (endbadly_task); | ||
105 | endbadly_task = NULL; | ||
106 | } | ||
107 | if (NULL != nsh) | ||
108 | { | ||
109 | GNUNET_NAMESTORE_disconnect (nsh); | ||
110 | nsh = NULL; | ||
111 | } | ||
112 | if (NULL != s_rd_1) | ||
113 | { | ||
114 | GNUNET_free_nz ((void *) s_rd_1->data); | ||
115 | GNUNET_free (s_rd_1); | ||
116 | } | ||
117 | if (NULL != s_rd_2) | ||
118 | { | ||
119 | GNUNET_free_nz ((void *) s_rd_2->data); | ||
120 | GNUNET_free (s_rd_2); | ||
121 | } | ||
122 | if (NULL != s_rd_3) | ||
123 | { | ||
124 | GNUNET_free_nz ((void *) s_rd_3->data); | ||
125 | GNUNET_free (s_rd_3); | ||
126 | } | ||
127 | } | ||
128 | |||
129 | |||
130 | static void | ||
131 | zone_proc (void *cls, | ||
132 | const struct GNUNET_IDENTITY_PrivateKey *zone_key, | ||
133 | const char *name, | ||
134 | unsigned int rd_count, | ||
135 | const struct GNUNET_GNSRECORD_Data *rd) | ||
136 | { | ||
137 | static int returned_records; | ||
138 | static int fail = GNUNET_NO; | ||
139 | |||
140 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
141 | "Comparing results name %s\n", | ||
142 | name); | ||
143 | if (0 != GNUNET_memcmp (zone_key, | ||
144 | &privkey)) | ||
145 | { | ||
146 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
147 | "Monitoring returned wrong zone key\n"); | ||
148 | GNUNET_break (0); | ||
149 | GNUNET_SCHEDULER_shutdown (); | ||
150 | return; | ||
151 | } | ||
152 | |||
153 | if (0 == strcmp (name, | ||
154 | s_name_1)) | ||
155 | { | ||
156 | if (GNUNET_YES != | ||
157 | GNUNET_GNSRECORD_records_cmp (rd, | ||
158 | s_rd_1)) | ||
159 | { | ||
160 | GNUNET_break (0); | ||
161 | fail = GNUNET_YES; | ||
162 | } | ||
163 | } | ||
164 | else if (0 == strcmp (name, | ||
165 | s_name_2)) | ||
166 | { | ||
167 | if (GNUNET_YES != | ||
168 | GNUNET_GNSRECORD_records_cmp (rd, | ||
169 | s_rd_2)) | ||
170 | { | ||
171 | GNUNET_break (0); | ||
172 | fail = GNUNET_YES; | ||
173 | } | ||
174 | } | ||
175 | else | ||
176 | { | ||
177 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
178 | "Invalid name %s\n", | ||
179 | name); | ||
180 | GNUNET_break (0); | ||
181 | fail = GNUNET_YES; | ||
182 | } | ||
183 | GNUNET_NAMESTORE_zone_monitor_next (zm, | ||
184 | 1); | ||
185 | if (2 == ++returned_records) | ||
186 | { | ||
187 | GNUNET_SCHEDULER_shutdown (); | ||
188 | if (GNUNET_YES == fail) | ||
189 | { | ||
190 | GNUNET_break (0); | ||
191 | res = 1; | ||
192 | } | ||
193 | else | ||
194 | { | ||
195 | res = 0; | ||
196 | } | ||
197 | } | ||
198 | } | ||
199 | |||
200 | |||
201 | static void | ||
202 | fail_cb (void *cls) | ||
203 | { | ||
204 | GNUNET_assert (0); | ||
205 | } | ||
206 | |||
207 | |||
208 | static void | ||
209 | sync_cb (void *cls) | ||
210 | { | ||
211 | /* do nothing */ | ||
212 | } | ||
213 | |||
214 | |||
215 | static void | ||
216 | put_cont (void *cls, | ||
217 | int32_t success, | ||
218 | const char *emsg) | ||
219 | { | ||
220 | static int c = 0; | ||
221 | const char *label = cls; | ||
222 | |||
223 | if (0 == strcmp (label, | ||
224 | s_name_1)) | ||
225 | ns_ops[0] = NULL; | ||
226 | else if (0 == strcmp (label, | ||
227 | s_name_2)) | ||
228 | ns_ops[1] = NULL; | ||
229 | else if (0 == strcmp (label, | ||
230 | s_name_3)) | ||
231 | ns_ops[2] = NULL; | ||
232 | |||
233 | if (success == GNUNET_OK) | ||
234 | { | ||
235 | c++; | ||
236 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
237 | "Created record %u: `%s'\n", | ||
238 | c, | ||
239 | label); | ||
240 | } | ||
241 | else | ||
242 | { | ||
243 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
244 | "Failed to created records\n"); | ||
245 | GNUNET_break (0); | ||
246 | res = 1; | ||
247 | GNUNET_SCHEDULER_shutdown (); | ||
248 | return; | ||
249 | } | ||
250 | |||
251 | if (3 == c) | ||
252 | { | ||
253 | /* Start monitoring */ | ||
254 | zm = GNUNET_NAMESTORE_zone_monitor_start (cfg, | ||
255 | &privkey, | ||
256 | GNUNET_YES, | ||
257 | &fail_cb, | ||
258 | NULL, | ||
259 | &zone_proc, | ||
260 | NULL, | ||
261 | &sync_cb, | ||
262 | NULL); | ||
263 | if (NULL == zm) | ||
264 | { | ||
265 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
266 | "Failed to create zone monitor\n"); | ||
267 | GNUNET_break (0); | ||
268 | res = 1; | ||
269 | GNUNET_SCHEDULER_shutdown (); | ||
270 | return; | ||
271 | } | ||
272 | } | ||
273 | } | ||
274 | |||
275 | |||
276 | static struct GNUNET_GNSRECORD_Data * | ||
277 | create_record (unsigned int count) | ||
278 | { | ||
279 | struct GNUNET_GNSRECORD_Data *rd; | ||
280 | |||
281 | rd = GNUNET_new_array (count, | ||
282 | struct GNUNET_GNSRECORD_Data); | ||
283 | for (unsigned int c = 0; c < count; c++) | ||
284 | { | ||
285 | rd[c].expiration_time = GNUNET_TIME_relative_to_absolute ( | ||
286 | GNUNET_TIME_UNIT_HOURS).abs_value_us; | ||
287 | rd[c].record_type = TEST_RECORD_TYPE; | ||
288 | rd[c].data_size = 50; | ||
289 | rd[c].data = GNUNET_malloc (50); | ||
290 | rd[c].flags = 0; | ||
291 | memset ((char *) rd[c].data, | ||
292 | 'a', | ||
293 | 50); | ||
294 | } | ||
295 | return rd; | ||
296 | } | ||
297 | |||
298 | |||
299 | static void | ||
300 | run (void *cls, | ||
301 | const struct GNUNET_CONFIGURATION_Handle *mycfg, | ||
302 | struct GNUNET_TESTING_Peer *peer) | ||
303 | { | ||
304 | res = 1; | ||
305 | privkey.type = htonl (GNUNET_GNSRECORD_TYPE_PKEY); | ||
306 | privkey2.type = htonl (GNUNET_GNSRECORD_TYPE_PKEY); | ||
307 | GNUNET_CRYPTO_ecdsa_key_create (&privkey.ecdsa_key); | ||
308 | GNUNET_CRYPTO_ecdsa_key_create (&privkey2.ecdsa_key); | ||
309 | |||
310 | cfg = mycfg; | ||
311 | GNUNET_SCHEDULER_add_shutdown (&end, | ||
312 | NULL); | ||
313 | endbadly_task = GNUNET_SCHEDULER_add_delayed (TIMEOUT, | ||
314 | &endbadly, | ||
315 | NULL); | ||
316 | /* Connect to namestore */ | ||
317 | nsh = GNUNET_NAMESTORE_connect (cfg); | ||
318 | if (NULL == nsh) | ||
319 | { | ||
320 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
321 | "Connect to namestore failed\n"); | ||
322 | GNUNET_break (0); | ||
323 | endbadly_task = GNUNET_SCHEDULER_add_now (&endbadly, | ||
324 | NULL); | ||
325 | return; | ||
326 | } | ||
327 | |||
328 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
329 | "Created record 3\n"); | ||
330 | /* name in different zone */ | ||
331 | s_name_3 = "dummy3"; | ||
332 | s_rd_3 = create_record (1); | ||
333 | GNUNET_assert (NULL != (ns_ops[2] = | ||
334 | GNUNET_NAMESTORE_records_store (nsh, | ||
335 | &privkey2, | ||
336 | s_name_3, | ||
337 | 1, | ||
338 | s_rd_3, | ||
339 | &put_cont, | ||
340 | (void *) s_name_3))); | ||
341 | |||
342 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
343 | "Created record 1\n"); | ||
344 | s_name_1 = "dummy1"; | ||
345 | s_rd_1 = create_record (1); | ||
346 | GNUNET_assert (NULL != (ns_ops[0] = | ||
347 | GNUNET_NAMESTORE_records_store (nsh, | ||
348 | &privkey, | ||
349 | s_name_1, | ||
350 | 1, | ||
351 | s_rd_1, | ||
352 | &put_cont, | ||
353 | (void *) s_name_1))); | ||
354 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
355 | "Created record 2 \n"); | ||
356 | s_name_2 = "dummy2"; | ||
357 | s_rd_2 = create_record (1); | ||
358 | GNUNET_assert (NULL != (ns_ops[1] = | ||
359 | GNUNET_NAMESTORE_records_store (nsh, | ||
360 | &privkey, | ||
361 | s_name_2, | ||
362 | 1, | ||
363 | s_rd_2, | ||
364 | &put_cont, | ||
365 | (void *) s_name_2))); | ||
366 | } | ||
367 | |||
368 | |||
369 | #include "test_common.c" | ||
370 | |||
371 | |||
372 | int | ||
373 | main (int argc, | ||
374 | char *argv[]) | ||
375 | { | ||
376 | const char *plugin_name; | ||
377 | char *cfg_name; | ||
378 | |||
379 | SETUP_CFG (plugin_name, cfg_name); | ||
380 | res = 1; | ||
381 | if (0 != | ||
382 | GNUNET_TESTING_peer_run ("test-namestore-api-monitoring-existing", | ||
383 | cfg_name, | ||
384 | &run, | ||
385 | NULL)) | ||
386 | { | ||
387 | GNUNET_break (0); | ||
388 | res = 1; | ||
389 | } | ||
390 | GNUNET_DISK_purge_cfg_dir (cfg_name, | ||
391 | "GNUNET_TEST_HOME"); | ||
392 | GNUNET_free (cfg_name); | ||
393 | return res; | ||
394 | } | ||
395 | |||
396 | |||
397 | /* end of test_namestore_api_monitoring_existing.c */ | ||
diff --git a/src/namestore/test_namestore_api_postgres.conf b/src/namestore/test_namestore_api_postgres.conf deleted file mode 100644 index 93ef935b5..000000000 --- a/src/namestore/test_namestore_api_postgres.conf +++ /dev/null | |||
@@ -1,9 +0,0 @@ | |||
1 | @INLINE@ test_namestore_api.conf | ||
2 | |||
3 | [namestore] | ||
4 | DATABASE = postgres | ||
5 | |||
6 | |||
7 | [namestore-postgres] | ||
8 | CONFIG = connect_timeout=10 dbname=gnunetcheck | ||
9 | TEMPORARY_TABLE = YES | ||
diff --git a/src/namestore/test_namestore_api_remove.c b/src/namestore/test_namestore_api_remove.c deleted file mode 100644 index b6254e531..000000000 --- a/src/namestore/test_namestore_api_remove.c +++ /dev/null | |||
@@ -1,221 +0,0 @@ | |||
1 | /* | ||
2 | This file is part of GNUnet. | ||
3 | Copyright (C) 2013 GNUnet e.V. | ||
4 | |||
5 | GNUnet is free software: you can redistribute it and/or modify it | ||
6 | under the terms of the GNU Affero General Public License as published | ||
7 | by the Free Software Foundation, either version 3 of the License, | ||
8 | or (at your option) any later version. | ||
9 | |||
10 | GNUnet is distributed in the hope that it will be useful, but | ||
11 | WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
13 | Affero General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU Affero General Public License | ||
16 | along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
17 | |||
18 | SPDX-License-Identifier: AGPL3.0-or-later | ||
19 | */ | ||
20 | /** | ||
21 | * @file namestore/test_namestore_api.c | ||
22 | * @brief testcase for namestore_api.c to: remove record | ||
23 | */ | ||
24 | #include "platform.h" | ||
25 | #include "gnunet_namestore_service.h" | ||
26 | #include "gnunet_testing_lib.h" | ||
27 | #include "gnunet_dnsparser_lib.h" | ||
28 | |||
29 | #define TEST_RECORD_TYPE GNUNET_DNSPARSER_TYPE_TXT | ||
30 | |||
31 | #define TEST_RECORD_DATALEN 123 | ||
32 | |||
33 | #define TEST_RECORD_DATA 'a' | ||
34 | |||
35 | #define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 100) | ||
36 | |||
37 | |||
38 | static struct GNUNET_NAMESTORE_Handle *nsh; | ||
39 | |||
40 | static struct GNUNET_SCHEDULER_Task *endbadly_task; | ||
41 | |||
42 | static struct GNUNET_IDENTITY_PrivateKey privkey; | ||
43 | |||
44 | static struct GNUNET_IDENTITY_PublicKey pubkey; | ||
45 | |||
46 | static int res; | ||
47 | |||
48 | static int removed; | ||
49 | |||
50 | static struct GNUNET_NAMESTORE_QueueEntry *nsqe; | ||
51 | |||
52 | |||
53 | static void | ||
54 | cleanup () | ||
55 | { | ||
56 | if (NULL != nsh) | ||
57 | { | ||
58 | GNUNET_NAMESTORE_disconnect (nsh); | ||
59 | nsh = NULL; | ||
60 | } | ||
61 | GNUNET_SCHEDULER_shutdown (); | ||
62 | } | ||
63 | |||
64 | |||
65 | /** | ||
66 | * Re-establish the connection to the service. | ||
67 | * | ||
68 | * @param cls handle to use to re-connect. | ||
69 | */ | ||
70 | static void | ||
71 | endbadly (void *cls) | ||
72 | { | ||
73 | if (NULL != nsqe) | ||
74 | { | ||
75 | GNUNET_NAMESTORE_cancel (nsqe); | ||
76 | nsqe = NULL; | ||
77 | } | ||
78 | cleanup (); | ||
79 | res = 1; | ||
80 | } | ||
81 | |||
82 | |||
83 | static void | ||
84 | end (void *cls) | ||
85 | { | ||
86 | cleanup (); | ||
87 | res = 0; | ||
88 | } | ||
89 | |||
90 | |||
91 | static void | ||
92 | remove_cont (void *cls, | ||
93 | int32_t success, | ||
94 | const char *emsg) | ||
95 | { | ||
96 | nsqe = NULL; | ||
97 | if (GNUNET_YES != success) | ||
98 | { | ||
99 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
100 | _ ("Records could not be removed: `%s'\n"), | ||
101 | emsg); | ||
102 | if (NULL != endbadly_task) | ||
103 | GNUNET_SCHEDULER_cancel (endbadly_task); | ||
104 | endbadly_task = GNUNET_SCHEDULER_add_now (&endbadly, | ||
105 | NULL); | ||
106 | return; | ||
107 | } | ||
108 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, | ||
109 | "Records were removed, perform lookup\n"); | ||
110 | removed = GNUNET_YES; | ||
111 | if (NULL != endbadly_task) | ||
112 | GNUNET_SCHEDULER_cancel (endbadly_task); | ||
113 | GNUNET_SCHEDULER_add_now (&end, NULL); | ||
114 | } | ||
115 | |||
116 | |||
117 | static void | ||
118 | put_cont (void *cls, | ||
119 | int32_t success, | ||
120 | const char *emsg) | ||
121 | { | ||
122 | const char *name = cls; | ||
123 | |||
124 | GNUNET_assert (NULL != cls); | ||
125 | nsqe = NULL; | ||
126 | if (GNUNET_SYSERR == success) | ||
127 | { | ||
128 | GNUNET_break (0); | ||
129 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
130 | "Namestore could not store record: `%s'\n", | ||
131 | emsg); | ||
132 | if (endbadly_task != NULL) | ||
133 | GNUNET_SCHEDULER_cancel (endbadly_task); | ||
134 | endbadly_task = GNUNET_SCHEDULER_add_now (&endbadly, NULL); | ||
135 | return; | ||
136 | } | ||
137 | |||
138 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
139 | "Name store added record for `%s': %s\n", | ||
140 | name, | ||
141 | (success == GNUNET_OK) ? "SUCCESS" : "FAIL"); | ||
142 | nsqe = GNUNET_NAMESTORE_records_store (nsh, | ||
143 | &privkey, | ||
144 | name, | ||
145 | 0, NULL, | ||
146 | &remove_cont, (void *) name); | ||
147 | } | ||
148 | |||
149 | |||
150 | static void | ||
151 | run (void *cls, | ||
152 | const struct GNUNET_CONFIGURATION_Handle *cfg, | ||
153 | struct GNUNET_TESTING_Peer *peer) | ||
154 | { | ||
155 | struct GNUNET_GNSRECORD_Data rd; | ||
156 | const char *name = "dummy.dummy.gnunet"; | ||
157 | |||
158 | endbadly_task = GNUNET_SCHEDULER_add_delayed (TIMEOUT, | ||
159 | &endbadly, | ||
160 | NULL); | ||
161 | privkey.type = htonl (GNUNET_GNSRECORD_TYPE_PKEY); | ||
162 | GNUNET_CRYPTO_ecdsa_key_create (&privkey.ecdsa_key); | ||
163 | GNUNET_IDENTITY_key_get_public (&privkey, | ||
164 | &pubkey); | ||
165 | |||
166 | removed = GNUNET_NO; | ||
167 | |||
168 | rd.expiration_time = GNUNET_TIME_absolute_get ().abs_value_us; | ||
169 | rd.record_type = TEST_RECORD_TYPE; | ||
170 | rd.data_size = TEST_RECORD_DATALEN; | ||
171 | rd.data = GNUNET_malloc (TEST_RECORD_DATALEN); | ||
172 | rd.flags = 0; | ||
173 | memset ((char *) rd.data, | ||
174 | 'a', | ||
175 | TEST_RECORD_DATALEN); | ||
176 | |||
177 | nsh = GNUNET_NAMESTORE_connect (cfg); | ||
178 | GNUNET_break (NULL != nsh); | ||
179 | nsqe = GNUNET_NAMESTORE_records_store (nsh, | ||
180 | &privkey, | ||
181 | name, | ||
182 | 1, | ||
183 | &rd, | ||
184 | &put_cont, | ||
185 | (void *) name); | ||
186 | if (NULL == nsqe) | ||
187 | { | ||
188 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
189 | _ ("Namestore cannot store no block\n")); | ||
190 | } | ||
191 | GNUNET_free_nz ((void *) rd.data); | ||
192 | } | ||
193 | |||
194 | |||
195 | #include "test_common.c" | ||
196 | |||
197 | |||
198 | int | ||
199 | main (int argc, char *argv[]) | ||
200 | { | ||
201 | const char *plugin_name; | ||
202 | char *cfg_name; | ||
203 | |||
204 | SETUP_CFG (plugin_name, cfg_name); | ||
205 | res = 1; | ||
206 | if (0 != | ||
207 | GNUNET_TESTING_peer_run ("test-namestore-api-remove", | ||
208 | cfg_name, | ||
209 | &run, | ||
210 | NULL)) | ||
211 | { | ||
212 | res = 1; | ||
213 | } | ||
214 | GNUNET_DISK_purge_cfg_dir (cfg_name, | ||
215 | "GNUNET_TEST_HOME"); | ||
216 | GNUNET_free (cfg_name); | ||
217 | return res; | ||
218 | } | ||
219 | |||
220 | |||
221 | /* end of test_namestore_api_remove.c */ | ||
diff --git a/src/namestore/test_namestore_api_remove_not_existing_record.c b/src/namestore/test_namestore_api_remove_not_existing_record.c deleted file mode 100644 index e66992909..000000000 --- a/src/namestore/test_namestore_api_remove_not_existing_record.c +++ /dev/null | |||
@@ -1,180 +0,0 @@ | |||
1 | /* | ||
2 | This file is part of GNUnet. | ||
3 | Copyright (C) 2013 GNUnet e.V. | ||
4 | |||
5 | GNUnet is free software: you can redistribute it and/or modify it | ||
6 | under the terms of the GNU Affero General Public License as published | ||
7 | by the Free Software Foundation, either version 3 of the License, | ||
8 | or (at your option) any later version. | ||
9 | |||
10 | GNUnet is distributed in the hope that it will be useful, but | ||
11 | WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
13 | Affero General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU Affero General Public License | ||
16 | along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
17 | |||
18 | SPDX-License-Identifier: AGPL3.0-or-later | ||
19 | */ | ||
20 | /** | ||
21 | * @file namestore/test_namestore_api_remove_not_existing_record.c | ||
22 | * @brief testcase for namestore_api.c | ||
23 | */ | ||
24 | #include "platform.h" | ||
25 | #include "gnunet_namestore_service.h" | ||
26 | #include "gnunet_testing_lib.h" | ||
27 | |||
28 | #define TEST_RECORD_TYPE 1234 | ||
29 | |||
30 | #define TEST_RECORD_DATALEN 123 | ||
31 | |||
32 | #define TEST_RECORD_DATA 'a' | ||
33 | |||
34 | #define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 100) | ||
35 | |||
36 | |||
37 | static struct GNUNET_NAMESTORE_Handle *nsh; | ||
38 | |||
39 | static struct GNUNET_SCHEDULER_Task *endbadly_task; | ||
40 | |||
41 | static struct GNUNET_IDENTITY_PrivateKey privkey; | ||
42 | |||
43 | static struct GNUNET_IDENTITY_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 | int32_t success, | ||
91 | const char *emsg) | ||
92 | { | ||
93 | GNUNET_assert (NULL != cls); | ||
94 | nsqe = NULL; | ||
95 | if (endbadly_task != NULL) | ||
96 | { | ||
97 | GNUNET_SCHEDULER_cancel (endbadly_task); | ||
98 | endbadly_task = NULL; | ||
99 | } | ||
100 | switch (success) | ||
101 | { | ||
102 | case GNUNET_NO: | ||
103 | /* We expected GNUNET_NO, since record was not found */ | ||
104 | GNUNET_SCHEDULER_add_now (&end, NULL); | ||
105 | break; | ||
106 | |||
107 | case GNUNET_OK: | ||
108 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
109 | "Namestore could remove non-existing record: `%s'\n", | ||
110 | (NULL != emsg) ? emsg : ""); | ||
111 | GNUNET_SCHEDULER_add_now (&endbadly, NULL); | ||
112 | break; | ||
113 | |||
114 | case GNUNET_SYSERR: | ||
115 | default: | ||
116 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
117 | "Namestore failed: `%s'\n", | ||
118 | (NULL != emsg) ? emsg : ""); | ||
119 | GNUNET_SCHEDULER_add_now (&endbadly, NULL); | ||
120 | break; | ||
121 | } | ||
122 | } | ||
123 | |||
124 | |||
125 | static void | ||
126 | run (void *cls, | ||
127 | const struct GNUNET_CONFIGURATION_Handle *cfg, | ||
128 | struct GNUNET_TESTING_Peer *peer) | ||
129 | { | ||
130 | const char *name = "dummy.dummy.gnunet"; | ||
131 | |||
132 | endbadly_task = GNUNET_SCHEDULER_add_delayed (TIMEOUT, | ||
133 | &endbadly, | ||
134 | NULL); | ||
135 | privkey.type = htonl (GNUNET_GNSRECORD_TYPE_PKEY); | ||
136 | GNUNET_CRYPTO_ecdsa_key_create (&privkey.ecdsa_key); | ||
137 | GNUNET_IDENTITY_key_get_public (&privkey, &pubkey); | ||
138 | |||
139 | nsh = GNUNET_NAMESTORE_connect (cfg); | ||
140 | GNUNET_break (NULL != nsh); | ||
141 | nsqe = GNUNET_NAMESTORE_records_store (nsh, | ||
142 | &privkey, | ||
143 | name, | ||
144 | 0, NULL, | ||
145 | &put_cont, (void *) name); | ||
146 | if (NULL == nsqe) | ||
147 | { | ||
148 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
149 | _ ("Namestore cannot store no block\n")); | ||
150 | } | ||
151 | } | ||
152 | |||
153 | |||
154 | #include "test_common.c" | ||
155 | |||
156 | |||
157 | int | ||
158 | main (int argc, char *argv[]) | ||
159 | { | ||
160 | const char *plugin_name; | ||
161 | char *cfg_name; | ||
162 | |||
163 | SETUP_CFG (plugin_name, cfg_name); | ||
164 | res = 1; | ||
165 | if (0 != | ||
166 | GNUNET_TESTING_peer_run ("test-namestore-api-remove-non-existing-record", | ||
167 | cfg_name, | ||
168 | &run, | ||
169 | NULL)) | ||
170 | { | ||
171 | res = 1; | ||
172 | } | ||
173 | GNUNET_DISK_purge_cfg_dir (cfg_name, | ||
174 | "GNUNET_TEST_HOME"); | ||
175 | GNUNET_free (cfg_name); | ||
176 | return res; | ||
177 | } | ||
178 | |||
179 | |||
180 | /* end of test_namestore_api_remove_not_existing_record.c */ | ||
diff --git a/src/namestore/test_namestore_api_sqlite.conf b/src/namestore/test_namestore_api_sqlite.conf deleted file mode 100644 index cd4822097..000000000 --- a/src/namestore/test_namestore_api_sqlite.conf +++ /dev/null | |||
@@ -1,8 +0,0 @@ | |||
1 | @INLINE@ test_namestore_api.conf | ||
2 | |||
3 | [namestore] | ||
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 | ||
diff --git a/src/namestore/test_namestore_api_store.c b/src/namestore/test_namestore_api_store.c deleted file mode 100644 index e0b7daa5d..000000000 --- a/src/namestore/test_namestore_api_store.c +++ /dev/null | |||
@@ -1,172 +0,0 @@ | |||
1 | /* | ||
2 | This file is part of GNUnet. | ||
3 | Copyright (C) 2012 GNUnet e.V. | ||
4 | |||
5 | GNUnet is free software: you can redistribute it and/or modify it | ||
6 | under the terms of the GNU Affero General Public License as published | ||
7 | by the Free Software Foundation, either version 3 of the License, | ||
8 | or (at your option) any later version. | ||
9 | |||
10 | GNUnet is distributed in the hope that it will be useful, but | ||
11 | WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
13 | Affero General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU Affero General Public License | ||
16 | along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
17 | |||
18 | SPDX-License-Identifier: AGPL3.0-or-later | ||
19 | */ | ||
20 | /** | ||
21 | * @file namestore/test_namestore_api_store.c | ||
22 | * @brief testcase for namestore_api.c: store a record | ||
23 | */ | ||
24 | #include "platform.h" | ||
25 | #include "gnunet_namestore_service.h" | ||
26 | #include "gnunet_testing_lib.h" | ||
27 | #include "gnunet_dnsparser_lib.h" | ||
28 | |||
29 | #define TEST_RECORD_TYPE GNUNET_DNSPARSER_TYPE_TXT | ||
30 | |||
31 | #define TEST_RECORD_DATALEN 123 | ||
32 | |||
33 | #define TEST_RECORD_DATA 'a' | ||
34 | |||
35 | #define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 100) | ||
36 | |||
37 | |||
38 | static struct GNUNET_NAMESTORE_Handle *nsh; | ||
39 | |||
40 | static struct GNUNET_SCHEDULER_Task *endbadly_task; | ||
41 | |||
42 | static struct GNUNET_IDENTITY_PrivateKey privkey; | ||
43 | |||
44 | static struct GNUNET_IDENTITY_PublicKey pubkey; | ||
45 | |||
46 | static int res; | ||
47 | |||
48 | static struct GNUNET_NAMESTORE_QueueEntry *nsqe; | ||
49 | |||
50 | |||
51 | static void | ||
52 | cleanup () | ||
53 | { | ||
54 | if (NULL != nsh) | ||
55 | { | ||
56 | GNUNET_NAMESTORE_disconnect (nsh); | ||
57 | nsh = NULL; | ||
58 | } | ||
59 | GNUNET_SCHEDULER_shutdown (); | ||
60 | } | ||
61 | |||
62 | |||
63 | /** | ||
64 | * Re-establish the connection to the service. | ||
65 | * | ||
66 | * @param cls handle to use to re-connect. | ||
67 | */ | ||
68 | static void | ||
69 | endbadly (void *cls) | ||
70 | { | ||
71 | if (NULL != nsqe) | ||
72 | { | ||
73 | GNUNET_NAMESTORE_cancel (nsqe); | ||
74 | nsqe = NULL; | ||
75 | } | ||
76 | cleanup (); | ||
77 | res = 1; | ||
78 | } | ||
79 | |||
80 | |||
81 | static void | ||
82 | end (void *cls) | ||
83 | { | ||
84 | cleanup (); | ||
85 | res = 0; | ||
86 | } | ||
87 | |||
88 | |||
89 | static void | ||
90 | put_cont (void *cls, int32_t success, const char *emsg) | ||
91 | { | ||
92 | const char *name = cls; | ||
93 | |||
94 | nsqe = NULL; | ||
95 | GNUNET_assert (NULL != cls); | ||
96 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
97 | "Name store added record for `%s': %s\n", | ||
98 | name, | ||
99 | (success == GNUNET_OK) ? "SUCCESS" : "FAIL"); | ||
100 | GNUNET_SCHEDULER_cancel (endbadly_task); | ||
101 | endbadly_task = NULL; | ||
102 | GNUNET_SCHEDULER_add_now (&end, NULL); | ||
103 | } | ||
104 | |||
105 | |||
106 | static void | ||
107 | run (void *cls, | ||
108 | const struct GNUNET_CONFIGURATION_Handle *cfg, | ||
109 | struct GNUNET_TESTING_Peer *peer) | ||
110 | { | ||
111 | struct GNUNET_GNSRECORD_Data rd; | ||
112 | const char *name = "dummy.dummy.gnunet"; | ||
113 | |||
114 | endbadly_task = GNUNET_SCHEDULER_add_delayed (TIMEOUT, | ||
115 | &endbadly, NULL); | ||
116 | privkey.type = htonl (GNUNET_GNSRECORD_TYPE_PKEY); | ||
117 | GNUNET_CRYPTO_ecdsa_key_create (&privkey.ecdsa_key); | ||
118 | GNUNET_IDENTITY_key_get_public (&privkey, &pubkey); | ||
119 | |||
120 | |||
121 | rd.expiration_time = GNUNET_TIME_absolute_get ().abs_value_us; | ||
122 | rd.record_type = TEST_RECORD_TYPE; | ||
123 | rd.data_size = TEST_RECORD_DATALEN; | ||
124 | rd.data = GNUNET_malloc (TEST_RECORD_DATALEN); | ||
125 | rd.flags = 0; | ||
126 | memset ((char *) rd.data, 'a', TEST_RECORD_DATALEN); | ||
127 | |||
128 | nsh = GNUNET_NAMESTORE_connect (cfg); | ||
129 | GNUNET_break (NULL != nsh); | ||
130 | nsqe = GNUNET_NAMESTORE_records_store (nsh, | ||
131 | &privkey, | ||
132 | name, | ||
133 | 1, | ||
134 | &rd, | ||
135 | &put_cont, | ||
136 | (void *) name); | ||
137 | if (NULL == nsqe) | ||
138 | { | ||
139 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
140 | _ ("Namestore cannot store no block\n")); | ||
141 | } | ||
142 | GNUNET_free_nz ((void *) rd.data); | ||
143 | } | ||
144 | |||
145 | |||
146 | #include "test_common.c" | ||
147 | |||
148 | |||
149 | int | ||
150 | main (int argc, char *argv[]) | ||
151 | { | ||
152 | const char *plugin_name; | ||
153 | char *cfg_name; | ||
154 | |||
155 | SETUP_CFG (plugin_name, cfg_name); | ||
156 | res = 1; | ||
157 | if (0 != | ||
158 | GNUNET_TESTING_peer_run ("test-namestore-api", | ||
159 | cfg_name, | ||
160 | &run, | ||
161 | NULL)) | ||
162 | { | ||
163 | res = 1; | ||
164 | } | ||
165 | GNUNET_DISK_purge_cfg_dir (cfg_name, | ||
166 | "GNUNET_TEST_HOME"); | ||
167 | GNUNET_free (cfg_name); | ||
168 | return res; | ||
169 | } | ||
170 | |||
171 | |||
172 | /* end of test_namestore_api_store.c */ | ||
diff --git a/src/namestore/test_namestore_api_store_update.c b/src/namestore/test_namestore_api_store_update.c deleted file mode 100644 index 5c169734a..000000000 --- a/src/namestore/test_namestore_api_store_update.c +++ /dev/null | |||
@@ -1,309 +0,0 @@ | |||
1 | /* | ||
2 | This file is part of GNUnet. | ||
3 | Copyright (C) 2012, 2013, 2018 GNUnet e.V. | ||
4 | |||
5 | GNUnet is free software: you can redistribute it and/or modify it | ||
6 | under the terms of the GNU Affero General Public License as published | ||
7 | by the Free Software Foundation, either version 3 of the License, | ||
8 | or (at your option) any later version. | ||
9 | |||
10 | GNUnet is distributed in the hope that it will be useful, but | ||
11 | WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
13 | Affero General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU Affero General Public License | ||
16 | along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
17 | |||
18 | SPDX-License-Identifier: AGPL3.0-or-later | ||
19 | */ | ||
20 | /** | ||
21 | * @file namestore/test_namestore_api_store_update.c | ||
22 | * @brief testcase for namestore_api.c: store a record, update it and perform a lookup | ||
23 | * @author Matthias Wachs | ||
24 | * @author Christian Grothoff | ||
25 | */ | ||
26 | #include "platform.h" | ||
27 | #include "gnunet_namecache_service.h" | ||
28 | #include "gnunet_namestore_service.h" | ||
29 | #include "gnunet_testing_lib.h" | ||
30 | #include "gnunet_dnsparser_lib.h" | ||
31 | |||
32 | #define TEST_RECORD_TYPE GNUNET_DNSPARSER_TYPE_TXT | ||
33 | |||
34 | #define TEST_RECORD_DATALEN 123 | ||
35 | |||
36 | #define TEST_RECORD_DATA 'a' | ||
37 | |||
38 | #define TEST_RECORD_DATALEN2 234 | ||
39 | |||
40 | #define TEST_RECORD_DATA2 'b' | ||
41 | |||
42 | #define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 100) | ||
43 | |||
44 | |||
45 | static struct GNUNET_NAMESTORE_Handle *nsh; | ||
46 | |||
47 | static struct GNUNET_NAMECACHE_Handle *nch; | ||
48 | |||
49 | static struct GNUNET_SCHEDULER_Task *endbadly_task; | ||
50 | |||
51 | static struct GNUNET_IDENTITY_PrivateKey privkey; | ||
52 | |||
53 | static struct GNUNET_IDENTITY_PublicKey pubkey; | ||
54 | |||
55 | static int res; | ||
56 | |||
57 | static int update_performed; | ||
58 | |||
59 | static struct GNUNET_NAMESTORE_QueueEntry *nsqe; | ||
60 | |||
61 | static struct GNUNET_NAMECACHE_QueueEntry *ncqe; | ||
62 | |||
63 | static const char *name = "dummy"; | ||
64 | |||
65 | |||
66 | /** | ||
67 | * Terminate test with error. | ||
68 | * | ||
69 | * @param cls handle to use to re-connect. | ||
70 | */ | ||
71 | static void | ||
72 | endbadly (void *cls) | ||
73 | { | ||
74 | GNUNET_break (0); | ||
75 | endbadly_task = NULL; | ||
76 | GNUNET_SCHEDULER_shutdown (); | ||
77 | res = 1; | ||
78 | } | ||
79 | |||
80 | |||
81 | static void | ||
82 | end (void *cls) | ||
83 | { | ||
84 | if (NULL != endbadly_task) | ||
85 | { | ||
86 | GNUNET_SCHEDULER_cancel (endbadly_task); | ||
87 | endbadly_task = NULL; | ||
88 | } | ||
89 | if (NULL != nsqe) | ||
90 | { | ||
91 | GNUNET_NAMESTORE_cancel (nsqe); | ||
92 | nsqe = NULL; | ||
93 | } | ||
94 | if (NULL != ncqe) | ||
95 | { | ||
96 | GNUNET_NAMECACHE_cancel (ncqe); | ||
97 | ncqe = NULL; | ||
98 | } | ||
99 | if (NULL != nsh) | ||
100 | { | ||
101 | GNUNET_NAMESTORE_disconnect (nsh); | ||
102 | nsh = NULL; | ||
103 | } | ||
104 | if (NULL != nch) | ||
105 | { | ||
106 | GNUNET_NAMECACHE_disconnect (nch); | ||
107 | nch = NULL; | ||
108 | } | ||
109 | } | ||
110 | |||
111 | |||
112 | static void | ||
113 | put_cont (void *cls, | ||
114 | int32_t success, | ||
115 | const char *emsg); | ||
116 | |||
117 | |||
118 | static void | ||
119 | rd_decrypt_cb (void *cls, | ||
120 | unsigned int rd_count, | ||
121 | const struct GNUNET_GNSRECORD_Data *rd) | ||
122 | { | ||
123 | struct GNUNET_GNSRECORD_Data rd_new; | ||
124 | |||
125 | GNUNET_assert (1 == rd_count); | ||
126 | GNUNET_assert (NULL != rd); | ||
127 | |||
128 | if (GNUNET_NO == update_performed) | ||
129 | { | ||
130 | char rd_cmp_data[TEST_RECORD_DATALEN]; | ||
131 | |||
132 | memset (rd_cmp_data, | ||
133 | TEST_RECORD_DATA, | ||
134 | TEST_RECORD_DATALEN); | ||
135 | GNUNET_assert (TEST_RECORD_TYPE == rd[0].record_type); | ||
136 | GNUNET_assert (TEST_RECORD_DATALEN == rd[0].data_size); | ||
137 | GNUNET_assert (0 == memcmp (&rd_cmp_data, | ||
138 | rd[0].data, | ||
139 | TEST_RECORD_DATALEN)); | ||
140 | |||
141 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
142 | "Block was decrypted successfully, updating record \n"); | ||
143 | |||
144 | rd_new.flags = GNUNET_GNSRECORD_RF_NONE; | ||
145 | rd_new.expiration_time = GNUNET_TIME_absolute_get ().abs_value_us | ||
146 | + 1000000000; | ||
147 | rd_new.record_type = TEST_RECORD_TYPE; | ||
148 | rd_new.data_size = TEST_RECORD_DATALEN2; | ||
149 | rd_new.data = GNUNET_malloc (TEST_RECORD_DATALEN2); | ||
150 | memset ((char *) rd_new.data, | ||
151 | TEST_RECORD_DATA2, | ||
152 | TEST_RECORD_DATALEN2); | ||
153 | |||
154 | nsqe = GNUNET_NAMESTORE_records_store (nsh, | ||
155 | &privkey, | ||
156 | name, | ||
157 | 1, | ||
158 | &rd_new, | ||
159 | &put_cont, | ||
160 | (void *) name); | ||
161 | update_performed = GNUNET_YES; | ||
162 | } | ||
163 | else | ||
164 | { | ||
165 | char rd_cmp_data[TEST_RECORD_DATALEN2]; | ||
166 | |||
167 | memset (rd_cmp_data, | ||
168 | TEST_RECORD_DATA2, | ||
169 | TEST_RECORD_DATALEN2); | ||
170 | GNUNET_assert (TEST_RECORD_TYPE == rd[0].record_type); | ||
171 | GNUNET_assert (TEST_RECORD_DATALEN2 == rd[0].data_size); | ||
172 | GNUNET_assert (0 == memcmp (&rd_cmp_data, | ||
173 | rd[0].data, | ||
174 | TEST_RECORD_DATALEN2)); | ||
175 | GNUNET_SCHEDULER_shutdown (); | ||
176 | res = 0; | ||
177 | } | ||
178 | } | ||
179 | |||
180 | |||
181 | static void | ||
182 | name_lookup_proc (void *cls, | ||
183 | const struct GNUNET_GNSRECORD_Block *block) | ||
184 | { | ||
185 | const char *name = cls; | ||
186 | |||
187 | ncqe = NULL; | ||
188 | GNUNET_assert (NULL != cls); | ||
189 | if (NULL == block) | ||
190 | { | ||
191 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
192 | _ ("Namecache returned no block for `%s'\n"), | ||
193 | name); | ||
194 | GNUNET_SCHEDULER_shutdown (); | ||
195 | return; | ||
196 | } | ||
197 | |||
198 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
199 | "Namecache returned block, decrypting \n"); | ||
200 | GNUNET_assert (GNUNET_OK == | ||
201 | GNUNET_GNSRECORD_block_decrypt (block, | ||
202 | &pubkey, | ||
203 | name, | ||
204 | &rd_decrypt_cb, | ||
205 | (void *) name)); | ||
206 | } | ||
207 | |||
208 | |||
209 | static void | ||
210 | put_cont (void *cls, | ||
211 | int32_t success, | ||
212 | const char *emsg) | ||
213 | { | ||
214 | const char *name = cls; | ||
215 | struct GNUNET_HashCode derived_hash; | ||
216 | |||
217 | nsqe = NULL; | ||
218 | GNUNET_assert (NULL != cls); | ||
219 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
220 | "Name store added record for `%s': %s\n", | ||
221 | name, | ||
222 | (success == GNUNET_OK) ? "SUCCESS" : "FAIL"); | ||
223 | /* Create derived hash */ | ||
224 | GNUNET_GNSRECORD_query_from_private_key (&privkey, | ||
225 | name, | ||
226 | &derived_hash); | ||
227 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
228 | "Looking in namecache for `%s'\n", | ||
229 | GNUNET_h2s (&derived_hash)); | ||
230 | ncqe = GNUNET_NAMECACHE_lookup_block (nch, | ||
231 | &derived_hash, | ||
232 | &name_lookup_proc, (void *) name); | ||
233 | } | ||
234 | |||
235 | |||
236 | static void | ||
237 | run (void *cls, | ||
238 | const struct GNUNET_CONFIGURATION_Handle *cfg, | ||
239 | struct GNUNET_TESTING_Peer *peer) | ||
240 | { | ||
241 | struct GNUNET_GNSRECORD_Data rd; | ||
242 | |||
243 | update_performed = GNUNET_NO; | ||
244 | GNUNET_SCHEDULER_add_shutdown (&end, | ||
245 | NULL); | ||
246 | endbadly_task = GNUNET_SCHEDULER_add_delayed (TIMEOUT, | ||
247 | &endbadly, | ||
248 | NULL); | ||
249 | memset (&privkey, 0, sizeof (privkey)); | ||
250 | privkey.type = htonl (GNUNET_GNSRECORD_TYPE_PKEY); | ||
251 | GNUNET_CRYPTO_ecdsa_key_create (&privkey.ecdsa_key); | ||
252 | GNUNET_IDENTITY_key_get_public (&privkey, &pubkey); | ||
253 | rd.flags = GNUNET_GNSRECORD_RF_NONE; | ||
254 | rd.expiration_time = GNUNET_TIME_absolute_get ().abs_value_us + 1000000000; | ||
255 | rd.record_type = TEST_RECORD_TYPE; | ||
256 | rd.data_size = TEST_RECORD_DATALEN; | ||
257 | rd.data = GNUNET_malloc (TEST_RECORD_DATALEN); | ||
258 | memset ((char *) rd.data, | ||
259 | TEST_RECORD_DATA, | ||
260 | TEST_RECORD_DATALEN); | ||
261 | |||
262 | nsh = GNUNET_NAMESTORE_connect (cfg); | ||
263 | GNUNET_break (NULL != nsh); | ||
264 | nch = GNUNET_NAMECACHE_connect (cfg); | ||
265 | GNUNET_break (NULL != nch); | ||
266 | nsqe = GNUNET_NAMESTORE_records_store (nsh, | ||
267 | &privkey, | ||
268 | name, | ||
269 | 1, | ||
270 | &rd, | ||
271 | &put_cont, | ||
272 | (void *) name); | ||
273 | if (NULL == nsqe) | ||
274 | { | ||
275 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
276 | _ ("Namestore cannot store no block\n")); | ||
277 | } | ||
278 | GNUNET_free_nz ((void *) rd.data); | ||
279 | } | ||
280 | |||
281 | |||
282 | #include "test_common.c" | ||
283 | |||
284 | |||
285 | int | ||
286 | main (int argc, | ||
287 | char *argv[]) | ||
288 | { | ||
289 | const char *plugin_name; | ||
290 | char *cfg_name; | ||
291 | |||
292 | SETUP_CFG (plugin_name, cfg_name); | ||
293 | res = 1; | ||
294 | if (0 != | ||
295 | GNUNET_TESTING_peer_run ("test--store-update", | ||
296 | cfg_name, | ||
297 | &run, | ||
298 | NULL)) | ||
299 | { | ||
300 | res = 1; | ||
301 | } | ||
302 | GNUNET_DISK_purge_cfg_dir (cfg_name, | ||
303 | "GNUNET_TEST_HOME"); | ||
304 | GNUNET_free (cfg_name); | ||
305 | return res; | ||
306 | } | ||
307 | |||
308 | |||
309 | /* end of test_namestore_api_store_update.c */ | ||
diff --git a/src/namestore/test_namestore_api_zone_iteration.c b/src/namestore/test_namestore_api_zone_iteration.c deleted file mode 100644 index 55ca901e2..000000000 --- a/src/namestore/test_namestore_api_zone_iteration.c +++ /dev/null | |||
@@ -1,465 +0,0 @@ | |||
1 | /* | ||
2 | This file is part of GNUnet. | ||
3 | Copyright (C) 2013, 2018 GNUnet e.V. | ||
4 | |||
5 | GNUnet is free software: you can redistribute it and/or modify it | ||
6 | under the terms of the GNU Affero General Public License as published | ||
7 | by the Free Software Foundation, either version 3 of the License, | ||
8 | or (at your option) any later version. | ||
9 | |||
10 | GNUnet is distributed in the hope that it will be useful, but | ||
11 | WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
13 | Affero General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU Affero General Public License | ||
16 | along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
17 | |||
18 | SPDX-License-Identifier: AGPL3.0-or-later | ||
19 | */ | ||
20 | /** | ||
21 | * @file namestore/test_namestore_api_zone_iteration.c | ||
22 | * @brief testcase for zone iteration functionality: iterate all zones | ||
23 | */ | ||
24 | #include "platform.h" | ||
25 | #include "gnunet_namestore_service.h" | ||
26 | #include "gnunet_testing_lib.h" | ||
27 | #include "namestore.h" | ||
28 | #include "gnunet_dnsparser_lib.h" | ||
29 | |||
30 | #define TEST_RECORD_TYPE GNUNET_DNSPARSER_TYPE_TXT | ||
31 | |||
32 | |||
33 | #define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 100) | ||
34 | |||
35 | |||
36 | static struct GNUNET_NAMESTORE_Handle *nsh; | ||
37 | |||
38 | static struct GNUNET_SCHEDULER_Task *endbadly_task; | ||
39 | |||
40 | static struct GNUNET_IDENTITY_PrivateKey privkey; | ||
41 | |||
42 | static struct GNUNET_IDENTITY_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 | * Re-establish the connection to the service. | ||
65 | * | ||
66 | * @param cls handle to use to re-connect. | ||
67 | * @param tc scheduler context | ||
68 | */ | ||
69 | static void | ||
70 | endbadly (void *cls) | ||
71 | { | ||
72 | endbadly_task = NULL; | ||
73 | GNUNET_SCHEDULER_shutdown (); | ||
74 | res = 1; | ||
75 | } | ||
76 | |||
77 | |||
78 | static void | ||
79 | end (void *cls) | ||
80 | { | ||
81 | if (NULL != zi) | ||
82 | { | ||
83 | GNUNET_NAMESTORE_zone_iteration_stop (zi); | ||
84 | zi = NULL; | ||
85 | } | ||
86 | if (NULL != endbadly_task) | ||
87 | { | ||
88 | GNUNET_SCHEDULER_cancel (endbadly_task); | ||
89 | endbadly_task = NULL; | ||
90 | } | ||
91 | GNUNET_free (s_name_1); | ||
92 | GNUNET_free (s_name_2); | ||
93 | GNUNET_free (s_name_3); | ||
94 | if (NULL != s_rd_1) | ||
95 | { | ||
96 | GNUNET_free_nz ((void *) s_rd_1->data); | ||
97 | GNUNET_free (s_rd_1); | ||
98 | } | ||
99 | if (NULL != s_rd_2) | ||
100 | { | ||
101 | GNUNET_free_nz ((void *) s_rd_2->data); | ||
102 | GNUNET_free (s_rd_2); | ||
103 | } | ||
104 | if (NULL != s_rd_3) | ||
105 | { | ||
106 | GNUNET_free_nz ((void *) s_rd_3->data); | ||
107 | GNUNET_free (s_rd_3); | ||
108 | } | ||
109 | if (NULL != nsh) | ||
110 | { | ||
111 | GNUNET_NAMESTORE_disconnect (nsh); | ||
112 | nsh = NULL; | ||
113 | } | ||
114 | } | ||
115 | |||
116 | |||
117 | static void | ||
118 | zone_end (void *cls) | ||
119 | { | ||
120 | GNUNET_break (3 == returned_records); | ||
121 | if (3 == returned_records) | ||
122 | { | ||
123 | res = 0; /* Last iteraterator callback, we are done */ | ||
124 | zi = NULL; | ||
125 | } | ||
126 | else | ||
127 | res = 1; | ||
128 | |||
129 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
130 | "Received last result, iteration done after receing %u results\n", | ||
131 | returned_records); | ||
132 | GNUNET_SCHEDULER_shutdown (); | ||
133 | } | ||
134 | |||
135 | |||
136 | static void | ||
137 | fail_cb (void *cls) | ||
138 | { | ||
139 | GNUNET_assert (0); | ||
140 | } | ||
141 | |||
142 | |||
143 | static void | ||
144 | zone_proc (void *cls, | ||
145 | const struct GNUNET_IDENTITY_PrivateKey *zone, | ||
146 | const char *label, | ||
147 | unsigned int rd_count, | ||
148 | const struct GNUNET_GNSRECORD_Data *rd) | ||
149 | { | ||
150 | int failed = GNUNET_NO; | ||
151 | |||
152 | GNUNET_assert (NULL != zone); | ||
153 | if (0 == GNUNET_memcmp (zone, | ||
154 | &privkey)) | ||
155 | { | ||
156 | if (0 == strcmp (label, s_name_1)) | ||
157 | { | ||
158 | if (rd_count == 1) | ||
159 | { | ||
160 | if (GNUNET_YES != GNUNET_GNSRECORD_records_cmp (rd, s_rd_1)) | ||
161 | { | ||
162 | failed = GNUNET_YES; | ||
163 | GNUNET_break (0); | ||
164 | } | ||
165 | } | ||
166 | else | ||
167 | { | ||
168 | failed = GNUNET_YES; | ||
169 | GNUNET_break (0); | ||
170 | } | ||
171 | } | ||
172 | else if (0 == strcmp (label, s_name_2)) | ||
173 | { | ||
174 | if (rd_count == 1) | ||
175 | { | ||
176 | if (GNUNET_YES != GNUNET_GNSRECORD_records_cmp (rd, s_rd_2)) | ||
177 | { | ||
178 | failed = GNUNET_YES; | ||
179 | GNUNET_break (0); | ||
180 | } | ||
181 | } | ||
182 | else | ||
183 | { | ||
184 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
185 | "Received invalid record count\n"); | ||
186 | failed = GNUNET_YES; | ||
187 | GNUNET_break (0); | ||
188 | } | ||
189 | } | ||
190 | else | ||
191 | { | ||
192 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
193 | "Comparing result failed: got name `%s' for first zone\n", | ||
194 | label); | ||
195 | failed = GNUNET_YES; | ||
196 | GNUNET_break (0); | ||
197 | } | ||
198 | } | ||
199 | else if (0 == GNUNET_memcmp (zone, | ||
200 | &privkey2)) | ||
201 | { | ||
202 | if (0 == strcmp (label, s_name_3)) | ||
203 | { | ||
204 | if (rd_count == 1) | ||
205 | { | ||
206 | if (GNUNET_YES != GNUNET_GNSRECORD_records_cmp (rd, s_rd_3)) | ||
207 | { | ||
208 | failed = GNUNET_YES; | ||
209 | GNUNET_break (0); | ||
210 | } | ||
211 | } | ||
212 | else | ||
213 | { | ||
214 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
215 | "Received invalid record count\n"); | ||
216 | failed = GNUNET_YES; | ||
217 | GNUNET_break (0); | ||
218 | } | ||
219 | } | ||
220 | else | ||
221 | { | ||
222 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
223 | "Comparing result failed: got name `%s' for first zone\n", | ||
224 | label); | ||
225 | failed = GNUNET_YES; | ||
226 | GNUNET_break (0); | ||
227 | } | ||
228 | } | ||
229 | else | ||
230 | { | ||
231 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
232 | "Received invalid zone\n"); | ||
233 | failed = GNUNET_YES; | ||
234 | GNUNET_break (0); | ||
235 | } | ||
236 | |||
237 | if (failed == GNUNET_NO) | ||
238 | { | ||
239 | returned_records++; | ||
240 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
241 | "Telling namestore to send the next result\n"); | ||
242 | GNUNET_NAMESTORE_zone_iterator_next (zi, | ||
243 | 1); | ||
244 | } | ||
245 | else | ||
246 | { | ||
247 | GNUNET_break (0); | ||
248 | GNUNET_SCHEDULER_shutdown (); | ||
249 | res = 1; | ||
250 | } | ||
251 | } | ||
252 | |||
253 | |||
254 | static void | ||
255 | put_cont (void *cls, | ||
256 | int32_t success, | ||
257 | const char *emsg) | ||
258 | { | ||
259 | static int c = 0; | ||
260 | |||
261 | if (success == GNUNET_OK) | ||
262 | { | ||
263 | c++; | ||
264 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
265 | "Created record %u \n", | ||
266 | c); | ||
267 | } | ||
268 | else | ||
269 | { | ||
270 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
271 | "Failed to created records: `%s'\n", | ||
272 | emsg); | ||
273 | GNUNET_break (0); | ||
274 | GNUNET_SCHEDULER_shutdown (); | ||
275 | res = 1; | ||
276 | return; | ||
277 | } | ||
278 | |||
279 | if (c == 3) | ||
280 | { | ||
281 | res = 1; | ||
282 | returned_records = 0; | ||
283 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
284 | "All records created, starting iteration over all zones \n"); | ||
285 | zi = GNUNET_NAMESTORE_zone_iteration_start (nsh, | ||
286 | NULL, | ||
287 | &fail_cb, | ||
288 | NULL, | ||
289 | &zone_proc, | ||
290 | NULL, | ||
291 | &zone_end, | ||
292 | NULL); | ||
293 | if (zi == NULL) | ||
294 | { | ||
295 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
296 | "Failed to create zone iterator\n"); | ||
297 | GNUNET_break (0); | ||
298 | GNUNET_SCHEDULER_shutdown (); | ||
299 | res = 1; | ||
300 | return; | ||
301 | } | ||
302 | } | ||
303 | } | ||
304 | |||
305 | |||
306 | static struct GNUNET_GNSRECORD_Data * | ||
307 | create_record (unsigned int count) | ||
308 | { | ||
309 | struct GNUNET_GNSRECORD_Data *rd; | ||
310 | |||
311 | rd = GNUNET_new_array (count, | ||
312 | struct GNUNET_GNSRECORD_Data); | ||
313 | for (unsigned int c = 0; c < count; c++) | ||
314 | { | ||
315 | rd[c].expiration_time = GNUNET_TIME_relative_to_absolute ( | ||
316 | GNUNET_TIME_UNIT_HOURS).abs_value_us; | ||
317 | rd[c].record_type = TEST_RECORD_TYPE; | ||
318 | rd[c].data_size = 50; | ||
319 | rd[c].data = GNUNET_malloc (50); | ||
320 | rd[c].flags = 0; | ||
321 | memset ((char *) rd[c].data, 'a', 50); | ||
322 | } | ||
323 | return rd; | ||
324 | } | ||
325 | |||
326 | |||
327 | /** | ||
328 | * Callback called from the zone iterator when we iterate over | ||
329 | * the empty zone. Check that we got no records and then | ||
330 | * start the actual tests by filling the zone. | ||
331 | */ | ||
332 | static void | ||
333 | empty_zone_proc (void *cls, | ||
334 | const struct GNUNET_IDENTITY_PrivateKey *zone, | ||
335 | const char *label, | ||
336 | unsigned int rd_count, | ||
337 | const struct GNUNET_GNSRECORD_Data *rd) | ||
338 | { | ||
339 | GNUNET_assert (nsh == cls); | ||
340 | if (NULL != zone) | ||
341 | { | ||
342 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
343 | _ ("Expected empty zone but received zone private key\n")); | ||
344 | GNUNET_break (0); | ||
345 | GNUNET_SCHEDULER_shutdown (); | ||
346 | res = 1; | ||
347 | return; | ||
348 | } | ||
349 | if ((NULL != label) || (NULL != rd) || (0 != rd_count)) | ||
350 | { | ||
351 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
352 | _ ("Expected no zone content but received data\n")); | ||
353 | GNUNET_break (0); | ||
354 | GNUNET_SCHEDULER_shutdown (); | ||
355 | res = 1; | ||
356 | return; | ||
357 | } | ||
358 | GNUNET_assert (0); | ||
359 | } | ||
360 | |||
361 | |||
362 | static void | ||
363 | empty_zone_end (void *cls) | ||
364 | { | ||
365 | zi = NULL; | ||
366 | privkey.type = htonl (GNUNET_GNSRECORD_TYPE_PKEY); | ||
367 | privkey2.type = htonl (GNUNET_GNSRECORD_TYPE_PKEY); | ||
368 | GNUNET_CRYPTO_ecdsa_key_create (&privkey.ecdsa_key); | ||
369 | GNUNET_CRYPTO_ecdsa_key_create (&privkey2.ecdsa_key); | ||
370 | |||
371 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Created record 1\n"); | ||
372 | |||
373 | GNUNET_asprintf (&s_name_1, "dummy1"); | ||
374 | s_rd_1 = create_record (1); | ||
375 | GNUNET_NAMESTORE_records_store (nsh, | ||
376 | &privkey, | ||
377 | s_name_1, | ||
378 | 1, s_rd_1, | ||
379 | &put_cont, | ||
380 | NULL); | ||
381 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
382 | "Created record 2 \n"); | ||
383 | GNUNET_asprintf (&s_name_2, "dummy2"); | ||
384 | s_rd_2 = create_record (1); | ||
385 | GNUNET_NAMESTORE_records_store (nsh, | ||
386 | &privkey, | ||
387 | s_name_2, | ||
388 | 1, s_rd_2, | ||
389 | &put_cont, | ||
390 | NULL); | ||
391 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
392 | "Created record 3\n"); | ||
393 | /* name in different zone */ | ||
394 | GNUNET_asprintf (&s_name_3, "dummy3"); | ||
395 | s_rd_3 = create_record (1); | ||
396 | GNUNET_NAMESTORE_records_store (nsh, | ||
397 | &privkey2, | ||
398 | s_name_3, | ||
399 | 1, | ||
400 | s_rd_3, | ||
401 | &put_cont, | ||
402 | NULL); | ||
403 | } | ||
404 | |||
405 | |||
406 | static void | ||
407 | run (void *cls, | ||
408 | const struct GNUNET_CONFIGURATION_Handle *cfg, | ||
409 | struct GNUNET_TESTING_Peer *peer) | ||
410 | { | ||
411 | endbadly_task = GNUNET_SCHEDULER_add_delayed (TIMEOUT, | ||
412 | &endbadly, | ||
413 | NULL); | ||
414 | GNUNET_SCHEDULER_add_shutdown (&end, | ||
415 | NULL); | ||
416 | |||
417 | nsh = GNUNET_NAMESTORE_connect (cfg); | ||
418 | GNUNET_break (NULL != nsh); | ||
419 | /* first, iterate over empty namestore */ | ||
420 | zi = GNUNET_NAMESTORE_zone_iteration_start (nsh, | ||
421 | NULL, | ||
422 | &fail_cb, | ||
423 | NULL, | ||
424 | &empty_zone_proc, | ||
425 | nsh, | ||
426 | &empty_zone_end, | ||
427 | NULL); | ||
428 | if (NULL == zi) | ||
429 | { | ||
430 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
431 | "Failed to create zone iterator\n"); | ||
432 | GNUNET_break (0); | ||
433 | res = 1; | ||
434 | GNUNET_SCHEDULER_shutdown (); | ||
435 | } | ||
436 | } | ||
437 | |||
438 | |||
439 | #include "test_common.c" | ||
440 | |||
441 | |||
442 | int | ||
443 | main (int argc, char *argv[]) | ||
444 | { | ||
445 | const char *plugin_name; | ||
446 | char *cfg_name; | ||
447 | |||
448 | SETUP_CFG (plugin_name, cfg_name); | ||
449 | res = 1; | ||
450 | if (0 != | ||
451 | GNUNET_TESTING_peer_run ("test-namestore-api-zone-iteration", | ||
452 | cfg_name, | ||
453 | &run, | ||
454 | NULL)) | ||
455 | { | ||
456 | res = 1; | ||
457 | } | ||
458 | GNUNET_DISK_purge_cfg_dir (cfg_name, | ||
459 | "GNUNET_TEST_HOME"); | ||
460 | GNUNET_free (cfg_name); | ||
461 | return res; | ||
462 | } | ||
463 | |||
464 | |||
465 | /* end of test_namestore_api_zone_iteration.c */ | ||
diff --git a/src/namestore/test_namestore_api_zone_iteration_nick.c b/src/namestore/test_namestore_api_zone_iteration_nick.c deleted file mode 100644 index c203a63a6..000000000 --- a/src/namestore/test_namestore_api_zone_iteration_nick.c +++ /dev/null | |||
@@ -1,462 +0,0 @@ | |||
1 | /* | ||
2 | This file is part of GNUnet. | ||
3 | Copyright (C) 2013 GNUnet e.V. | ||
4 | |||
5 | GNUnet is free software: you can redistribute it and/or modify it | ||
6 | under the terms of the GNU Affero General Public License as published | ||
7 | by the Free Software Foundation, either version 3 of the License, | ||
8 | or (at your option) any later version. | ||
9 | |||
10 | GNUnet is distributed in the hope that it will be useful, but | ||
11 | WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
13 | Affero General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU Affero General Public License | ||
16 | along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
17 | |||
18 | SPDX-License-Identifier: AGPL3.0-or-later | ||
19 | */ | ||
20 | /** | ||
21 | * @file namestore/test_namestore_api_zone_iteration.c | ||
22 | * @brief testcase for zone iteration functionality: iterate all zones | ||
23 | */ | ||
24 | #include "platform.h" | ||
25 | #include "gnunet_namestore_service.h" | ||
26 | #include "gnunet_gns_service.h" | ||
27 | #include "gnunet_testing_lib.h" | ||
28 | #include "namestore.h" | ||
29 | #include "gnunet_dnsparser_lib.h" | ||
30 | |||
31 | #define TEST_RECORD_TYPE GNUNET_DNSPARSER_TYPE_TXT | ||
32 | |||
33 | #define ZONE_NICK_1 "nick1" | ||
34 | #define ZONE_NICK_2 "nick2" | ||
35 | |||
36 | #define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 100) | ||
37 | |||
38 | |||
39 | static struct GNUNET_NAMESTORE_Handle *nsh; | ||
40 | |||
41 | static struct GNUNET_IDENTITY_PrivateKey privkey; | ||
42 | |||
43 | static struct GNUNET_IDENTITY_PrivateKey privkey2; | ||
44 | |||
45 | static struct GNUNET_NAMESTORE_ZoneIterator *zi; | ||
46 | |||
47 | static int res; | ||
48 | |||
49 | static int returned_records; | ||
50 | |||
51 | static char *s_name_1; | ||
52 | |||
53 | static struct GNUNET_GNSRECORD_Data *s_rd_1; | ||
54 | |||
55 | static char *s_name_2; | ||
56 | |||
57 | static struct GNUNET_GNSRECORD_Data *s_rd_2; | ||
58 | |||
59 | static char *s_name_3; | ||
60 | |||
61 | static struct GNUNET_GNSRECORD_Data *s_rd_3; | ||
62 | |||
63 | static struct GNUNET_NAMESTORE_QueueEntry *nsqe; | ||
64 | |||
65 | |||
66 | /** | ||
67 | * Re-establish the connection to the service. | ||
68 | * | ||
69 | * @param cls handle to use to re-connect. | ||
70 | * @param tc scheduler context | ||
71 | */ | ||
72 | static void | ||
73 | end (void *cls) | ||
74 | { | ||
75 | if (NULL != zi) | ||
76 | { | ||
77 | GNUNET_NAMESTORE_zone_iteration_stop (zi); | ||
78 | zi = NULL; | ||
79 | } | ||
80 | if (nsh != NULL) | ||
81 | { | ||
82 | GNUNET_NAMESTORE_disconnect (nsh); | ||
83 | nsh = NULL; | ||
84 | } | ||
85 | GNUNET_free (s_name_1); | ||
86 | GNUNET_free (s_name_2); | ||
87 | GNUNET_free (s_name_3); | ||
88 | |||
89 | if (s_rd_1 != NULL) | ||
90 | { | ||
91 | GNUNET_free_nz ((void *) s_rd_1->data); | ||
92 | GNUNET_free (s_rd_1); | ||
93 | } | ||
94 | if (s_rd_2 != NULL) | ||
95 | { | ||
96 | GNUNET_free_nz ((void *) s_rd_2->data); | ||
97 | GNUNET_free (s_rd_2); | ||
98 | } | ||
99 | if (s_rd_3 != NULL) | ||
100 | { | ||
101 | GNUNET_free_nz ((void *) s_rd_3->data); | ||
102 | GNUNET_free (s_rd_3); | ||
103 | } | ||
104 | } | ||
105 | |||
106 | |||
107 | static int | ||
108 | check_zone_1 (const char *label, unsigned int rd_count, | ||
109 | const struct GNUNET_GNSRECORD_Data *rd) | ||
110 | { | ||
111 | for (unsigned int c = 0; c < rd_count; c++) | ||
112 | { | ||
113 | if ((rd[c].record_type == GNUNET_GNSRECORD_TYPE_NICK) && | ||
114 | (0 != strcmp (rd[c].data, ZONE_NICK_1))) | ||
115 | { | ||
116 | GNUNET_break (0); | ||
117 | return GNUNET_YES; | ||
118 | } | ||
119 | } | ||
120 | return GNUNET_NO; | ||
121 | } | ||
122 | |||
123 | |||
124 | static int | ||
125 | check_zone_2 (const char *label, | ||
126 | unsigned int rd_count, | ||
127 | const struct GNUNET_GNSRECORD_Data *rd) | ||
128 | { | ||
129 | for (unsigned int c = 0; c < rd_count; c++) | ||
130 | { | ||
131 | if ((rd[c].record_type == GNUNET_GNSRECORD_TYPE_NICK) && | ||
132 | (0 != strcmp (rd[c].data, ZONE_NICK_2))) | ||
133 | { | ||
134 | GNUNET_break (0); | ||
135 | return GNUNET_YES; | ||
136 | } | ||
137 | } | ||
138 | return GNUNET_NO; | ||
139 | } | ||
140 | |||
141 | |||
142 | static void | ||
143 | zone_proc_end (void *cls) | ||
144 | { | ||
145 | zi = NULL; | ||
146 | res = 0; | ||
147 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
148 | "Received last result, iteration done after receing %u results\n", | ||
149 | returned_records); | ||
150 | GNUNET_SCHEDULER_shutdown (); | ||
151 | } | ||
152 | |||
153 | |||
154 | static void | ||
155 | zone_proc (void *cls, | ||
156 | const struct GNUNET_IDENTITY_PrivateKey *zone, | ||
157 | const char *label, | ||
158 | unsigned int rd_count, | ||
159 | const struct GNUNET_GNSRECORD_Data *rd) | ||
160 | { | ||
161 | int failed = GNUNET_NO; | ||
162 | |||
163 | GNUNET_assert (NULL != zone); | ||
164 | if (0 == GNUNET_memcmp (zone, &privkey)) | ||
165 | { | ||
166 | failed = check_zone_1 (label, rd_count, rd); | ||
167 | if (GNUNET_YES == failed) | ||
168 | GNUNET_break (0); | ||
169 | } | ||
170 | else if (0 == GNUNET_memcmp (zone, &privkey2)) | ||
171 | { | ||
172 | failed = check_zone_2 (label, rd_count, rd); | ||
173 | if (GNUNET_YES == failed) | ||
174 | GNUNET_break (0); | ||
175 | } | ||
176 | else | ||
177 | { | ||
178 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
179 | "Received invalid zone\n"); | ||
180 | failed = GNUNET_YES; | ||
181 | GNUNET_break (0); | ||
182 | } | ||
183 | |||
184 | if (failed == GNUNET_NO) | ||
185 | { | ||
186 | returned_records++; | ||
187 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
188 | "Telling namestore to send the next result\n"); | ||
189 | GNUNET_NAMESTORE_zone_iterator_next (zi, | ||
190 | 1); | ||
191 | } | ||
192 | else | ||
193 | { | ||
194 | GNUNET_break (0); | ||
195 | res = 1; | ||
196 | GNUNET_SCHEDULER_shutdown (); | ||
197 | } | ||
198 | } | ||
199 | |||
200 | |||
201 | static void | ||
202 | fail_cb (void *cls) | ||
203 | { | ||
204 | GNUNET_assert (0); | ||
205 | } | ||
206 | |||
207 | |||
208 | static void | ||
209 | put_cont (void *cls, | ||
210 | int32_t success, | ||
211 | const char *emsg) | ||
212 | { | ||
213 | static int c = 0; | ||
214 | |||
215 | if (success == GNUNET_OK) | ||
216 | { | ||
217 | c++; | ||
218 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Created record %u \n", c); | ||
219 | } | ||
220 | else | ||
221 | { | ||
222 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Failed to created records: `%s'\n", | ||
223 | emsg); | ||
224 | GNUNET_break (0); | ||
225 | GNUNET_SCHEDULER_shutdown (); | ||
226 | return; | ||
227 | } | ||
228 | |||
229 | if (c == 3) | ||
230 | { | ||
231 | res = 1; | ||
232 | returned_records = 0; | ||
233 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
234 | "All records created, starting iteration over all zones \n"); | ||
235 | zi = GNUNET_NAMESTORE_zone_iteration_start (nsh, | ||
236 | NULL, | ||
237 | &fail_cb, | ||
238 | NULL, | ||
239 | &zone_proc, | ||
240 | NULL, | ||
241 | &zone_proc_end, | ||
242 | NULL); | ||
243 | if (zi == NULL) | ||
244 | { | ||
245 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Failed to create zone iterator\n"); | ||
246 | GNUNET_break (0); | ||
247 | GNUNET_SCHEDULER_shutdown (); | ||
248 | return; | ||
249 | } | ||
250 | } | ||
251 | } | ||
252 | |||
253 | |||
254 | static struct GNUNET_GNSRECORD_Data * | ||
255 | create_record (unsigned int count) | ||
256 | { | ||
257 | struct GNUNET_GNSRECORD_Data *rd; | ||
258 | |||
259 | rd = GNUNET_new_array (count, | ||
260 | struct GNUNET_GNSRECORD_Data); | ||
261 | for (unsigned int c = 0; c < count; c++) | ||
262 | { | ||
263 | rd[c].expiration_time = GNUNET_TIME_relative_to_absolute ( | ||
264 | GNUNET_TIME_UNIT_HOURS).abs_value_us; | ||
265 | rd[c].record_type = TEST_RECORD_TYPE; | ||
266 | rd[c].data_size = 50; | ||
267 | rd[c].data = GNUNET_malloc (50); | ||
268 | rd[c].flags = 0; | ||
269 | memset ((char *) rd[c].data, 'a', 50); | ||
270 | } | ||
271 | return rd; | ||
272 | } | ||
273 | |||
274 | |||
275 | static void | ||
276 | nick_2_cont (void *cls, | ||
277 | int32_t success, | ||
278 | const char *emsg) | ||
279 | { | ||
280 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
281 | "Nick added : %s\n", | ||
282 | (success == GNUNET_OK) ? "SUCCESS" : "FAIL"); | ||
283 | |||
284 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Created record 1\n"); | ||
285 | |||
286 | GNUNET_asprintf (&s_name_1, "dummy1"); | ||
287 | s_rd_1 = create_record (1); | ||
288 | GNUNET_NAMESTORE_records_store (nsh, &privkey, s_name_1, | ||
289 | 1, s_rd_1, | ||
290 | &put_cont, NULL); | ||
291 | |||
292 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
293 | "Created record 2 \n"); | ||
294 | GNUNET_asprintf (&s_name_2, "dummy2"); | ||
295 | s_rd_2 = create_record (1); | ||
296 | GNUNET_NAMESTORE_records_store (nsh, &privkey, s_name_2, | ||
297 | 1, s_rd_2, &put_cont, NULL); | ||
298 | |||
299 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
300 | "Created record 3\n"); | ||
301 | |||
302 | /* name in different zone */ | ||
303 | GNUNET_asprintf (&s_name_3, "dummy3"); | ||
304 | s_rd_3 = create_record (1); | ||
305 | GNUNET_NAMESTORE_records_store (nsh, &privkey2, s_name_3, | ||
306 | 1, s_rd_3, | ||
307 | &put_cont, NULL); | ||
308 | } | ||
309 | |||
310 | |||
311 | static void | ||
312 | nick_1_cont (void *cls, int32_t success, const char *emsg) | ||
313 | { | ||
314 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
315 | "Nick 1 added : %s\n", | ||
316 | (success == GNUNET_OK) ? "SUCCESS" : "FAIL"); | ||
317 | struct GNUNET_GNSRECORD_Data rd; | ||
318 | |||
319 | memset (&rd, 0, sizeof(rd)); | ||
320 | rd.data = ZONE_NICK_2; | ||
321 | rd.data_size = strlen (ZONE_NICK_2) + 1; | ||
322 | rd.record_type = GNUNET_GNSRECORD_TYPE_NICK; | ||
323 | rd.expiration_time = GNUNET_TIME_UNIT_FOREVER_ABS.abs_value_us; | ||
324 | rd.flags |= GNUNET_GNSRECORD_RF_PRIVATE; | ||
325 | nsqe = GNUNET_NAMESTORE_records_store (nsh, | ||
326 | &privkey2, | ||
327 | GNUNET_GNS_EMPTY_LABEL_AT, | ||
328 | 1, | ||
329 | &rd, | ||
330 | &nick_2_cont, | ||
331 | &privkey2); | ||
332 | |||
333 | if (NULL == nsqe) | ||
334 | { | ||
335 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
336 | _ ("Namestore cannot store no block\n")); | ||
337 | } | ||
338 | } | ||
339 | |||
340 | |||
341 | /** | ||
342 | * Callback called from the zone iterator when we iterate over | ||
343 | * the empty zone. Check that we got no records and then | ||
344 | * start the actual tests by filling the zone. | ||
345 | */ | ||
346 | static void | ||
347 | empty_zone_proc (void *cls, | ||
348 | const struct GNUNET_IDENTITY_PrivateKey *zone, | ||
349 | const char *label, | ||
350 | unsigned int rd_count, | ||
351 | const struct GNUNET_GNSRECORD_Data *rd) | ||
352 | { | ||
353 | GNUNET_assert (nsh == cls); | ||
354 | |||
355 | if (NULL != zone) | ||
356 | { | ||
357 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
358 | _ ("Expected empty zone but received zone private key\n")); | ||
359 | GNUNET_break (0); | ||
360 | GNUNET_SCHEDULER_shutdown (); | ||
361 | return; | ||
362 | } | ||
363 | if ((NULL != label) || (NULL != rd) || (0 != rd_count)) | ||
364 | { | ||
365 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
366 | _ ("Expected no zone content but received data\n")); | ||
367 | GNUNET_break (0); | ||
368 | GNUNET_SCHEDULER_shutdown (); | ||
369 | return; | ||
370 | } | ||
371 | GNUNET_assert (0); | ||
372 | } | ||
373 | |||
374 | |||
375 | static void | ||
376 | empty_zone_end (void *cls) | ||
377 | { | ||
378 | GNUNET_assert (nsh == cls); | ||
379 | struct GNUNET_GNSRECORD_Data rd; | ||
380 | |||
381 | zi = NULL; | ||
382 | privkey.type = htonl (GNUNET_GNSRECORD_TYPE_PKEY); | ||
383 | privkey2.type = htonl (GNUNET_GNSRECORD_TYPE_PKEY); | ||
384 | GNUNET_CRYPTO_ecdsa_key_create (&privkey.ecdsa_key); | ||
385 | GNUNET_CRYPTO_ecdsa_key_create (&privkey2.ecdsa_key); | ||
386 | |||
387 | memset (&rd, 0, sizeof(rd)); | ||
388 | rd.data = ZONE_NICK_1; | ||
389 | rd.data_size = strlen (ZONE_NICK_1) + 1; | ||
390 | rd.record_type = GNUNET_GNSRECORD_TYPE_NICK; | ||
391 | rd.expiration_time = GNUNET_TIME_UNIT_FOREVER_ABS.abs_value_us; | ||
392 | rd.flags |= GNUNET_GNSRECORD_RF_PRIVATE; | ||
393 | nsqe = GNUNET_NAMESTORE_records_store (nsh, | ||
394 | &privkey, | ||
395 | GNUNET_GNS_EMPTY_LABEL_AT, | ||
396 | 1, | ||
397 | &rd, | ||
398 | &nick_1_cont, | ||
399 | NULL); | ||
400 | if (NULL == nsqe) | ||
401 | { | ||
402 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
403 | _ ("Namestore cannot store no block\n")); | ||
404 | } | ||
405 | } | ||
406 | |||
407 | |||
408 | static void | ||
409 | run (void *cls, | ||
410 | const struct GNUNET_CONFIGURATION_Handle *cfg, | ||
411 | struct GNUNET_TESTING_Peer *peer) | ||
412 | { | ||
413 | nsh = GNUNET_NAMESTORE_connect (cfg); | ||
414 | GNUNET_break (NULL != nsh); | ||
415 | GNUNET_SCHEDULER_add_shutdown (&end, | ||
416 | NULL); | ||
417 | /* first, iterate over empty namestore */ | ||
418 | zi = GNUNET_NAMESTORE_zone_iteration_start (nsh, | ||
419 | NULL, | ||
420 | &fail_cb, | ||
421 | NULL, | ||
422 | &empty_zone_proc, | ||
423 | nsh, | ||
424 | &empty_zone_end, | ||
425 | nsh); | ||
426 | if (NULL == zi) | ||
427 | { | ||
428 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
429 | "Failed to create zone iterator\n"); | ||
430 | GNUNET_break (0); | ||
431 | GNUNET_SCHEDULER_shutdown (); | ||
432 | } | ||
433 | } | ||
434 | |||
435 | |||
436 | #include "test_common.c" | ||
437 | |||
438 | |||
439 | int | ||
440 | main (int argc, char *argv[]) | ||
441 | { | ||
442 | const char *plugin_name; | ||
443 | char *cfg_name; | ||
444 | |||
445 | SETUP_CFG (plugin_name, cfg_name); | ||
446 | res = 1; | ||
447 | if (0 != | ||
448 | GNUNET_TESTING_peer_run ("test-namestore-api-zone-iteration-nick", | ||
449 | cfg_name, | ||
450 | &run, | ||
451 | NULL)) | ||
452 | { | ||
453 | res = 1; | ||
454 | } | ||
455 | GNUNET_DISK_purge_cfg_dir (cfg_name, | ||
456 | "GNUNET_TEST_HOME"); | ||
457 | GNUNET_free (cfg_name); | ||
458 | return res; | ||
459 | } | ||
460 | |||
461 | |||
462 | /* end of test_namestore_api_zone_iteration.c */ | ||
diff --git a/src/namestore/test_namestore_api_zone_iteration_specific_zone.c b/src/namestore/test_namestore_api_zone_iteration_specific_zone.c deleted file mode 100644 index 70097a69e..000000000 --- a/src/namestore/test_namestore_api_zone_iteration_specific_zone.c +++ /dev/null | |||
@@ -1,448 +0,0 @@ | |||
1 | /* | ||
2 | This file is part of GNUnet. | ||
3 | Copyright (C) 2013 GNUnet e.V. | ||
4 | |||
5 | GNUnet is free software: you can redistribute it and/or modify it | ||
6 | under the terms of the GNU Affero General Public License as published | ||
7 | by the Free Software Foundation, either version 3 of the License, | ||
8 | or (at your option) any later version. | ||
9 | |||
10 | GNUnet is distributed in the hope that it will be useful, but | ||
11 | WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
13 | Affero General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU Affero General Public License | ||
16 | along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
17 | |||
18 | SPDX-License-Identifier: AGPL3.0-or-later | ||
19 | */ | ||
20 | /** | ||
21 | * @file namestore/test_namestore_api_zone_iteration_specific_zone.c | ||
22 | * @brief testcase for zone iteration functionality: iterate over a specific zone | ||
23 | * @author Matthias Wachs | ||
24 | */ | ||
25 | #include "platform.h" | ||
26 | #include "gnunet_namestore_service.h" | ||
27 | #include "gnunet_testing_lib.h" | ||
28 | #include "namestore.h" | ||
29 | #include "gnunet_dnsparser_lib.h" | ||
30 | |||
31 | #define TEST_RECORD_TYPE GNUNET_DNSPARSER_TYPE_TXT | ||
32 | |||
33 | |||
34 | #define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 100) | ||
35 | |||
36 | |||
37 | static struct GNUNET_NAMESTORE_Handle *nsh; | ||
38 | |||
39 | static struct GNUNET_SCHEDULER_Task *endbadly_task; | ||
40 | |||
41 | static struct GNUNET_IDENTITY_PrivateKey privkey; | ||
42 | |||
43 | static struct GNUNET_IDENTITY_PrivateKey privkey2; | ||
44 | |||
45 | static struct GNUNET_NAMESTORE_ZoneIterator *zi; | ||
46 | |||
47 | static int res; | ||
48 | |||
49 | static int returned_records; | ||
50 | |||
51 | static char *s_name_1; | ||
52 | |||
53 | static struct GNUNET_GNSRECORD_Data *s_rd_1; | ||
54 | |||
55 | static char *s_name_2; | ||
56 | |||
57 | static struct GNUNET_GNSRECORD_Data *s_rd_2; | ||
58 | |||
59 | static char *s_name_3; | ||
60 | |||
61 | static struct GNUNET_GNSRECORD_Data *s_rd_3; | ||
62 | |||
63 | |||
64 | /** | ||
65 | * Handle timeout. | ||
66 | * | ||
67 | * @param cls handle to use to re-connect. | ||
68 | */ | ||
69 | static void | ||
70 | endbadly (void *cls) | ||
71 | { | ||
72 | endbadly_task = NULL; | ||
73 | GNUNET_SCHEDULER_shutdown (); | ||
74 | res = 1; | ||
75 | } | ||
76 | |||
77 | |||
78 | static void | ||
79 | end (void *cls) | ||
80 | { | ||
81 | if (NULL != zi) | ||
82 | { | ||
83 | GNUNET_NAMESTORE_zone_iteration_stop (zi); | ||
84 | zi = NULL; | ||
85 | } | ||
86 | if (NULL != endbadly_task) | ||
87 | { | ||
88 | GNUNET_SCHEDULER_cancel (endbadly_task); | ||
89 | endbadly_task = NULL; | ||
90 | } | ||
91 | GNUNET_free (s_name_1); | ||
92 | GNUNET_free (s_name_2); | ||
93 | GNUNET_free (s_name_3); | ||
94 | if (s_rd_1 != NULL) | ||
95 | { | ||
96 | GNUNET_free_nz ((void *) s_rd_1->data); | ||
97 | GNUNET_free (s_rd_1); | ||
98 | } | ||
99 | if (s_rd_2 != NULL) | ||
100 | { | ||
101 | GNUNET_free_nz ((void *) s_rd_2->data); | ||
102 | GNUNET_free (s_rd_2); | ||
103 | } | ||
104 | if (s_rd_3 != NULL) | ||
105 | { | ||
106 | GNUNET_free_nz ((void *) s_rd_3->data); | ||
107 | GNUNET_free (s_rd_3); | ||
108 | } | ||
109 | if (nsh != NULL) | ||
110 | { | ||
111 | GNUNET_NAMESTORE_disconnect (nsh); | ||
112 | nsh = NULL; | ||
113 | } | ||
114 | } | ||
115 | |||
116 | |||
117 | static void | ||
118 | fail_cb (void *cls) | ||
119 | { | ||
120 | GNUNET_assert (0); | ||
121 | zi = NULL; | ||
122 | } | ||
123 | |||
124 | |||
125 | static void | ||
126 | zone_proc (void *cls, | ||
127 | const struct GNUNET_IDENTITY_PrivateKey *zone, | ||
128 | const char *label, | ||
129 | unsigned int rd_count, | ||
130 | const struct GNUNET_GNSRECORD_Data *rd) | ||
131 | { | ||
132 | int failed = GNUNET_NO; | ||
133 | |||
134 | GNUNET_assert (NULL != zone); | ||
135 | if (0 == GNUNET_memcmp (zone, | ||
136 | &privkey)) | ||
137 | { | ||
138 | if (0 == strcmp (label, s_name_1)) | ||
139 | { | ||
140 | if (rd_count == 1) | ||
141 | { | ||
142 | if (GNUNET_YES != GNUNET_GNSRECORD_records_cmp (rd, s_rd_1)) | ||
143 | { | ||
144 | failed = GNUNET_YES; | ||
145 | GNUNET_break (0); | ||
146 | } | ||
147 | } | ||
148 | else | ||
149 | { | ||
150 | failed = GNUNET_YES; | ||
151 | GNUNET_break (0); | ||
152 | } | ||
153 | } | ||
154 | else if (0 == strcmp (label, s_name_2)) | ||
155 | { | ||
156 | if (rd_count == 1) | ||
157 | { | ||
158 | if (GNUNET_YES != GNUNET_GNSRECORD_records_cmp (rd, s_rd_2)) | ||
159 | { | ||
160 | failed = GNUNET_YES; | ||
161 | GNUNET_break (0); | ||
162 | } | ||
163 | } | ||
164 | else | ||
165 | { | ||
166 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
167 | "Received invalid record count\n"); | ||
168 | failed = GNUNET_YES; | ||
169 | GNUNET_break (0); | ||
170 | } | ||
171 | } | ||
172 | else | ||
173 | { | ||
174 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
175 | "Comparing result failed: got name `%s' for first zone\n", | ||
176 | label); | ||
177 | failed = GNUNET_YES; | ||
178 | GNUNET_break (0); | ||
179 | } | ||
180 | } | ||
181 | else if (0 == GNUNET_memcmp (zone, &privkey2)) | ||
182 | { | ||
183 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
184 | "Received data for not requested zone\n"); | ||
185 | failed = GNUNET_YES; | ||
186 | GNUNET_break (0); | ||
187 | } | ||
188 | else | ||
189 | { | ||
190 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
191 | "Received invalid zone\n"); | ||
192 | failed = GNUNET_YES; | ||
193 | GNUNET_break (0); | ||
194 | } | ||
195 | if (failed == GNUNET_NO) | ||
196 | { | ||
197 | returned_records++; | ||
198 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
199 | "Telling namestore to send the next result\n"); | ||
200 | GNUNET_NAMESTORE_zone_iterator_next (zi, | ||
201 | 1); | ||
202 | } | ||
203 | else | ||
204 | { | ||
205 | GNUNET_break (0); | ||
206 | res = 2; | ||
207 | GNUNET_SCHEDULER_shutdown (); | ||
208 | } | ||
209 | } | ||
210 | |||
211 | |||
212 | static void | ||
213 | zone_proc_end (void *cls) | ||
214 | { | ||
215 | zi = NULL; | ||
216 | GNUNET_break (2 == returned_records); | ||
217 | if (2 == returned_records) | ||
218 | { | ||
219 | res = 0; /* Last iteraterator callback, we are done */ | ||
220 | } | ||
221 | else | ||
222 | { | ||
223 | res = 1; | ||
224 | } | ||
225 | |||
226 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
227 | "Received last result, iteration done after receing %u results\n", | ||
228 | returned_records); | ||
229 | GNUNET_SCHEDULER_shutdown (); | ||
230 | } | ||
231 | |||
232 | |||
233 | static void | ||
234 | put_cont (void *cls, | ||
235 | int32_t success, | ||
236 | const char *emsg) | ||
237 | { | ||
238 | static int c = 0; | ||
239 | |||
240 | if (success == GNUNET_OK) | ||
241 | { | ||
242 | c++; | ||
243 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
244 | "Created record %u \n", c); | ||
245 | } | ||
246 | else | ||
247 | { | ||
248 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
249 | "Failed to created records: `%s'\n", | ||
250 | emsg); | ||
251 | GNUNET_break (0); | ||
252 | res = 2; | ||
253 | GNUNET_SCHEDULER_shutdown (); | ||
254 | return; | ||
255 | } | ||
256 | |||
257 | if (c == 3) | ||
258 | { | ||
259 | res = 1; | ||
260 | returned_records = 0; | ||
261 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
262 | "All records created, starting iteration over all zones \n"); | ||
263 | zi = GNUNET_NAMESTORE_zone_iteration_start (nsh, | ||
264 | &privkey, | ||
265 | &fail_cb, | ||
266 | NULL, | ||
267 | &zone_proc, | ||
268 | NULL, | ||
269 | &zone_proc_end, | ||
270 | NULL); | ||
271 | if (zi == NULL) | ||
272 | { | ||
273 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
274 | "Failed to create zone iterator\n"); | ||
275 | GNUNET_break (0); | ||
276 | res = 2; | ||
277 | GNUNET_SCHEDULER_shutdown (); | ||
278 | return; | ||
279 | } | ||
280 | } | ||
281 | } | ||
282 | |||
283 | |||
284 | static struct GNUNET_GNSRECORD_Data * | ||
285 | create_record (unsigned int count) | ||
286 | { | ||
287 | struct GNUNET_GNSRECORD_Data *rd; | ||
288 | |||
289 | rd = GNUNET_new_array (count, | ||
290 | struct GNUNET_GNSRECORD_Data); | ||
291 | for (unsigned int c = 0; c < count; c++) | ||
292 | { | ||
293 | rd[c].expiration_time = GNUNET_TIME_relative_to_absolute ( | ||
294 | GNUNET_TIME_UNIT_HOURS).abs_value_us; | ||
295 | rd[c].record_type = TEST_RECORD_TYPE; | ||
296 | rd[c].data_size = 50; | ||
297 | rd[c].data = GNUNET_malloc (50); | ||
298 | rd[c].flags = 0; | ||
299 | memset ((char *) rd[c].data, 'a', 50); | ||
300 | } | ||
301 | return rd; | ||
302 | } | ||
303 | |||
304 | |||
305 | /** | ||
306 | * Callback called from the zone iterator when we iterate over | ||
307 | * the empty zone. Check that we got no records and then | ||
308 | * start the actual tests by filling the zone. | ||
309 | */ | ||
310 | static void | ||
311 | empty_zone_proc (void *cls, | ||
312 | const struct GNUNET_IDENTITY_PrivateKey *zone, | ||
313 | const char *label, | ||
314 | unsigned int rd_count, | ||
315 | const struct GNUNET_GNSRECORD_Data *rd) | ||
316 | { | ||
317 | GNUNET_assert (nsh == cls); | ||
318 | if (NULL != zone) | ||
319 | { | ||
320 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
321 | _ ("Expected empty zone but received zone private key\n")); | ||
322 | GNUNET_break (0); | ||
323 | res = 2; | ||
324 | GNUNET_SCHEDULER_shutdown (); | ||
325 | return; | ||
326 | } | ||
327 | if ((NULL != label) || (NULL != rd) || (0 != rd_count)) | ||
328 | { | ||
329 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
330 | _ ("Expected no zone content but received data\n")); | ||
331 | GNUNET_break (0); | ||
332 | res = 2; | ||
333 | GNUNET_SCHEDULER_shutdown (); | ||
334 | return; | ||
335 | } | ||
336 | GNUNET_assert (0); | ||
337 | } | ||
338 | |||
339 | |||
340 | static void | ||
341 | empty_zone_proc_end (void *cls) | ||
342 | { | ||
343 | zi = NULL; | ||
344 | privkey.type = htonl (GNUNET_GNSRECORD_TYPE_PKEY); | ||
345 | privkey2.type = htonl (GNUNET_GNSRECORD_TYPE_PKEY); | ||
346 | GNUNET_CRYPTO_ecdsa_key_create (&privkey.ecdsa_key); | ||
347 | GNUNET_CRYPTO_ecdsa_key_create (&privkey2.ecdsa_key); | ||
348 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
349 | "Created record 1\n"); | ||
350 | GNUNET_asprintf (&s_name_1, | ||
351 | "dummy1"); | ||
352 | s_rd_1 = create_record (1); | ||
353 | GNUNET_NAMESTORE_records_store (nsh, | ||
354 | &privkey, | ||
355 | s_name_1, | ||
356 | 1, | ||
357 | s_rd_1, | ||
358 | &put_cont, | ||
359 | NULL); | ||
360 | |||
361 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
362 | "Created record 2 \n"); | ||
363 | GNUNET_asprintf (&s_name_2, | ||
364 | "dummy2"); | ||
365 | s_rd_2 = create_record (1); | ||
366 | GNUNET_NAMESTORE_records_store (nsh, | ||
367 | &privkey, | ||
368 | s_name_2, | ||
369 | 1, | ||
370 | s_rd_2, | ||
371 | &put_cont, | ||
372 | NULL); | ||
373 | |||
374 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
375 | "Created record 3\n"); | ||
376 | |||
377 | /* name in different zone */ | ||
378 | GNUNET_asprintf (&s_name_3, | ||
379 | "dummy3"); | ||
380 | s_rd_3 = create_record (1); | ||
381 | GNUNET_NAMESTORE_records_store (nsh, | ||
382 | &privkey2, | ||
383 | s_name_3, | ||
384 | 1, s_rd_3, | ||
385 | &put_cont, | ||
386 | NULL); | ||
387 | } | ||
388 | |||
389 | |||
390 | static void | ||
391 | run (void *cls, | ||
392 | const struct GNUNET_CONFIGURATION_Handle *cfg, | ||
393 | struct GNUNET_TESTING_Peer *peer) | ||
394 | { | ||
395 | GNUNET_SCHEDULER_add_shutdown (&end, | ||
396 | NULL); | ||
397 | endbadly_task = GNUNET_SCHEDULER_add_delayed (TIMEOUT, | ||
398 | &endbadly, | ||
399 | NULL); | ||
400 | nsh = GNUNET_NAMESTORE_connect (cfg); | ||
401 | GNUNET_break (NULL != nsh); | ||
402 | /* first, iterate over empty namestore */ | ||
403 | zi = GNUNET_NAMESTORE_zone_iteration_start (nsh, | ||
404 | NULL, | ||
405 | &fail_cb, | ||
406 | NULL, | ||
407 | &empty_zone_proc, | ||
408 | nsh, | ||
409 | &empty_zone_proc_end, | ||
410 | nsh); | ||
411 | if (NULL == zi) | ||
412 | { | ||
413 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
414 | "Failed to create zone iterator\n"); | ||
415 | GNUNET_break (0); | ||
416 | GNUNET_SCHEDULER_shutdown (); | ||
417 | } | ||
418 | } | ||
419 | |||
420 | |||
421 | #include "test_common.c" | ||
422 | |||
423 | |||
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 ( | ||
434 | "test-namestore-api-zone-iteration-specific-zone", | ||
435 | cfg_name, | ||
436 | &run, | ||
437 | NULL)) | ||
438 | { | ||
439 | res = 1; | ||
440 | } | ||
441 | GNUNET_DISK_purge_cfg_dir (cfg_name, | ||
442 | "GNUNET_TEST_HOME"); | ||
443 | GNUNET_free (cfg_name); | ||
444 | return res; | ||
445 | } | ||
446 | |||
447 | |||
448 | /* end of test_namestore_api_zone_iteration_specific_zone.c */ | ||
diff --git a/src/namestore/test_namestore_api_zone_iteration_stop.c b/src/namestore/test_namestore_api_zone_iteration_stop.c deleted file mode 100644 index 71b36ba09..000000000 --- a/src/namestore/test_namestore_api_zone_iteration_stop.c +++ /dev/null | |||
@@ -1,449 +0,0 @@ | |||
1 | /* | ||
2 | This file is part of GNUnet. | ||
3 | Copyright (C) 2009 GNUnet e.V. | ||
4 | |||
5 | GNUnet is free software: you can redistribute it and/or modify it | ||
6 | under the terms of the GNU Affero General Public License as published | ||
7 | by the Free Software Foundation, either version 3 of the License, | ||
8 | or (at your option) any later version. | ||
9 | |||
10 | GNUnet is distributed in the hope that it will be useful, but | ||
11 | WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
13 | Affero General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU Affero General Public License | ||
16 | along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
17 | |||
18 | SPDX-License-Identifier: AGPL3.0-or-later | ||
19 | */ | ||
20 | /** | ||
21 | * @file namestore/test_namestore_api_zone_iteration_stop.c | ||
22 | * @brief testcase for zone iteration functionality: stop iterating of zones | ||
23 | */ | ||
24 | #include "platform.h" | ||
25 | #include "gnunet_namestore_service.h" | ||
26 | #include "gnunet_testing_lib.h" | ||
27 | #include "namestore.h" | ||
28 | #include "gnunet_dnsparser_lib.h" | ||
29 | |||
30 | #define TEST_RECORD_TYPE GNUNET_DNSPARSER_TYPE_TXT | ||
31 | |||
32 | #define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 100) | ||
33 | #define WAIT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 2) | ||
34 | |||
35 | static struct GNUNET_NAMESTORE_Handle *nsh; | ||
36 | |||
37 | static struct GNUNET_IDENTITY_PrivateKey privkey; | ||
38 | |||
39 | static struct GNUNET_IDENTITY_PrivateKey privkey2; | ||
40 | |||
41 | static struct GNUNET_NAMESTORE_ZoneIterator *zi; | ||
42 | |||
43 | static int res; | ||
44 | |||
45 | static int returned_records; | ||
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 | |||
60 | /** | ||
61 | * Re-establish the connection to the service. | ||
62 | * | ||
63 | * @param cls handle to use to re-connect. | ||
64 | */ | ||
65 | static void | ||
66 | end (void *cls) | ||
67 | { | ||
68 | if (NULL != zi) | ||
69 | { | ||
70 | GNUNET_NAMESTORE_zone_iteration_stop (zi); | ||
71 | zi = NULL; | ||
72 | } | ||
73 | if (nsh != NULL) | ||
74 | { | ||
75 | GNUNET_NAMESTORE_disconnect (nsh); | ||
76 | nsh = NULL; | ||
77 | } | ||
78 | GNUNET_free (s_name_1); | ||
79 | GNUNET_free (s_name_2); | ||
80 | GNUNET_free (s_name_3); | ||
81 | if (s_rd_1 != NULL) | ||
82 | { | ||
83 | GNUNET_free_nz ((void *) s_rd_1->data); | ||
84 | GNUNET_free (s_rd_1); | ||
85 | } | ||
86 | if (s_rd_2 != NULL) | ||
87 | { | ||
88 | GNUNET_free_nz ((void *) s_rd_2->data); | ||
89 | GNUNET_free (s_rd_2); | ||
90 | } | ||
91 | if (s_rd_3 != NULL) | ||
92 | { | ||
93 | GNUNET_free_nz ((void *) s_rd_3->data); | ||
94 | GNUNET_free (s_rd_3); | ||
95 | } | ||
96 | } | ||
97 | |||
98 | |||
99 | static void | ||
100 | delayed_end (void *cls) | ||
101 | { | ||
102 | GNUNET_SCHEDULER_shutdown (); | ||
103 | } | ||
104 | |||
105 | |||
106 | static void | ||
107 | fail_cb (void *cls) | ||
108 | { | ||
109 | GNUNET_assert (0); | ||
110 | } | ||
111 | |||
112 | |||
113 | static void | ||
114 | zone_proc (void *cls, | ||
115 | const struct GNUNET_IDENTITY_PrivateKey *zone, | ||
116 | const char *label, | ||
117 | unsigned int rd_count, | ||
118 | const struct GNUNET_GNSRECORD_Data *rd) | ||
119 | { | ||
120 | int failed = GNUNET_NO; | ||
121 | |||
122 | GNUNET_assert (NULL != zone); | ||
123 | if (0 == GNUNET_memcmp (zone, &privkey)) | ||
124 | { | ||
125 | if (0 == strcmp (label, s_name_1)) | ||
126 | { | ||
127 | if (rd_count == 1) | ||
128 | { | ||
129 | if (GNUNET_YES != GNUNET_GNSRECORD_records_cmp (rd, s_rd_1)) | ||
130 | { | ||
131 | failed = GNUNET_YES; | ||
132 | GNUNET_break (0); | ||
133 | } | ||
134 | } | ||
135 | else | ||
136 | { | ||
137 | failed = GNUNET_YES; | ||
138 | GNUNET_break (0); | ||
139 | } | ||
140 | } | ||
141 | else if (0 == strcmp (label, s_name_2)) | ||
142 | { | ||
143 | if (rd_count == 1) | ||
144 | { | ||
145 | if (GNUNET_YES != GNUNET_GNSRECORD_records_cmp (rd, s_rd_2)) | ||
146 | { | ||
147 | failed = GNUNET_YES; | ||
148 | GNUNET_break (0); | ||
149 | } | ||
150 | } | ||
151 | else | ||
152 | { | ||
153 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
154 | "Received invalid record count\n"); | ||
155 | failed = GNUNET_YES; | ||
156 | GNUNET_break (0); | ||
157 | } | ||
158 | } | ||
159 | else | ||
160 | { | ||
161 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
162 | "Comparing result failed: got name `%s' for first zone\n", | ||
163 | label); | ||
164 | failed = GNUNET_YES; | ||
165 | GNUNET_break (0); | ||
166 | } | ||
167 | } | ||
168 | else if (0 == GNUNET_memcmp (zone, &privkey2)) | ||
169 | { | ||
170 | if (0 == strcmp (label, s_name_3)) | ||
171 | { | ||
172 | if (rd_count == 1) | ||
173 | { | ||
174 | if (GNUNET_YES != GNUNET_GNSRECORD_records_cmp (rd, s_rd_3)) | ||
175 | { | ||
176 | failed = GNUNET_YES; | ||
177 | GNUNET_break (0); | ||
178 | } | ||
179 | } | ||
180 | else | ||
181 | { | ||
182 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
183 | "Received invalid record count\n"); | ||
184 | failed = GNUNET_YES; | ||
185 | GNUNET_break (0); | ||
186 | } | ||
187 | } | ||
188 | else | ||
189 | { | ||
190 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
191 | "Comparing result failed: got name `%s' for first zone\n", | ||
192 | label); | ||
193 | failed = GNUNET_YES; | ||
194 | GNUNET_break (0); | ||
195 | } | ||
196 | } | ||
197 | else | ||
198 | { | ||
199 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
200 | "Received invalid zone\n"); | ||
201 | failed = GNUNET_YES; | ||
202 | GNUNET_break (0); | ||
203 | } | ||
204 | if (failed == GNUNET_NO) | ||
205 | { | ||
206 | if (1 == returned_records) | ||
207 | { | ||
208 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
209 | "Telling namestore to stop zone iteration\n"); | ||
210 | GNUNET_NAMESTORE_zone_iteration_stop (zi); | ||
211 | zi = NULL; | ||
212 | res = 0; | ||
213 | GNUNET_SCHEDULER_add_delayed (WAIT, | ||
214 | &delayed_end, | ||
215 | NULL); | ||
216 | return; | ||
217 | } | ||
218 | returned_records++; | ||
219 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
220 | "Telling namestore to send the next result\n"); | ||
221 | GNUNET_NAMESTORE_zone_iterator_next (zi, | ||
222 | 1); | ||
223 | } | ||
224 | else | ||
225 | { | ||
226 | GNUNET_break (0); | ||
227 | GNUNET_SCHEDULER_shutdown (); | ||
228 | } | ||
229 | } | ||
230 | |||
231 | |||
232 | static void | ||
233 | zone_proc_end (void *cls) | ||
234 | { | ||
235 | GNUNET_break (1 <= returned_records); | ||
236 | if (1 >= returned_records) | ||
237 | res = 1; /* Last iteraterator callback, we are done */ | ||
238 | else | ||
239 | res = 0; | ||
240 | zi = NULL; | ||
241 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
242 | "Received last result, iteration done after receing %u results\n", | ||
243 | returned_records); | ||
244 | GNUNET_SCHEDULER_add_now (&end, NULL); | ||
245 | } | ||
246 | |||
247 | |||
248 | static void | ||
249 | put_cont (void *cls, int32_t success, const char *emsg) | ||
250 | { | ||
251 | static int c = 0; | ||
252 | |||
253 | if (success == GNUNET_OK) | ||
254 | { | ||
255 | c++; | ||
256 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Created record %u \n", c); | ||
257 | } | ||
258 | else | ||
259 | { | ||
260 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Failed to created records: `%s'\n", | ||
261 | emsg); | ||
262 | GNUNET_break (0); | ||
263 | GNUNET_SCHEDULER_shutdown (); | ||
264 | return; | ||
265 | } | ||
266 | |||
267 | if (c == 3) | ||
268 | { | ||
269 | res = 1; | ||
270 | returned_records = 0; | ||
271 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
272 | "All records created, starting iteration over all zones \n"); | ||
273 | zi = GNUNET_NAMESTORE_zone_iteration_start (nsh, | ||
274 | NULL, | ||
275 | &fail_cb, | ||
276 | NULL, | ||
277 | &zone_proc, | ||
278 | NULL, | ||
279 | &zone_proc_end, | ||
280 | NULL); | ||
281 | if (zi == NULL) | ||
282 | { | ||
283 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
284 | "Failed to create zone iterator\n"); | ||
285 | GNUNET_break (0); | ||
286 | GNUNET_SCHEDULER_shutdown (); | ||
287 | return; | ||
288 | } | ||
289 | } | ||
290 | } | ||
291 | |||
292 | |||
293 | static struct GNUNET_GNSRECORD_Data * | ||
294 | create_record (unsigned int count) | ||
295 | { | ||
296 | struct GNUNET_GNSRECORD_Data *rd; | ||
297 | |||
298 | rd = GNUNET_new_array (count, | ||
299 | struct GNUNET_GNSRECORD_Data); | ||
300 | for (unsigned int c = 0; c < count; c++) | ||
301 | { | ||
302 | rd[c].expiration_time = GNUNET_TIME_relative_to_absolute ( | ||
303 | GNUNET_TIME_UNIT_HOURS).abs_value_us; | ||
304 | rd[c].record_type = TEST_RECORD_TYPE; | ||
305 | rd[c].data_size = 50; | ||
306 | rd[c].data = GNUNET_malloc (50); | ||
307 | rd[c].flags = 0; | ||
308 | memset ((char *) rd[c].data, 'a', 50); | ||
309 | } | ||
310 | return rd; | ||
311 | } | ||
312 | |||
313 | |||
314 | /** | ||
315 | * Callback called from the zone iterator when we iterate over | ||
316 | * the empty zone. Check that we got no records and then | ||
317 | * start the actual tests by filling the zone. | ||
318 | */ | ||
319 | static void | ||
320 | empty_zone_proc (void *cls, | ||
321 | const struct GNUNET_IDENTITY_PrivateKey *zone, | ||
322 | const char *label, | ||
323 | unsigned int rd_count, | ||
324 | const struct GNUNET_GNSRECORD_Data *rd) | ||
325 | { | ||
326 | GNUNET_assert (nsh == cls); | ||
327 | if (NULL != zone) | ||
328 | { | ||
329 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
330 | _ ("Expected empty zone but received zone private key\n")); | ||
331 | GNUNET_break (0); | ||
332 | GNUNET_SCHEDULER_shutdown (); | ||
333 | return; | ||
334 | } | ||
335 | if ((NULL != label) || (NULL != rd) || (0 != rd_count)) | ||
336 | { | ||
337 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
338 | _ ("Expected no zone content but received data\n")); | ||
339 | GNUNET_break (0); | ||
340 | GNUNET_SCHEDULER_shutdown (); | ||
341 | return; | ||
342 | } | ||
343 | GNUNET_assert (0); | ||
344 | } | ||
345 | |||
346 | |||
347 | static void | ||
348 | empty_zone_proc_end (void *cls) | ||
349 | { | ||
350 | GNUNET_assert (nsh == cls); | ||
351 | zi = NULL; | ||
352 | privkey.type = htonl (GNUNET_GNSRECORD_TYPE_PKEY); | ||
353 | privkey2.type = htonl (GNUNET_GNSRECORD_TYPE_PKEY); | ||
354 | GNUNET_CRYPTO_ecdsa_key_create (&privkey.ecdsa_key); | ||
355 | GNUNET_CRYPTO_ecdsa_key_create (&privkey2.ecdsa_key); | ||
356 | |||
357 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
358 | "Created record 1\n"); | ||
359 | |||
360 | GNUNET_asprintf (&s_name_1, | ||
361 | "dummy1"); | ||
362 | s_rd_1 = create_record (1); | ||
363 | GNUNET_NAMESTORE_records_store (nsh, | ||
364 | &privkey, s_name_1, | ||
365 | 1, s_rd_1, &put_cont, NULL); | ||
366 | |||
367 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
368 | "Created record 2 \n"); | ||
369 | GNUNET_asprintf (&s_name_2, | ||
370 | "dummy2"); | ||
371 | s_rd_2 = create_record (1); | ||
372 | GNUNET_NAMESTORE_records_store (nsh, | ||
373 | &privkey, | ||
374 | s_name_2, | ||
375 | 1, | ||
376 | s_rd_2, | ||
377 | &put_cont, NULL); | ||
378 | |||
379 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
380 | "Created record 3\n"); | ||
381 | |||
382 | /* name in different zone */ | ||
383 | GNUNET_asprintf (&s_name_3, "dummy3"); | ||
384 | s_rd_3 = create_record (1); | ||
385 | GNUNET_NAMESTORE_records_store (nsh, | ||
386 | &privkey2, | ||
387 | s_name_3, | ||
388 | 1, | ||
389 | s_rd_3, | ||
390 | &put_cont, NULL); | ||
391 | } | ||
392 | |||
393 | |||
394 | static void | ||
395 | run (void *cls, | ||
396 | const struct GNUNET_CONFIGURATION_Handle *cfg, | ||
397 | struct GNUNET_TESTING_Peer *peer) | ||
398 | { | ||
399 | nsh = GNUNET_NAMESTORE_connect (cfg); | ||
400 | GNUNET_break (NULL != nsh); | ||
401 | GNUNET_SCHEDULER_add_shutdown (&end, | ||
402 | NULL); | ||
403 | /* first, iterate over empty namestore */ | ||
404 | zi = GNUNET_NAMESTORE_zone_iteration_start (nsh, | ||
405 | NULL, | ||
406 | &fail_cb, | ||
407 | NULL, | ||
408 | &empty_zone_proc, | ||
409 | nsh, | ||
410 | &empty_zone_proc_end, | ||
411 | nsh); | ||
412 | if (NULL == zi) | ||
413 | { | ||
414 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
415 | "Failed to create zone iterator\n"); | ||
416 | GNUNET_break (0); | ||
417 | GNUNET_SCHEDULER_shutdown (); | ||
418 | } | ||
419 | } | ||
420 | |||
421 | |||
422 | #include "test_common.c" | ||
423 | |||
424 | |||
425 | int | ||
426 | main (int argc, char *argv[]) | ||
427 | { | ||
428 | const char *plugin_name; | ||
429 | char *cfg_name; | ||
430 | |||
431 | SETUP_CFG (plugin_name, cfg_name); | ||
432 | res = 1; | ||
433 | if (0 != | ||
434 | GNUNET_TESTING_peer_run ("test-namestore-api-zone-iteration-stop", | ||
435 | cfg_name, | ||
436 | &run, | ||
437 | NULL)) | ||
438 | { | ||
439 | res = 1; | ||
440 | } | ||
441 | GNUNET_DISK_purge_cfg_dir (cfg_name, | ||
442 | "GNUNET_TEST_HOME"); | ||
443 | GNUNET_free (cfg_name); | ||
444 | |||
445 | return res; | ||
446 | } | ||
447 | |||
448 | |||
449 | /* end of test_namestore_api_zone_iteration_stop.c */ | ||
diff --git a/src/namestore/test_namestore_api_zone_to_name.c b/src/namestore/test_namestore_api_zone_to_name.c deleted file mode 100644 index 3fd10e4a1..000000000 --- a/src/namestore/test_namestore_api_zone_to_name.c +++ /dev/null | |||
@@ -1,266 +0,0 @@ | |||
1 | /* | ||
2 | This file is part of GNUnet. | ||
3 | Copyright (C) 2009 GNUnet e.V. | ||
4 | |||
5 | GNUnet is free software: you can redistribute it and/or modify it | ||
6 | under the terms of the GNU Affero General Public License as published | ||
7 | by the Free Software Foundation, either version 3 of the License, | ||
8 | or (at your option) any later version. | ||
9 | |||
10 | GNUnet is distributed in the hope that it will be useful, but | ||
11 | WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
13 | Affero General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU Affero General Public License | ||
16 | along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
17 | |||
18 | SPDX-License-Identifier: AGPL3.0-or-later | ||
19 | */ | ||
20 | /** | ||
21 | * @file namestore/test_namestore_api_zone_to_name.c | ||
22 | * @brief testcase for zone to name translation | ||
23 | */ | ||
24 | #include "platform.h" | ||
25 | #include "gnunet_namestore_service.h" | ||
26 | #include "gnunet_testing_lib.h" | ||
27 | #include "namestore.h" | ||
28 | #include "gnunet_dnsparser_lib.h" | ||
29 | |||
30 | #define TEST_RECORD_TYPE GNUNET_DNSPARSER_TYPE_TXT | ||
31 | |||
32 | #define RECORDS 5 | ||
33 | |||
34 | #define TEST_RECORD_DATALEN 123 | ||
35 | |||
36 | #define TEST_RECORD_DATA 'a' | ||
37 | |||
38 | #define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 100) | ||
39 | |||
40 | |||
41 | static struct GNUNET_NAMESTORE_Handle *nsh; | ||
42 | |||
43 | static struct GNUNET_SCHEDULER_Task *endbadly_task; | ||
44 | |||
45 | static struct GNUNET_IDENTITY_PrivateKey privkey; | ||
46 | |||
47 | static struct GNUNET_IDENTITY_PublicKey pubkey; | ||
48 | |||
49 | static struct GNUNET_IDENTITY_PublicKey s_zone_value; | ||
50 | |||
51 | static char *s_name; | ||
52 | |||
53 | static int res; | ||
54 | |||
55 | static struct GNUNET_NAMESTORE_QueueEntry *qe; | ||
56 | |||
57 | |||
58 | /** | ||
59 | * Re-establish the connection to the service. | ||
60 | * | ||
61 | * @param cls handle to use to re-connect. | ||
62 | */ | ||
63 | static void | ||
64 | endbadly (void *cls) | ||
65 | { | ||
66 | (void) cls; | ||
67 | GNUNET_SCHEDULER_shutdown (); | ||
68 | res = 1; | ||
69 | } | ||
70 | |||
71 | |||
72 | static void | ||
73 | end (void *cls) | ||
74 | { | ||
75 | if (NULL != qe) | ||
76 | { | ||
77 | GNUNET_NAMESTORE_cancel (qe); | ||
78 | qe = NULL; | ||
79 | } | ||
80 | if (NULL != endbadly_task) | ||
81 | { | ||
82 | GNUNET_SCHEDULER_cancel (endbadly_task); | ||
83 | endbadly_task = NULL; | ||
84 | } | ||
85 | if (NULL != nsh) | ||
86 | { | ||
87 | GNUNET_NAMESTORE_disconnect (nsh); | ||
88 | nsh = NULL; | ||
89 | } | ||
90 | } | ||
91 | |||
92 | |||
93 | static void | ||
94 | zone_to_name_proc (void *cls, | ||
95 | const struct GNUNET_IDENTITY_PrivateKey *zone_key, | ||
96 | const char *n, | ||
97 | unsigned int rd_count, | ||
98 | const struct GNUNET_GNSRECORD_Data *rd) | ||
99 | { | ||
100 | int fail = GNUNET_NO; | ||
101 | |||
102 | qe = NULL; | ||
103 | if ((NULL == zone_key) && | ||
104 | (NULL == n) && | ||
105 | (0 == rd_count) && | ||
106 | (NULL == rd)) | ||
107 | { | ||
108 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
109 | "No result found\n"); | ||
110 | res = 1; | ||
111 | } | ||
112 | else | ||
113 | { | ||
114 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
115 | "Result found: `%s'\n", | ||
116 | n); | ||
117 | if ((NULL == n) || | ||
118 | (0 != strcmp (n, | ||
119 | s_name))) | ||
120 | { | ||
121 | fail = GNUNET_YES; | ||
122 | GNUNET_break (0); | ||
123 | } | ||
124 | if (1 != rd_count) | ||
125 | { | ||
126 | fail = GNUNET_YES; | ||
127 | GNUNET_break (0); | ||
128 | } | ||
129 | if ((NULL == zone_key) || | ||
130 | (0 != GNUNET_memcmp (zone_key, | ||
131 | &privkey))) | ||
132 | { | ||
133 | fail = GNUNET_YES; | ||
134 | GNUNET_break (0); | ||
135 | } | ||
136 | if (fail == GNUNET_NO) | ||
137 | res = 0; | ||
138 | else | ||
139 | res = 1; | ||
140 | } | ||
141 | GNUNET_SCHEDULER_add_now (&end, | ||
142 | NULL); | ||
143 | } | ||
144 | |||
145 | |||
146 | static void | ||
147 | error_cb (void *cls) | ||
148 | { | ||
149 | (void) cls; | ||
150 | qe = NULL; | ||
151 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
152 | "Not found!\n"); | ||
153 | GNUNET_SCHEDULER_shutdown (); | ||
154 | res = 2; | ||
155 | } | ||
156 | |||
157 | |||
158 | static void | ||
159 | put_cont (void *cls, | ||
160 | int32_t success, | ||
161 | const char *emsg) | ||
162 | { | ||
163 | char *name = cls; | ||
164 | |||
165 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
166 | "Name store added record for `%s': %s\n", | ||
167 | name, | ||
168 | (success == GNUNET_OK) ? "SUCCESS" : emsg); | ||
169 | if (success == GNUNET_OK) | ||
170 | { | ||
171 | res = 0; | ||
172 | |||
173 | qe = GNUNET_NAMESTORE_zone_to_name (nsh, | ||
174 | &privkey, | ||
175 | &s_zone_value, | ||
176 | &error_cb, | ||
177 | NULL, | ||
178 | &zone_to_name_proc, | ||
179 | NULL); | ||
180 | } | ||
181 | else | ||
182 | { | ||
183 | res = 1; | ||
184 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
185 | "Failed to put records for name `%s'\n", | ||
186 | name); | ||
187 | GNUNET_SCHEDULER_add_now (&end, | ||
188 | NULL); | ||
189 | } | ||
190 | } | ||
191 | |||
192 | |||
193 | static void | ||
194 | run (void *cls, | ||
195 | const struct GNUNET_CONFIGURATION_Handle *cfg, | ||
196 | struct GNUNET_TESTING_Peer *peer) | ||
197 | { | ||
198 | (void) cls; | ||
199 | (void) peer; | ||
200 | endbadly_task = GNUNET_SCHEDULER_add_delayed (TIMEOUT, | ||
201 | &endbadly, | ||
202 | NULL); | ||
203 | GNUNET_SCHEDULER_add_shutdown (&end, | ||
204 | NULL); | ||
205 | GNUNET_asprintf (&s_name, "dummy"); | ||
206 | privkey.type = htonl (GNUNET_GNSRECORD_TYPE_PKEY); | ||
207 | GNUNET_CRYPTO_ecdsa_key_create (&privkey.ecdsa_key); | ||
208 | /* get public key */ | ||
209 | GNUNET_IDENTITY_key_get_public (&privkey, | ||
210 | &pubkey); | ||
211 | |||
212 | GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_WEAK, | ||
213 | &s_zone_value, | ||
214 | sizeof(s_zone_value)); | ||
215 | s_zone_value.type = htonl (GNUNET_GNSRECORD_TYPE_PKEY); | ||
216 | { | ||
217 | struct GNUNET_GNSRECORD_Data rd; | ||
218 | |||
219 | rd.expiration_time = GNUNET_TIME_absolute_get ().abs_value_us; | ||
220 | rd.record_type = GNUNET_GNSRECORD_TYPE_PKEY; | ||
221 | rd.data_size = GNUNET_IDENTITY_key_get_length (&s_zone_value); | ||
222 | rd.data = &s_zone_value; | ||
223 | rd.flags = 0; | ||
224 | |||
225 | nsh = GNUNET_NAMESTORE_connect (cfg); | ||
226 | GNUNET_break (NULL != nsh); | ||
227 | GNUNET_NAMESTORE_records_store (nsh, | ||
228 | &privkey, | ||
229 | s_name, | ||
230 | 1, | ||
231 | &rd, | ||
232 | &put_cont, | ||
233 | NULL); | ||
234 | } | ||
235 | } | ||
236 | |||
237 | |||
238 | #include "test_common.c" | ||
239 | |||
240 | |||
241 | int | ||
242 | main (int argc, | ||
243 | char *argv[]) | ||
244 | { | ||
245 | const char *plugin_name; | ||
246 | char *cfg_name; | ||
247 | |||
248 | (void) argc; | ||
249 | SETUP_CFG (plugin_name, cfg_name); | ||
250 | res = 1; | ||
251 | if (0 != | ||
252 | GNUNET_TESTING_peer_run ("test-namestore-api-zone-to-name", | ||
253 | cfg_name, | ||
254 | &run, | ||
255 | NULL)) | ||
256 | { | ||
257 | res = 1; | ||
258 | } | ||
259 | GNUNET_DISK_purge_cfg_dir (cfg_name, | ||
260 | "GNUNET_TEST_HOME"); | ||
261 | GNUNET_free (cfg_name); | ||
262 | return res; | ||
263 | } | ||
264 | |||
265 | |||
266 | /* end of test_namestore_api_zone_to_name.c */ | ||
diff --git a/src/namestore/test_namestore_delete.sh b/src/namestore/test_namestore_delete.sh deleted file mode 100755 index 44ea1e66c..000000000 --- a/src/namestore/test_namestore_delete.sh +++ /dev/null | |||
@@ -1,76 +0,0 @@ | |||
1 | #!/bin/bash | ||
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_NAME = false -a $FOUND_IP != false ] | ||
65 | then | ||
66 | echo "PASS: Delete name in namestore" | ||
67 | exit 0 | ||
68 | elif [ $FOUND_NAME = true ] | ||
69 | then | ||
70 | echo "FAIL: Delete name in namestore: name returned" | ||
71 | exit 1 | ||
72 | elif [ $FOUND_IP = true ] | ||
73 | then | ||
74 | echo "FAIL: Delete name in namestore: IP returned" | ||
75 | exit 1 | ||
76 | 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 100644 index f33fb1c3a..000000000 --- a/src/namestore/test_namestore_put_multiple.sh +++ /dev/null | |||
@@ -1,123 +0,0 @@ | |||
1 | #!/bin/bash | ||
2 | |||
3 | # Check for required packages | ||
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 minimize_ttl { | ||
28 | ttl=10000000 | ||
29 | arr=$1 | ||
30 | # parse each element and update ttl to smallest one | ||
31 | for i in "${arr[@]}" | ||
32 | do | ||
33 | currttl=$(echo -n "$i" | cut -d' ' -f1) | ||
34 | if [ "$currttl" -lt "$ttl" ] | ||
35 | then | ||
36 | ttl=$currttl | ||
37 | fi | ||
38 | |||
39 | done | ||
40 | echo "$ttl" | ||
41 | } | ||
42 | |||
43 | function get_record_type { | ||
44 | arr=$1 | ||
45 | typ=$(echo -n "${arr[0]}" | cut -d' ' -f2) | ||
46 | echo "$typ" | ||
47 | } | ||
48 | |||
49 | function get_value { | ||
50 | arr=$1 | ||
51 | val=$(echo -n "${arr[0]}" | cut -d' ' -f4-) | ||
52 | echo "$val" | ||
53 | } | ||
54 | |||
55 | function testing { | ||
56 | label=$1 | ||
57 | records=$2 | ||
58 | recordstring="" | ||
59 | typ=$(get_record_type "${records[@]}") | ||
60 | for i in "${records[@]}" | ||
61 | do | ||
62 | recordstring+="-R $i" | ||
63 | done | ||
64 | #echo "$recordstring" | ||
65 | gnunet-namestore -z randomtestingid -n "$label" "$recordstring" 2>&1 /dev/null | ||
66 | if [ 0 -ne $ret ]; then | ||
67 | echo "failed to add record $label: $recordstring" | ||
68 | fi | ||
69 | gnunet-gns -t "$typ" -u foo2.randomtestingid 2>&1 /dev/null | ||
70 | if [ 0 -ne $ret ]; then | ||
71 | echo "record $label could not be found" | ||
72 | fi | ||
73 | } | ||
74 | |||
75 | # TEST CASES | ||
76 | # 1 | ||
77 | echo "Testing adding of single A record with -R" | ||
78 | testing test1 "${arr[@]}" | ||
79 | # 2 | ||
80 | echo "Testing adding of multiple A records with -R" | ||
81 | declare -a arr=('1200 A n 127.0.0.1' '2400 A n 127.0.0.2') | ||
82 | testing test2 "${arr[@]}" | ||
83 | # 3 | ||
84 | echo "Testing adding of multiple different records with -R" | ||
85 | declare -a arr=('1200 A n 127.0.0.1' '2400 AAAA n 2002::') | ||
86 | testing test3 "${arr[@]}" | ||
87 | # 4 | ||
88 | echo "Testing adding of single GNS2DNS record with -R" | ||
89 | declare -a arr=('86400 GNS2DNS n gnu.org@127.0.0.1') | ||
90 | testing test4 "${arr[@]}" | ||
91 | # 5 | ||
92 | echo "Testing adding of single GNS2DNS shadow record with -R" | ||
93 | declare -a arr=('86409 GNS2DNS s gnu.org@127.0.0.250') | ||
94 | testing test5 "${arr[@]}" | ||
95 | # 6 | ||
96 | echo "Testing adding of multiple GNS2DNS record with -R" | ||
97 | declare -a arr=('1 GNS2DNS n gnunet.org@127.0.0.1' '3600 GNS2DNS s gnunet.org@127.0.0.2') | ||
98 | testing test6 "${arr[@]}" | ||
99 | val=$(gnunet-gns -t GNS2DNS -u test6.randomtestingid) | ||
100 | if [[ $val == *"127.0.0.1"* ]]; then | ||
101 | echo "shadow!" | ||
102 | fi | ||
103 | echo "Sleeping to let record expire" | ||
104 | sleep 5 | ||
105 | val=$(gnunet-gns -t GNS2DNS -u test6.randomtestingid) | ||
106 | if [[ $val == *"127.0.0.2"* ]]; then | ||
107 | echo "no shadow!" | ||
108 | fi | ||
109 | # 7 | ||
110 | echo "Testing adding MX record with -R" | ||
111 | declare -a arr=('3600 MX n 10,mail') | ||
112 | testing test7 "${arr[@]}" | ||
113 | # 8 | ||
114 | echo "Testing adding TXT record with -R" | ||
115 | declare -a arr=('3600 TXT n Pretty_Unicorns') | ||
116 | testing test8 "${arr[@]}" | ||
117 | # 8 | ||
118 | echo "Testing adding TXT record with -R" | ||
119 | declare -a arr=('3600 SRV n _autodiscover_old._tcp.bfh.ch.') | ||
120 | testing test8 "${arr[@]}" | ||
121 | |||
122 | # CLEANUP | ||
123 | gnunet-identity -D randomtestingid | ||
diff --git a/src/namestore/test_plugin_namestore.c b/src/namestore/test_plugin_namestore.c deleted file mode 100644 index baea0e444..000000000 --- a/src/namestore/test_plugin_namestore.c +++ /dev/null | |||
@@ -1,205 +0,0 @@ | |||
1 | /* | ||
2 | This file is part of GNUnet. | ||
3 | Copyright (C) 2012 GNUnet e.V. | ||
4 | |||
5 | GNUnet is free software: you can redistribute it and/or modify it | ||
6 | under the terms of the GNU Affero General Public License as published | ||
7 | by the Free Software Foundation, either version 3 of the License, | ||
8 | or (at your option) any later version. | ||
9 | |||
10 | GNUnet is distributed in the hope that it will be useful, but | ||
11 | WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
13 | Affero General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU Affero General Public License | ||
16 | along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
17 | |||
18 | SPDX-License-Identifier: AGPL3.0-or-later | ||
19 | */ | ||
20 | /* | ||
21 | * @file namestore/test_plugin_namestore.c | ||
22 | * @brief Test for the namestore plugins | ||
23 | * @author Christian Grothoff | ||
24 | */ | ||
25 | #include "platform.h" | ||
26 | #include "gnunet_util_lib.h" | ||
27 | #include "gnunet_namestore_plugin.h" | ||
28 | #include "gnunet_testing_lib.h" | ||
29 | #include "gnunet_dnsparser_lib.h" | ||
30 | |||
31 | #define TEST_RECORD_TYPE GNUNET_DNSPARSER_TYPE_TXT | ||
32 | |||
33 | static int ok; | ||
34 | |||
35 | /** | ||
36 | * Name of plugin under test. | ||
37 | */ | ||
38 | static const char *plugin_name; | ||
39 | |||
40 | |||
41 | /** | ||
42 | * Function called when the service shuts down. Unloads our namestore | ||
43 | * plugin. | ||
44 | * | ||
45 | * @param api api to unload | ||
46 | */ | ||
47 | static void | ||
48 | unload_plugin (struct GNUNET_NAMESTORE_PluginFunctions *api) | ||
49 | { | ||
50 | char *libname; | ||
51 | |||
52 | GNUNET_asprintf (&libname, "libgnunet_plugin_namestore_%s", plugin_name); | ||
53 | GNUNET_break (NULL == GNUNET_PLUGIN_unload (libname, api)); | ||
54 | GNUNET_free (libname); | ||
55 | } | ||
56 | |||
57 | |||
58 | /** | ||
59 | * Load the namestore plugin. | ||
60 | * | ||
61 | * @param cfg configuration to pass | ||
62 | * @return NULL on error | ||
63 | */ | ||
64 | static struct GNUNET_NAMESTORE_PluginFunctions * | ||
65 | load_plugin (const struct GNUNET_CONFIGURATION_Handle *cfg) | ||
66 | { | ||
67 | struct GNUNET_NAMESTORE_PluginFunctions *ret; | ||
68 | char *libname; | ||
69 | |||
70 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, | ||
71 | _ ("Loading `%s' namestore plugin\n"), | ||
72 | plugin_name); | ||
73 | GNUNET_asprintf (&libname, "libgnunet_plugin_namestore_%s", plugin_name); | ||
74 | if (NULL == (ret = GNUNET_PLUGIN_load (libname, (void *) cfg))) | ||
75 | { | ||
76 | fprintf (stderr, "Failed to load plugin `%s'!\n", plugin_name); | ||
77 | GNUNET_free (libname); | ||
78 | return NULL; | ||
79 | } | ||
80 | GNUNET_free (libname); | ||
81 | return ret; | ||
82 | } | ||
83 | |||
84 | |||
85 | static void | ||
86 | test_record (void *cls, | ||
87 | uint64_t seq, | ||
88 | const struct GNUNET_IDENTITY_PrivateKey *private_key, | ||
89 | const char *label, | ||
90 | unsigned int rd_count, | ||
91 | const struct GNUNET_GNSRECORD_Data *rd) | ||
92 | { | ||
93 | int *idp = cls; | ||
94 | int id = *idp; | ||
95 | struct GNUNET_IDENTITY_PrivateKey tzone_private_key; | ||
96 | char tname[64]; | ||
97 | unsigned int trd_count = 1 + (id % 1024); | ||
98 | |||
99 | GNUNET_snprintf (tname, sizeof(tname), "a%u", (unsigned int) id); | ||
100 | GNUNET_assert (trd_count == rd_count); | ||
101 | for (unsigned int i = 0; i < trd_count; i++) | ||
102 | { | ||
103 | GNUNET_assert (rd[i].data_size == id % 10); | ||
104 | GNUNET_assert (0 == memcmp ("Hello World", rd[i].data, id % 10)); | ||
105 | GNUNET_assert (rd[i].record_type == TEST_RECORD_TYPE); | ||
106 | GNUNET_assert (rd[i].flags == 0); | ||
107 | } | ||
108 | memset (&tzone_private_key, (id % 241), sizeof(tzone_private_key)); | ||
109 | GNUNET_assert (0 == strcmp (label, tname)); | ||
110 | GNUNET_assert (0 == GNUNET_memcmp (&tzone_private_key, private_key)); | ||
111 | } | ||
112 | |||
113 | |||
114 | static void | ||
115 | get_record (struct GNUNET_NAMESTORE_PluginFunctions *nsp, int id) | ||
116 | { | ||
117 | GNUNET_assert ( | ||
118 | GNUNET_OK == | ||
119 | nsp->iterate_records (nsp->cls, NULL, 0, 1, &test_record, &id)); | ||
120 | } | ||
121 | |||
122 | |||
123 | static void | ||
124 | put_record (struct GNUNET_NAMESTORE_PluginFunctions *nsp, int id) | ||
125 | { | ||
126 | struct GNUNET_IDENTITY_PrivateKey zone_private_key; | ||
127 | char label[64]; | ||
128 | unsigned int rd_count = 1 + (id % 1024); | ||
129 | struct GNUNET_GNSRECORD_Data rd[GNUNET_NZL (rd_count)]; | ||
130 | struct GNUNET_CRYPTO_EcdsaSignature signature; | ||
131 | |||
132 | GNUNET_snprintf (label, sizeof(label), "a%u", (unsigned int) id); | ||
133 | for (unsigned int i = 0; i < rd_count; i++) | ||
134 | { | ||
135 | rd[i].data = "Hello World"; | ||
136 | rd[i].data_size = id % 10; | ||
137 | rd[i].expiration_time = | ||
138 | GNUNET_TIME_relative_to_absolute (GNUNET_TIME_UNIT_MINUTES).abs_value_us; | ||
139 | rd[i].record_type = TEST_RECORD_TYPE; | ||
140 | rd[i].flags = 0; | ||
141 | } | ||
142 | memset (&zone_private_key, (id % 241), sizeof(zone_private_key)); | ||
143 | memset (&signature, (id % 243), sizeof(signature)); | ||
144 | GNUNET_assert ( | ||
145 | GNUNET_OK == | ||
146 | nsp->store_records (nsp->cls, &zone_private_key, label, rd_count, rd)); | ||
147 | } | ||
148 | |||
149 | |||
150 | static void | ||
151 | run (void *cls, | ||
152 | char *const *args, | ||
153 | const char *cfgfile, | ||
154 | const struct GNUNET_CONFIGURATION_Handle *cfg) | ||
155 | { | ||
156 | struct GNUNET_NAMESTORE_PluginFunctions *nsp; | ||
157 | |||
158 | ok = 0; | ||
159 | nsp = load_plugin (cfg); | ||
160 | if (NULL == nsp) | ||
161 | { | ||
162 | fprintf ( | ||
163 | stderr, | ||
164 | "%s", | ||
165 | "Failed to initialize namestore. Database likely not setup, skipping test.\n"); | ||
166 | return; | ||
167 | } | ||
168 | put_record (nsp, 1); | ||
169 | get_record (nsp, 1); | ||
170 | #ifndef DARWIN // #5582 | ||
171 | unload_plugin (nsp); | ||
172 | #endif | ||
173 | } | ||
174 | |||
175 | |||
176 | int | ||
177 | main (int argc, char *argv[]) | ||
178 | { | ||
179 | char cfg_name[PATH_MAX]; | ||
180 | char *const xargv[] = { "test-plugin-namestore", "-c", cfg_name, NULL }; | ||
181 | struct GNUNET_GETOPT_CommandLineOption options[] = | ||
182 | { GNUNET_GETOPT_OPTION_END }; | ||
183 | |||
184 | GNUNET_log_setup ("test-plugin-namestore", "WARNING", NULL); | ||
185 | plugin_name = GNUNET_TESTING_get_testname_from_underscore (argv[0]); | ||
186 | GNUNET_snprintf (cfg_name, | ||
187 | sizeof(cfg_name), | ||
188 | "test_plugin_namestore_%s.conf", | ||
189 | plugin_name); | ||
190 | GNUNET_DISK_purge_cfg_dir (cfg_name, "GNUNET_TMP"); | ||
191 | GNUNET_PROGRAM_run ((sizeof(xargv) / sizeof(char *)) - 1, | ||
192 | xargv, | ||
193 | "test-plugin-namestore", | ||
194 | "nohelp", | ||
195 | options, | ||
196 | &run, | ||
197 | NULL); | ||
198 | GNUNET_DISK_purge_cfg_dir (cfg_name, "GNUNET_TMP"); | ||
199 | if (ok != 0) | ||
200 | fprintf (stderr, "Missed some testcases: %d\n", ok); | ||
201 | return ok; | ||
202 | } | ||
203 | |||
204 | |||
205 | /* end of test_plugin_namestore.c */ | ||
diff --git a/src/namestore/test_plugin_namestore_flat.conf b/src/namestore/test_plugin_namestore_flat.conf deleted file mode 100644 index 5c632f0d1..000000000 --- a/src/namestore/test_plugin_namestore_flat.conf +++ /dev/null | |||
@@ -1,2 +0,0 @@ | |||
1 | [namestore-flat] | ||
2 | FILENAME = $GNUNET_TMP/gnunet-test-plugin-namestore-flat/flatdb | ||
diff --git a/src/namestore/test_plugin_namestore_postgres.conf b/src/namestore/test_plugin_namestore_postgres.conf deleted file mode 100644 index 2ce8a7792..000000000 --- a/src/namestore/test_plugin_namestore_postgres.conf +++ /dev/null | |||
@@ -1,3 +0,0 @@ | |||
1 | [namestore-postgres] | ||
2 | CONFIG = connect_timeout=10 dbname=gnunetcheck | ||
3 | 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 24eecd286..000000000 --- a/src/namestore/test_plugin_namestore_sqlite.conf +++ /dev/null | |||
@@ -1,2 +0,0 @@ | |||
1 | [namestore-sqlite] | ||
2 | FILENAME = $GNUNET_TMP/gnunet-test-plugin-namestore-sqlite/sqlite.db | ||
diff --git a/src/namestore/test_plugin_rest_namestore.sh b/src/namestore/test_plugin_rest_namestore.sh deleted file mode 100755 index 8a45cebf5..000000000 --- a/src/namestore/test_plugin_rest_namestore.sh +++ /dev/null | |||
@@ -1,137 +0,0 @@ | |||
1 | #!/bin/sh | ||
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 | |||
22 | curl_get () { | ||
23 | #$1 is link | ||
24 | #$2 is grep | ||
25 | resp=$(curl -v "$1" 2>&1) | ||
26 | cache="$(echo $resp | grep "$2")" | ||
27 | #echo $cache | ||
28 | if [ "" = "$cache" ] | ||
29 | then | ||
30 | echo "Error in get response: $resp, expected $2" | ||
31 | gnunet-arm -e -c test_namestore_api.conf | ||
32 | exit 1 | ||
33 | fi | ||
34 | } | ||
35 | |||
36 | curl_post () { | ||
37 | #$1 is link | ||
38 | #$2 is data | ||
39 | #$3 is grep | ||
40 | resp=$(curl -v -X "POST" "$1" --data "$2" 2>&1) | ||
41 | cache="$(echo $resp | grep "$3")" | ||
42 | #echo $cache | ||
43 | if [ "" = "$cache" ] | ||
44 | then | ||
45 | echo "Error in post response: $resp ($2), expected $3" | ||
46 | gnunet-arm -e -c test_namestore_api.conf | ||
47 | exit 1 | ||
48 | fi | ||
49 | } | ||
50 | |||
51 | curl_delete () { | ||
52 | #$1 is link | ||
53 | #$2 is grep | ||
54 | resp=$(curl -v -X "DELETE" "$1" 2>&1) | ||
55 | cache="$(echo $resp | grep "$2")" | ||
56 | #echo $cache | ||
57 | if [ "" = "$cache" ] | ||
58 | then | ||
59 | echo "Error in delete response: $resp, expected $2" | ||
60 | gnunet-arm -e -c test_namestore_api.conf | ||
61 | exit 1 | ||
62 | fi | ||
63 | } | ||
64 | |||
65 | # curl_put () { | ||
66 | # #$1 is link | ||
67 | # #$2 is data | ||
68 | # #$3 is grep | ||
69 | # cache="$(curl -v -X "PUT" "$1" --data "$2" 2>&1 | grep "$3")" | ||
70 | # #echo $cache | ||
71 | # if [ "" == "$cache" ] | ||
72 | # then | ||
73 | # exit 1 | ||
74 | # fi | ||
75 | # } | ||
76 | |||
77 | #Test subsystem default identity | ||
78 | |||
79 | TEST_ID="test" | ||
80 | gnunet-arm -s -c test_namestore_api.conf | ||
81 | gnunet-arm -i rest -c test_namestore_api.conf | ||
82 | #Test GET | ||
83 | gnunet-identity -C $TEST_ID -c test_namestore_api.conf | ||
84 | test="$(gnunet-namestore -D -z $TEST_ID -c test_namestore_api.conf)" | ||
85 | name=$TEST_ID | ||
86 | public="$(gnunet-identity -d -c test_namestore_api.conf | grep $TEST_ID | awk 'NR==1{print $3}')" | ||
87 | echo "$name $public" | ||
88 | valgrind gnunet-namestore -z $name -p -a -n "test_entry" -e "1d" -V "000G006WVZ8HQ5YTVFNX09HK0VJVVQ9ZCBYDSCH3ERT04N5ZRBKEB82EP8" -t "PKEY" -c test_namestore_api.conf | ||
89 | #curl_get "${namestore_link}" "HTTP/1.1 200 OK" | ||
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", "expiration_time":"1d","private": false, "relative_expiration": false, "supplemental": false, "shadow": 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", "expiration_time":"1d","private": false, "relative_expiration": false, "supplemental": false, "shadow": 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", "expiration_time":"1d","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", "expiration_time":"1d","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", "expiration_time":"0d","private": false, "relative_expiration": true, "supplemental": false, "shadow": 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", "expiration_time":"10000d","private": false, "relative_expiration": true, "supplemental": false, "shadow": 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":"now","private": false, "relative_expiration": false, "supplemental": false, "shadow": 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 | curl_post "${namestore_link}/$name" '{"data": [{"value":"000G006WVZ8HQ5YTVFNX09HK0VJVVQ9ZCBYDSCH3ERT04N5ZRBKEB82EP8", "record_type":"PKEY", "expiration_time_missing":"1d","private": false, "relative_expiration": false, "supplemental": false, "shadow": false}],"record_name":"test_entry"}' "error" | ||
120 | gnunet-namestore -z $name -d -n "test_entry" -c test_namestore_api.conf > /dev/null 2>&1 | ||
121 | |||
122 | #record_name | ||
123 | curl_post "${namestore_link}/$name" '{"data": [{"value":"000G006WVZ8HQ5YTVFNX09HK0VJVVQ9ZCBYDSCH3ERT04N5ZRBKEB82EP8", "record_type":"PKEY", "expiration_time":"1d","private": false, "relative_expiration": false, "supplemental": false, "shadow": false}],"record_name":""}' "error" | ||
124 | gnunet-namestore -z $name -d -n "test_entry" -c test_namestore_api.conf > /dev/null 2>&1 | ||
125 | curl_post "${namestore_link}/$name" '{"data": [{"value":"000G006WVZ8HQ5YTVFNX09HK0VJVVQ9ZCBYDSCH3ERT04N5ZRBKEB82EP8", "record_type":"PKEY", "expiration_time":"1d","private": false, "relative_expiration": false, "supplemental": false, "shadow": false}],"record_name_missing":"test_entry"}' "error" | ||
126 | gnunet-namestore -z $name -d -n "test_entry" -c test_namestore_api.conf > /dev/null 2>&1 | ||
127 | |||
128 | #Test DELETE | ||
129 | gnunet-namestore -z $name -p -a -n "test_entry" -e "1d" -V "000G006WVZ8HQ5YTVFNX09HK0VJVVQ9ZCBYDSCH3ERT04N5ZRBKEB82EP8" -t "PKEY" -c test_namestore_api.conf | ||
130 | curl_delete "${namestore_link}/$name/test_entry" "HTTP/1.1 204" | ||
131 | curl_delete "${namestore_link}/$name/test_entry" "error" | ||
132 | gnunet-namestore -z $name -p -a -n "test_entry" -e "1d" -V "000G006WVZ8HQ5YTVFNX09HK0VJVVQ9ZCBYDSCH3ERT04N5ZRBKEB82EP8" -t "PKEY" -c test_namestore_api.conf | ||
133 | curl_delete "${namestore_link}/$public/test_entry" "error" | ||
134 | |||
135 | gnunet-arm -e -c test_namestore_api.conf | ||
136 | exit 0; | ||
137 | |||