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