aboutsummaryrefslogtreecommitdiff
path: root/src/gns
diff options
context:
space:
mode:
Diffstat (limited to 'src/gns')
-rw-r--r--src/gns/Makefile.am260
-rw-r--r--src/gns/Makefile.in641
-rw-r--r--src/gns/gns.conf.in25
-rw-r--r--src/gns/gns.h125
-rw-r--r--src/gns/gns_api.c919
-rw-r--r--src/gns/gns_proxy_proto.h49
-rw-r--r--src/gns/gnunet-gns-fcfsd.c811
-rw-r--r--src/gns/gnunet-gns-proxy.c815
-rw-r--r--src/gns/gnunet-gns.c262
-rw-r--r--src/gns/gnunet-service-gns.c1781
-rw-r--r--src/gns/gnunet-service-gns_interceptor.c394
-rw-r--r--src/gns/gnunet-service-gns_interceptor.h23
-rw-r--r--src/gns/gnunet-service-gns_resolver.c2751
-rw-r--r--src/gns/gnunet-service-gns_resolver.h356
-rw-r--r--src/gns/namestore_stub_api.c438
-rw-r--r--src/gns/nss/Makefile.am59
-rw-r--r--src/gns/nss/Makefile.in769
-rw-r--r--src/gns/nss/map-file14
-rw-r--r--src/gns/nss/nss_gns.c264
-rw-r--r--src/gns/nss/nss_gns_query.c65
-rw-r--r--src/gns/nss/nss_gns_query.h66
-rw-r--r--src/gns/plugin_block_gns.c165
-rw-r--r--src/gns/test_gns_defaults.conf69
-rw-r--r--src/gns/test_gns_dht_default.conf94
-rw-r--r--src/gns/test_gns_dht_delegated_lookup.c411
-rw-r--r--src/gns/test_gns_dht_threepeer.c524
-rw-r--r--src/gns/test_gns_max_queries.c381
-rw-r--r--src/gns/test_gns_pseu_shorten.c643
-rw-r--r--src/gns/test_gns_simple_delegated_lookup.c355
-rw-r--r--src/gns/test_gns_simple_get_authority.c388
-rw-r--r--src/gns/test_gns_simple_lookup.c317
-rw-r--r--src/gns/test_gns_simple_lookup.conf112
-rw-r--r--src/gns/test_gns_simple_mx_lookup.c396
-rw-r--r--src/gns/test_gns_simple_shorten.c388
-rw-r--r--src/gns/test_gns_simple_zkey_lookup.c358
-rw-r--r--src/gns/test_gns_twopeer.c463
-rw-r--r--src/gns/test_gns_twopeer.conf80
-rwxr-xr-xsrc/gns/test_gnunet_gns.sh22
38 files changed, 13449 insertions, 2604 deletions
diff --git a/src/gns/Makefile.am b/src/gns/Makefile.am
index cc19939..10b9ff3 100644
--- a/src/gns/Makefile.am
+++ b/src/gns/Makefile.am
@@ -1,5 +1,11 @@
INCLUDES = -I$(top_srcdir)/src/include
+if HAVE_GLIBCNSS
+NSS_SUBDIR = nss
+endif
+
+SUBDIRS = . $(NSS_SUBDIR)
+
if MINGW
WINFLAGS = -Wl,--no-undefined -Wl,--export-all-symbols
endif
@@ -16,98 +22,272 @@ pkgcfg_DATA = \
gns.conf
lib_LTLIBRARIES = \
- libgnunetgns.la libgnunetnamestore.la
+ libgnunetgns.la
+
+if HAVE_MHD
+ DO_FCFSD=gnunet-gns-fcfsd
+ DO_PROXY=gnunet-gns-proxy
+endif
bin_PROGRAMS = \
- gnunet-service-gns
+ gnunet-service-gns \
+ $(DO_FCFSD) \
+ $(DO_PROXY) \
+ gnunet-gns
#noinst_PROGRAMS = \
# gnunet-gns-lookup
-check_SCRIPTS = \
- test_gnunet_gns.sh
-
check_PROGRAMS = \
- test_gns_twopeer
+ test_gns_simple_shorten \
+ test_gns_simple_get_authority \
+ test_gns_simple_lookup \
+ test_gns_simple_delegated_lookup \
+ test_gns_simple_mx_lookup \
+ test_gns_simple_zkey_lookup \
+ test_gns_dht_delegated_lookup \
+ test_gns_pseu_shorten \
+ test_gns_max_queries \
+ test_gns_dht_threepeer
+
+
+# test_gns_simple_lookup
+# test_gns_simple_delegated_lookup
+# test_gns_dht_delegated_lookup
plugin_LTLIBRARIES = \
libgnunet_plugin_block_gns.la
-test_gns_twopeer_SOURCES = \
- test_gns_twopeer.c
-test_gns_twopeer_LDADD = \
+test_gns_dht_threepeer_SOURCES = \
+ test_gns_dht_threepeer.c
+test_gns_dht_threepeer_LDADD = \
+ $(top_builddir)/src/util/libgnunetutil.la \
+ $(top_builddir)/src/namestore/libgnunetnamestore.la \
+ $(top_builddir)/src/gns/libgnunetgns.la \
+ $(top_builddir)/src/testing/libgnunettesting.la
+test_gns_dht_threepeer_DEPENDENCIES = \
+ $(top_builddir)/src/util/libgnunetutil.la \
+ $(top_builddir)/src/namestore/libgnunetnamestore.la \
+ $(top_builddir)/src/gns/libgnunetgns.la \
+ $(top_builddir)/src/testing/libgnunettesting.la
+
+test_gns_simple_lookup_SOURCES = \
+ test_gns_simple_lookup.c
+test_gns_simple_lookup_LDADD = \
$(top_builddir)/src/util/libgnunetutil.la \
+ $(top_builddir)/src/namestore/libgnunetnamestore.la \
+ $(top_builddir)/src/gns/libgnunetgns.la \
$(top_builddir)/src/testing/libgnunettesting.la
-test_gns_twopeer_DEPENDENCIES = \
+test_gns_simple_lookup_DEPENDENCIES = \
$(top_builddir)/src/util/libgnunetutil.la \
+ $(top_builddir)/src/namestore/libgnunetnamestore.la \
+ $(top_builddir)/src/gns/libgnunetgns.la \
$(top_builddir)/src/testing/libgnunettesting.la
-#gnunet_gns_lookup_SOURCES = \
-# gnunet-gns-lookup.c
-#gnunet_gns_lookup_LDADD = \
-# $(top_builddir)/src/gns/libgnunetgns.la \
-# $(top_builddir)/src/util/libgnunetutil.la \
-# $(GN_LIBINTL)
-#gnunet_dns_lookup_DEPENDENCIES = \
-# libgnunetgns.la
+test_gns_simple_delegated_lookup_SOURCES = \
+ test_gns_simple_delegated_lookup.c
+test_gns_simple_delegated_lookup_LDADD = \
+ $(top_builddir)/src/util/libgnunetutil.la \
+ $(top_builddir)/src/namestore/libgnunetnamestore.la \
+ $(top_builddir)/src/gns/libgnunetgns.la \
+ $(top_builddir)/src/testing/libgnunettesting.la
+test_gns_simple_delegated_lookup_DEPENDENCIES = \
+ $(top_builddir)/src/util/libgnunetutil.la \
+ $(top_builddir)/src/namestore/libgnunetnamestore.la \
+ $(top_builddir)/src/gns/libgnunetgns.la \
+ $(top_builddir)/src/testing/libgnunettesting.la
+
+test_gns_simple_mx_lookup_SOURCES = \
+ test_gns_simple_mx_lookup.c
+test_gns_simple_mx_lookup_LDADD = \
+ $(top_builddir)/src/util/libgnunetutil.la \
+ $(top_builddir)/src/namestore/libgnunetnamestore.la \
+ $(top_builddir)/src/gns/libgnunetgns.la \
+ $(top_builddir)/src/testing/libgnunettesting.la
+test_gns_simple_mx_lookup_DEPENDENCIES = \
+ $(top_builddir)/src/util/libgnunetutil.la \
+ $(top_builddir)/src/namestore/libgnunetnamestore.la \
+ $(top_builddir)/src/gns/libgnunetgns.la \
+ $(top_builddir)/src/testing/libgnunettesting.la
+
+test_gns_simple_zkey_lookup_SOURCES = \
+ test_gns_simple_zkey_lookup.c
+test_gns_simple_zkey_lookup_LDADD = \
+ $(top_builddir)/src/util/libgnunetutil.la \
+ $(top_builddir)/src/namestore/libgnunetnamestore.la \
+ $(top_builddir)/src/gns/libgnunetgns.la \
+ $(top_builddir)/src/testing/libgnunettesting.la
+test_gns_simple_zkey_lookup_DEPENDENCIES = \
+ $(top_builddir)/src/util/libgnunetutil.la \
+ $(top_builddir)/src/namestore/libgnunetnamestore.la \
+ $(top_builddir)/src/gns/libgnunetgns.la \
+ $(top_builddir)/src/testing/libgnunettesting.la
+
+test_gns_dht_delegated_lookup_SOURCES = \
+ test_gns_dht_delegated_lookup.c
+test_gns_dht_delegated_lookup_LDADD = \
+ $(top_builddir)/src/util/libgnunetutil.la \
+ $(top_builddir)/src/namestore/libgnunetnamestore.la \
+ $(top_builddir)/src/dht/libgnunetdht.la \
+ $(top_builddir)/src/gns/libgnunetgns.la \
+ $(top_builddir)/src/testing/libgnunettesting.la
+test_gns_dht_delegated_lookup_DEPENDENCIES = \
+ $(top_builddir)/src/util/libgnunetutil.la \
+ $(top_builddir)/src/namestore/libgnunetnamestore.la \
+ $(top_builddir)/src/dht/libgnunetdht.la \
+ $(top_builddir)/src/gns/libgnunetgns.la \
+ $(top_builddir)/src/testing/libgnunettesting.la
+
+test_gns_simple_shorten_SOURCES = \
+ test_gns_simple_shorten.c
+test_gns_simple_shorten_LDADD = \
+ $(top_builddir)/src/util/libgnunetutil.la \
+ $(top_builddir)/src/namestore/libgnunetnamestore.la \
+ $(top_builddir)/src/gns/libgnunetgns.la \
+ $(top_builddir)/src/testing/libgnunettesting.la
+test_gns_simple_shorten_DEPENDENCIES = \
+ $(top_builddir)/src/util/libgnunetutil.la \
+ $(top_builddir)/src/namestore/libgnunetnamestore.la \
+ $(top_builddir)/src/gns/libgnunetgns.la \
+ $(top_builddir)/src/testing/libgnunettesting.la
+
+test_gns_simple_get_authority_SOURCES = \
+ test_gns_simple_get_authority.c
+test_gns_simple_get_authority_LDADD = \
+ $(top_builddir)/src/util/libgnunetutil.la \
+ $(top_builddir)/src/namestore/libgnunetnamestore.la \
+ $(top_builddir)/src/gns/libgnunetgns.la \
+ $(top_builddir)/src/testing/libgnunettesting.la
+test_gns_simple_get_authority_DEPENDENCIES = \
+ $(top_builddir)/src/util/libgnunetutil.la \
+ $(top_builddir)/src/namestore/libgnunetnamestore.la \
+ $(top_builddir)/src/gns/libgnunetgns.la \
+ $(top_builddir)/src/testing/libgnunettesting.la
+
+
+test_gns_pseu_shorten_SOURCES = \
+ test_gns_pseu_shorten.c
+test_gns_pseu_shorten_LDADD = \
+ $(top_builddir)/src/util/libgnunetutil.la \
+ $(top_builddir)/src/namestore/libgnunetnamestore.la \
+ $(top_builddir)/src/dht/libgnunetdht.la \
+ $(top_builddir)/src/gns/libgnunetgns.la \
+ $(top_builddir)/src/testing/libgnunettesting.la
+test_gns_pseu_shorten_DEPENDENCIES = \
+ $(top_builddir)/src/util/libgnunetutil.la \
+ $(top_builddir)/src/namestore/libgnunetnamestore.la \
+ $(top_builddir)/src/dht/libgnunetdht.la \
+ $(top_builddir)/src/gns/libgnunetgns.la \
+ $(top_builddir)/src/testing/libgnunettesting.la
+
+
+test_gns_max_queries_SOURCES = \
+ test_gns_max_queries.c
+test_gns_max_queries_LDADD = \
+ $(top_builddir)/src/util/libgnunetutil.la \
+ $(top_builddir)/src/namestore/libgnunetnamestore.la \
+ $(top_builddir)/src/gns/libgnunetgns.la \
+ $(top_builddir)/src/testing/libgnunettesting.la
+test_gns_max_queries_DEPENDENCIES = \
+ $(top_builddir)/src/util/libgnunetutil.la \
+ $(top_builddir)/src/namestore/libgnunetnamestore.la \
+ $(top_builddir)/src/gns/libgnunetgns.la \
+ $(top_builddir)/src/testing/libgnunettesting.la
+
+gnunet_gns_SOURCES = \
+ gnunet-gns.c
+gnunet_gns_LDADD = \
+ $(top_builddir)/src/gns/libgnunetgns.la \
+ $(top_builddir)/src/util/libgnunetutil.la \
+ $(top_builddir)/src/namestore/libgnunetnamestore.la \
+ $(GN_LIBINTL)
+gnunet_gns_DEPENDENCIES = \
+ libgnunetgns.la
+
+gnunet_gns_proxy_SOURCES = \
+ gnunet-gns-proxy.c gns_proxy_proto.h
+gnunet_gns_proxy_LDADD = -lmicrohttpd \
+ $(top_builddir)/src/gns/libgnunetgns.la \
+ $(top_builddir)/src/util/libgnunetutil.la \
+ $(GN_LIBINTL)
+gnunet_gns_proxy_DEPENDENCIES = \
+ libgnunetgns.la
gnunet_service_gns_SOURCES = \
- gnunet-service-gns.c
+ gnunet-service-gns.c \
+ gnunet-service-gns_resolver.c gnunet-service-gns_resolver.h \
+ gnunet-service-gns_interceptor.c gnunet-service-gns_interceptor.h
gnunet_service_gns_LDADD = \
- $(top_builddir)/src/tun/libgnunettun.la \
- $(top_builddir)/src/mesh/libgnunetmesh.la \
$(top_builddir)/src/statistics/libgnunetstatistics.la \
$(top_builddir)/src/util/libgnunetutil.la \
$(top_builddir)/src/dns/libgnunetdns.la \
$(top_builddir)/src/dns/libgnunetdnsparser.la \
$(top_builddir)/src/dht/libgnunetdht.la \
- $(top_builddir)/src/gns/libgnunetnamestore.la \
+ $(top_builddir)/src/namestore/libgnunetnamestore.la \
$(GN_LIBINTL)
gnunet_service_gns_DEPENDENCIES = \
- $(top_builddir)/src/tun/libgnunettun.la \
- $(top_builddir)/src/mesh/libgnunetmesh.la \
$(top_builddir)/src/statistics/libgnunetstatistics.la \
$(top_builddir)/src/util/libgnunetutil.la \
$(top_builddir)/src/dns/libgnunetdns.la \
$(top_builddir)/src/dns/libgnunetdnsparser.la \
$(top_builddir)/src/dht/libgnunetdht.la \
- $(top_builddir)/src/gns/libgnunetnamestore.la
+ $(top_builddir)/src/namestore/libgnunetnamestore.la
+
+
+gnunet_gns_fcfsd_SOURCES = \
+ gnunet-gns-fcfsd.c
+gnunet_gns_fcfsd_LDADD = -lmicrohttpd \
+ $(top_builddir)/src/util/libgnunetutil.la \
+ $(top_builddir)/src/namestore/libgnunetnamestore.la \
+ $(GN_LIBINTL)
+gnunet_gns_fcfsd_DEPENDENCIES = \
+ $(top_builddir)/src/util/libgnunetutil.la \
+ $(top_builddir)/src/namestore/libgnunetnamestore.la
+
libgnunetgns_la_SOURCES = \
gns_api.c gns.h
libgnunetgns_la_LIBADD = \
- $(top_builddir)/src/util/libgnunetutil.la $(XLIB)
+ $(top_builddir)/src/util/libgnunetutil.la $(XLIB) \
+ $(top_builddir)/src/namestore/libgnunetnamestore.la
libgnunetgns_la_LDFLAGS = \
$(GN_LIB_LDFLAGS)
libgnunetgns_la_DEPENDENCIES = \
- $(top_builddir)/src/util/libgnunetutil.la
+ $(top_builddir)/src/util/libgnunetutil.la \
+ $(top_builddir)/src/namestore/libgnunetnamestore.la
libgnunet_plugin_block_gns_la_SOURCES = \
plugin_block_gns.c
libgnunet_plugin_block_gns_la_LIBADD = \
$(top_builddir)/src/util/libgnunetutil.la \
- $(top_builddir)/src/block/libgnunetblock.la
+ $(top_builddir)/src/block/libgnunetblock.la \
+ $(top_builddir)/src/namestore/libgnunetnamestore.la
libgnunet_plugin_block_gns_la_LDFLAGS = \
$(GN_PLUGIN_LDFLAGS)
libgnunet_plugin_block_gns_la_DEPENDENCIES = \
$(top_builddir)/src/util/libgnunetutil.la \
- $(top_builddir)/src/block/libgnunetblock.la
+ $(top_builddir)/src/block/libgnunetblock.la \
+ $(top_builddir)/src/namestore/libgnunetnamestore.la
#Build stub api
-libgnunetnamestore_la_SOURCES = \
- namestore_stub_api.c
-libgnunetnamestore_la_LIBADD = \
- $(top_builddir)/src/util/libgnunetutil.la $(XLIB)
-libgnunetnamestore_la_LDFLAGS = \
- $(GN_LIB_LDFLAGS)
-libgnunetnamestore_la_DEPENDENCIES = \
- $(top_builddir)/src/util/libgnunetutil.la
+#libgnunetnamestore_la_SOURCES = \
+# namestore_stub_api.c
+#libgnunetnamestore_la_LIBADD = \
+# $(top_builddir)/src/util/libgnunetutil.la $(XLIB)
+#libgnunetnamestore_la_LDFLAGS = \
+# $(GN_LIB_LDFLAGS)
+#libgnunetnamestore_la_DEPENDENCIES = \
+# $(top_builddir)/src/util/libgnunetutil.la
if ENABLE_TEST_RUN
-TESTS = $(check_PROGRAMS) $(check_SCRIPTS)
+if LINUX
+TESTS = $(check_PROGRAMS)
+endif
endif
EXTRA_DIST = \
- $(check_SCRIPTS) \
- test_gns_twopeer.conf
+ test_gns_defaults.conf \
+ test_gns_simple_lookup.conf \
+ test_gns_dht_default.conf
+
diff --git a/src/gns/Makefile.in b/src/gns/Makefile.in
index 87422ab..5bdd92a 100644
--- a/src/gns/Makefile.in
+++ b/src/gns/Makefile.in
@@ -37,8 +37,17 @@ POST_UNINSTALL = :
build_triplet = @build@
host_triplet = @host@
target_triplet = @target@
-bin_PROGRAMS = gnunet-service-gns$(EXEEXT)
-check_PROGRAMS = test_gns_twopeer$(EXEEXT)
+bin_PROGRAMS = gnunet-service-gns$(EXEEXT) $(am__EXEEXT_1) \
+ $(am__EXEEXT_2) gnunet-gns$(EXEEXT)
+check_PROGRAMS = test_gns_simple_shorten$(EXEEXT) \
+ test_gns_simple_get_authority$(EXEEXT) \
+ test_gns_simple_lookup$(EXEEXT) \
+ test_gns_simple_delegated_lookup$(EXEEXT) \
+ test_gns_simple_mx_lookup$(EXEEXT) \
+ test_gns_simple_zkey_lookup$(EXEEXT) \
+ test_gns_dht_delegated_lookup$(EXEEXT) \
+ test_gns_pseu_shorten$(EXEEXT) test_gns_max_queries$(EXEEXT) \
+ test_gns_dht_threepeer$(EXEEXT)
subdir = src/gns
DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in \
$(srcdir)/gns.conf.in
@@ -101,18 +110,52 @@ libgnunetgns_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \
$(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \
$(AM_CFLAGS) $(CFLAGS) $(libgnunetgns_la_LDFLAGS) $(LDFLAGS) \
-o $@
-am_libgnunetnamestore_la_OBJECTS = namestore_stub_api.lo
-libgnunetnamestore_la_OBJECTS = $(am_libgnunetnamestore_la_OBJECTS)
-libgnunetnamestore_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \
- $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \
- $(AM_CFLAGS) $(CFLAGS) $(libgnunetnamestore_la_LDFLAGS) \
- $(LDFLAGS) -o $@
+@HAVE_MHD_TRUE@am__EXEEXT_1 = gnunet-gns-fcfsd$(EXEEXT)
+@HAVE_MHD_TRUE@am__EXEEXT_2 = gnunet-gns-proxy$(EXEEXT)
PROGRAMS = $(bin_PROGRAMS)
-am_gnunet_service_gns_OBJECTS = gnunet-service-gns.$(OBJEXT)
-gnunet_service_gns_OBJECTS = $(am_gnunet_service_gns_OBJECTS)
+am_gnunet_gns_OBJECTS = gnunet-gns.$(OBJEXT)
+gnunet_gns_OBJECTS = $(am_gnunet_gns_OBJECTS)
am__DEPENDENCIES_1 =
-am_test_gns_twopeer_OBJECTS = test_gns_twopeer.$(OBJEXT)
-test_gns_twopeer_OBJECTS = $(am_test_gns_twopeer_OBJECTS)
+am_gnunet_gns_fcfsd_OBJECTS = gnunet-gns-fcfsd.$(OBJEXT)
+gnunet_gns_fcfsd_OBJECTS = $(am_gnunet_gns_fcfsd_OBJECTS)
+am_gnunet_gns_proxy_OBJECTS = gnunet-gns-proxy.$(OBJEXT)
+gnunet_gns_proxy_OBJECTS = $(am_gnunet_gns_proxy_OBJECTS)
+am_gnunet_service_gns_OBJECTS = gnunet-service-gns.$(OBJEXT) \
+ gnunet-service-gns_resolver.$(OBJEXT) \
+ gnunet-service-gns_interceptor.$(OBJEXT)
+gnunet_service_gns_OBJECTS = $(am_gnunet_service_gns_OBJECTS)
+am_test_gns_dht_delegated_lookup_OBJECTS = \
+ test_gns_dht_delegated_lookup.$(OBJEXT)
+test_gns_dht_delegated_lookup_OBJECTS = \
+ $(am_test_gns_dht_delegated_lookup_OBJECTS)
+am_test_gns_dht_threepeer_OBJECTS = test_gns_dht_threepeer.$(OBJEXT)
+test_gns_dht_threepeer_OBJECTS = $(am_test_gns_dht_threepeer_OBJECTS)
+am_test_gns_max_queries_OBJECTS = test_gns_max_queries.$(OBJEXT)
+test_gns_max_queries_OBJECTS = $(am_test_gns_max_queries_OBJECTS)
+am_test_gns_pseu_shorten_OBJECTS = test_gns_pseu_shorten.$(OBJEXT)
+test_gns_pseu_shorten_OBJECTS = $(am_test_gns_pseu_shorten_OBJECTS)
+am_test_gns_simple_delegated_lookup_OBJECTS = \
+ test_gns_simple_delegated_lookup.$(OBJEXT)
+test_gns_simple_delegated_lookup_OBJECTS = \
+ $(am_test_gns_simple_delegated_lookup_OBJECTS)
+am_test_gns_simple_get_authority_OBJECTS = \
+ test_gns_simple_get_authority.$(OBJEXT)
+test_gns_simple_get_authority_OBJECTS = \
+ $(am_test_gns_simple_get_authority_OBJECTS)
+am_test_gns_simple_lookup_OBJECTS = test_gns_simple_lookup.$(OBJEXT)
+test_gns_simple_lookup_OBJECTS = $(am_test_gns_simple_lookup_OBJECTS)
+am_test_gns_simple_mx_lookup_OBJECTS = \
+ test_gns_simple_mx_lookup.$(OBJEXT)
+test_gns_simple_mx_lookup_OBJECTS = \
+ $(am_test_gns_simple_mx_lookup_OBJECTS)
+am_test_gns_simple_shorten_OBJECTS = \
+ test_gns_simple_shorten.$(OBJEXT)
+test_gns_simple_shorten_OBJECTS = \
+ $(am_test_gns_simple_shorten_OBJECTS)
+am_test_gns_simple_zkey_lookup_OBJECTS = \
+ test_gns_simple_zkey_lookup.$(OBJEXT)
+test_gns_simple_zkey_lookup_OBJECTS = \
+ $(am_test_gns_simple_zkey_lookup_OBJECTS)
DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
depcomp = $(SHELL) $(top_srcdir)/depcomp
am__depfiles_maybe = depfiles
@@ -140,17 +183,77 @@ AM_V_GEN = $(am__v_GEN_$(V))
am__v_GEN_ = $(am__v_GEN_$(AM_DEFAULT_VERBOSITY))
am__v_GEN_0 = @echo " GEN " $@;
SOURCES = $(libgnunet_plugin_block_gns_la_SOURCES) \
- $(libgnunetgns_la_SOURCES) $(libgnunetnamestore_la_SOURCES) \
- $(gnunet_service_gns_SOURCES) $(test_gns_twopeer_SOURCES)
+ $(libgnunetgns_la_SOURCES) $(gnunet_gns_SOURCES) \
+ $(gnunet_gns_fcfsd_SOURCES) $(gnunet_gns_proxy_SOURCES) \
+ $(gnunet_service_gns_SOURCES) \
+ $(test_gns_dht_delegated_lookup_SOURCES) \
+ $(test_gns_dht_threepeer_SOURCES) \
+ $(test_gns_max_queries_SOURCES) \
+ $(test_gns_pseu_shorten_SOURCES) \
+ $(test_gns_simple_delegated_lookup_SOURCES) \
+ $(test_gns_simple_get_authority_SOURCES) \
+ $(test_gns_simple_lookup_SOURCES) \
+ $(test_gns_simple_mx_lookup_SOURCES) \
+ $(test_gns_simple_shorten_SOURCES) \
+ $(test_gns_simple_zkey_lookup_SOURCES)
DIST_SOURCES = $(libgnunet_plugin_block_gns_la_SOURCES) \
- $(libgnunetgns_la_SOURCES) $(libgnunetnamestore_la_SOURCES) \
- $(gnunet_service_gns_SOURCES) $(test_gns_twopeer_SOURCES)
+ $(libgnunetgns_la_SOURCES) $(gnunet_gns_SOURCES) \
+ $(gnunet_gns_fcfsd_SOURCES) $(gnunet_gns_proxy_SOURCES) \
+ $(gnunet_service_gns_SOURCES) \
+ $(test_gns_dht_delegated_lookup_SOURCES) \
+ $(test_gns_dht_threepeer_SOURCES) \
+ $(test_gns_max_queries_SOURCES) \
+ $(test_gns_pseu_shorten_SOURCES) \
+ $(test_gns_simple_delegated_lookup_SOURCES) \
+ $(test_gns_simple_get_authority_SOURCES) \
+ $(test_gns_simple_lookup_SOURCES) \
+ $(test_gns_simple_mx_lookup_SOURCES) \
+ $(test_gns_simple_shorten_SOURCES) \
+ $(test_gns_simple_zkey_lookup_SOURCES)
+RECURSIVE_TARGETS = all-recursive check-recursive dvi-recursive \
+ html-recursive info-recursive install-data-recursive \
+ install-dvi-recursive install-exec-recursive \
+ install-html-recursive install-info-recursive \
+ install-pdf-recursive install-ps-recursive install-recursive \
+ installcheck-recursive installdirs-recursive pdf-recursive \
+ ps-recursive uninstall-recursive
DATA = $(pkgcfg_DATA)
+RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \
+ distclean-recursive maintainer-clean-recursive
+AM_RECURSIVE_TARGETS = $(RECURSIVE_TARGETS:-recursive=) \
+ $(RECURSIVE_CLEAN_TARGETS:-recursive=) tags TAGS ctags CTAGS \
+ distdir
ETAGS = etags
CTAGS = ctags
am__tty_colors = \
red=; grn=; lgn=; blu=; std=
+DIST_SUBDIRS = . nss
DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+am__relativize = \
+ dir0=`pwd`; \
+ sed_first='s,^\([^/]*\)/.*$$,\1,'; \
+ sed_rest='s,^[^/]*/*,,'; \
+ sed_last='s,^.*/\([^/]*\)$$,\1,'; \
+ sed_butlast='s,/*[^/]*$$,,'; \
+ while test -n "$$dir1"; do \
+ first=`echo "$$dir1" | sed -e "$$sed_first"`; \
+ if test "$$first" != "."; then \
+ if test "$$first" = ".."; then \
+ dir2=`echo "$$dir0" | sed -e "$$sed_last"`/"$$dir2"; \
+ dir0=`echo "$$dir0" | sed -e "$$sed_butlast"`; \
+ else \
+ first2=`echo "$$dir2" | sed -e "$$sed_first"`; \
+ if test "$$first2" = "$$first"; then \
+ dir2=`echo "$$dir2" | sed -e "$$sed_rest"`; \
+ else \
+ dir2="../$$dir2"; \
+ fi; \
+ dir0="$$dir0"/"$$first"; \
+ fi; \
+ fi; \
+ dir1=`echo "$$dir1" | sed -e "$$sed_rest"`; \
+ done; \
+ reldir="$$dir2"
ACLOCAL = @ACLOCAL@
AMTAR = @AMTAR@
AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
@@ -206,6 +309,7 @@ INSTALL_SCRIPT = @INSTALL_SCRIPT@
INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
INTLLIBS = @INTLLIBS@
INTL_MACOSX_LIBS = @INTL_MACOSX_LIBS@
+JAVAPORT = @JAVAPORT@
LD = @LD@
LDFLAGS = @LDFLAGS@
LIBADD_DL = @LIBADD_DL@
@@ -239,6 +343,7 @@ LT_DLLOADERS = @LT_DLLOADERS@
LT_DLPREOPEN = @LT_DLPREOPEN@
MAKEINFO = @MAKEINFO@
MKDIR_P = @MKDIR_P@
+MONKEYPREFIX = @MONKEYPREFIX@
MSGFMT = @MSGFMT@
MSGFMT_015 = @MSGFMT_015@
MSGMERGE = @MSGMERGE@
@@ -356,6 +461,8 @@ top_build_prefix = @top_build_prefix@
top_builddir = @top_builddir@
top_srcdir = @top_srcdir@
INCLUDES = -I$(top_srcdir)/src/include
+@HAVE_GLIBCNSS_TRUE@NSS_SUBDIR = nss
+SUBDIRS = . $(NSS_SUBDIR)
@MINGW_TRUE@WINFLAGS = -Wl,--no-undefined -Wl,--export-all-symbols
@USE_COVERAGE_TRUE@AM_CFLAGS = --coverage -O0
pkgcfgdir = $(pkgdatadir)/config.d/
@@ -364,107 +471,275 @@ pkgcfg_DATA = \
gns.conf
lib_LTLIBRARIES = \
- libgnunetgns.la libgnunetnamestore.la
-
+ libgnunetgns.la
-#noinst_PROGRAMS = \
-# gnunet-gns-lookup
-check_SCRIPTS = \
- test_gnunet_gns.sh
+@HAVE_MHD_TRUE@DO_FCFSD = gnunet-gns-fcfsd
+@HAVE_MHD_TRUE@DO_PROXY = gnunet-gns-proxy
+# test_gns_simple_lookup
+# test_gns_simple_delegated_lookup
+# test_gns_dht_delegated_lookup
plugin_LTLIBRARIES = \
libgnunet_plugin_block_gns.la
-test_gns_twopeer_SOURCES = \
- test_gns_twopeer.c
+test_gns_dht_threepeer_SOURCES = \
+ test_gns_dht_threepeer.c
+
+test_gns_dht_threepeer_LDADD = \
+ $(top_builddir)/src/util/libgnunetutil.la \
+ $(top_builddir)/src/namestore/libgnunetnamestore.la \
+ $(top_builddir)/src/gns/libgnunetgns.la \
+ $(top_builddir)/src/testing/libgnunettesting.la
+
+test_gns_dht_threepeer_DEPENDENCIES = \
+ $(top_builddir)/src/util/libgnunetutil.la \
+ $(top_builddir)/src/namestore/libgnunetnamestore.la \
+ $(top_builddir)/src/gns/libgnunetgns.la \
+ $(top_builddir)/src/testing/libgnunettesting.la
+
+test_gns_simple_lookup_SOURCES = \
+ test_gns_simple_lookup.c
+
+test_gns_simple_lookup_LDADD = \
+ $(top_builddir)/src/util/libgnunetutil.la \
+ $(top_builddir)/src/namestore/libgnunetnamestore.la \
+ $(top_builddir)/src/gns/libgnunetgns.la \
+ $(top_builddir)/src/testing/libgnunettesting.la
+
+test_gns_simple_lookup_DEPENDENCIES = \
+ $(top_builddir)/src/util/libgnunetutil.la \
+ $(top_builddir)/src/namestore/libgnunetnamestore.la \
+ $(top_builddir)/src/gns/libgnunetgns.la \
+ $(top_builddir)/src/testing/libgnunettesting.la
+
+test_gns_simple_delegated_lookup_SOURCES = \
+ test_gns_simple_delegated_lookup.c
+
+test_gns_simple_delegated_lookup_LDADD = \
+ $(top_builddir)/src/util/libgnunetutil.la \
+ $(top_builddir)/src/namestore/libgnunetnamestore.la \
+ $(top_builddir)/src/gns/libgnunetgns.la \
+ $(top_builddir)/src/testing/libgnunettesting.la
+
+test_gns_simple_delegated_lookup_DEPENDENCIES = \
+ $(top_builddir)/src/util/libgnunetutil.la \
+ $(top_builddir)/src/namestore/libgnunetnamestore.la \
+ $(top_builddir)/src/gns/libgnunetgns.la \
+ $(top_builddir)/src/testing/libgnunettesting.la
+
+test_gns_simple_mx_lookup_SOURCES = \
+ test_gns_simple_mx_lookup.c
+
+test_gns_simple_mx_lookup_LDADD = \
+ $(top_builddir)/src/util/libgnunetutil.la \
+ $(top_builddir)/src/namestore/libgnunetnamestore.la \
+ $(top_builddir)/src/gns/libgnunetgns.la \
+ $(top_builddir)/src/testing/libgnunettesting.la
+
+test_gns_simple_mx_lookup_DEPENDENCIES = \
+ $(top_builddir)/src/util/libgnunetutil.la \
+ $(top_builddir)/src/namestore/libgnunetnamestore.la \
+ $(top_builddir)/src/gns/libgnunetgns.la \
+ $(top_builddir)/src/testing/libgnunettesting.la
+
+test_gns_simple_zkey_lookup_SOURCES = \
+ test_gns_simple_zkey_lookup.c
+
+test_gns_simple_zkey_lookup_LDADD = \
+ $(top_builddir)/src/util/libgnunetutil.la \
+ $(top_builddir)/src/namestore/libgnunetnamestore.la \
+ $(top_builddir)/src/gns/libgnunetgns.la \
+ $(top_builddir)/src/testing/libgnunettesting.la
+
+test_gns_simple_zkey_lookup_DEPENDENCIES = \
+ $(top_builddir)/src/util/libgnunetutil.la \
+ $(top_builddir)/src/namestore/libgnunetnamestore.la \
+ $(top_builddir)/src/gns/libgnunetgns.la \
+ $(top_builddir)/src/testing/libgnunettesting.la
+
+test_gns_dht_delegated_lookup_SOURCES = \
+ test_gns_dht_delegated_lookup.c
+
+test_gns_dht_delegated_lookup_LDADD = \
+ $(top_builddir)/src/util/libgnunetutil.la \
+ $(top_builddir)/src/namestore/libgnunetnamestore.la \
+ $(top_builddir)/src/dht/libgnunetdht.la \
+ $(top_builddir)/src/gns/libgnunetgns.la \
+ $(top_builddir)/src/testing/libgnunettesting.la
+
+test_gns_dht_delegated_lookup_DEPENDENCIES = \
+ $(top_builddir)/src/util/libgnunetutil.la \
+ $(top_builddir)/src/namestore/libgnunetnamestore.la \
+ $(top_builddir)/src/dht/libgnunetdht.la \
+ $(top_builddir)/src/gns/libgnunetgns.la \
+ $(top_builddir)/src/testing/libgnunettesting.la
+
+test_gns_simple_shorten_SOURCES = \
+ test_gns_simple_shorten.c
+
+test_gns_simple_shorten_LDADD = \
+ $(top_builddir)/src/util/libgnunetutil.la \
+ $(top_builddir)/src/namestore/libgnunetnamestore.la \
+ $(top_builddir)/src/gns/libgnunetgns.la \
+ $(top_builddir)/src/testing/libgnunettesting.la
+
+test_gns_simple_shorten_DEPENDENCIES = \
+ $(top_builddir)/src/util/libgnunetutil.la \
+ $(top_builddir)/src/namestore/libgnunetnamestore.la \
+ $(top_builddir)/src/gns/libgnunetgns.la \
+ $(top_builddir)/src/testing/libgnunettesting.la
+
+test_gns_simple_get_authority_SOURCES = \
+ test_gns_simple_get_authority.c
-test_gns_twopeer_LDADD = \
+test_gns_simple_get_authority_LDADD = \
$(top_builddir)/src/util/libgnunetutil.la \
+ $(top_builddir)/src/namestore/libgnunetnamestore.la \
+ $(top_builddir)/src/gns/libgnunetgns.la \
$(top_builddir)/src/testing/libgnunettesting.la
-test_gns_twopeer_DEPENDENCIES = \
+test_gns_simple_get_authority_DEPENDENCIES = \
$(top_builddir)/src/util/libgnunetutil.la \
+ $(top_builddir)/src/namestore/libgnunetnamestore.la \
+ $(top_builddir)/src/gns/libgnunetgns.la \
$(top_builddir)/src/testing/libgnunettesting.la
+test_gns_pseu_shorten_SOURCES = \
+ test_gns_pseu_shorten.c
+
+test_gns_pseu_shorten_LDADD = \
+ $(top_builddir)/src/util/libgnunetutil.la \
+ $(top_builddir)/src/namestore/libgnunetnamestore.la \
+ $(top_builddir)/src/dht/libgnunetdht.la \
+ $(top_builddir)/src/gns/libgnunetgns.la \
+ $(top_builddir)/src/testing/libgnunettesting.la
+
+test_gns_pseu_shorten_DEPENDENCIES = \
+ $(top_builddir)/src/util/libgnunetutil.la \
+ $(top_builddir)/src/namestore/libgnunetnamestore.la \
+ $(top_builddir)/src/dht/libgnunetdht.la \
+ $(top_builddir)/src/gns/libgnunetgns.la \
+ $(top_builddir)/src/testing/libgnunettesting.la
+
+test_gns_max_queries_SOURCES = \
+ test_gns_max_queries.c
+
+test_gns_max_queries_LDADD = \
+ $(top_builddir)/src/util/libgnunetutil.la \
+ $(top_builddir)/src/namestore/libgnunetnamestore.la \
+ $(top_builddir)/src/gns/libgnunetgns.la \
+ $(top_builddir)/src/testing/libgnunettesting.la
+
+test_gns_max_queries_DEPENDENCIES = \
+ $(top_builddir)/src/util/libgnunetutil.la \
+ $(top_builddir)/src/namestore/libgnunetnamestore.la \
+ $(top_builddir)/src/gns/libgnunetgns.la \
+ $(top_builddir)/src/testing/libgnunettesting.la
+
+gnunet_gns_SOURCES = \
+ gnunet-gns.c
+
+gnunet_gns_LDADD = \
+ $(top_builddir)/src/gns/libgnunetgns.la \
+ $(top_builddir)/src/util/libgnunetutil.la \
+ $(top_builddir)/src/namestore/libgnunetnamestore.la \
+ $(GN_LIBINTL)
+
+gnunet_gns_DEPENDENCIES = \
+ libgnunetgns.la
+
+gnunet_gns_proxy_SOURCES = \
+ gnunet-gns-proxy.c gns_proxy_proto.h
+
+gnunet_gns_proxy_LDADD = -lmicrohttpd \
+ $(top_builddir)/src/gns/libgnunetgns.la \
+ $(top_builddir)/src/util/libgnunetutil.la \
+ $(GN_LIBINTL)
+
+gnunet_gns_proxy_DEPENDENCIES = \
+ libgnunetgns.la
-#gnunet_gns_lookup_SOURCES = \
-# gnunet-gns-lookup.c
-#gnunet_gns_lookup_LDADD = \
-# $(top_builddir)/src/gns/libgnunetgns.la \
-# $(top_builddir)/src/util/libgnunetutil.la \
-# $(GN_LIBINTL)
-#gnunet_dns_lookup_DEPENDENCIES = \
-# libgnunetgns.la
gnunet_service_gns_SOURCES = \
- gnunet-service-gns.c
+ gnunet-service-gns.c \
+ gnunet-service-gns_resolver.c gnunet-service-gns_resolver.h \
+ gnunet-service-gns_interceptor.c gnunet-service-gns_interceptor.h
gnunet_service_gns_LDADD = \
- $(top_builddir)/src/tun/libgnunettun.la \
- $(top_builddir)/src/mesh/libgnunetmesh.la \
$(top_builddir)/src/statistics/libgnunetstatistics.la \
$(top_builddir)/src/util/libgnunetutil.la \
$(top_builddir)/src/dns/libgnunetdns.la \
$(top_builddir)/src/dns/libgnunetdnsparser.la \
$(top_builddir)/src/dht/libgnunetdht.la \
- $(top_builddir)/src/gns/libgnunetnamestore.la \
+ $(top_builddir)/src/namestore/libgnunetnamestore.la \
$(GN_LIBINTL)
gnunet_service_gns_DEPENDENCIES = \
- $(top_builddir)/src/tun/libgnunettun.la \
- $(top_builddir)/src/mesh/libgnunetmesh.la \
$(top_builddir)/src/statistics/libgnunetstatistics.la \
$(top_builddir)/src/util/libgnunetutil.la \
$(top_builddir)/src/dns/libgnunetdns.la \
$(top_builddir)/src/dns/libgnunetdnsparser.la \
$(top_builddir)/src/dht/libgnunetdht.la \
- $(top_builddir)/src/gns/libgnunetnamestore.la
+ $(top_builddir)/src/namestore/libgnunetnamestore.la
+
+gnunet_gns_fcfsd_SOURCES = \
+ gnunet-gns-fcfsd.c
+
+gnunet_gns_fcfsd_LDADD = -lmicrohttpd \
+ $(top_builddir)/src/util/libgnunetutil.la \
+ $(top_builddir)/src/namestore/libgnunetnamestore.la \
+ $(GN_LIBINTL)
+
+gnunet_gns_fcfsd_DEPENDENCIES = \
+ $(top_builddir)/src/util/libgnunetutil.la \
+ $(top_builddir)/src/namestore/libgnunetnamestore.la
libgnunetgns_la_SOURCES = \
gns_api.c gns.h
libgnunetgns_la_LIBADD = \
- $(top_builddir)/src/util/libgnunetutil.la $(XLIB)
+ $(top_builddir)/src/util/libgnunetutil.la $(XLIB) \
+ $(top_builddir)/src/namestore/libgnunetnamestore.la
libgnunetgns_la_LDFLAGS = \
$(GN_LIB_LDFLAGS)
libgnunetgns_la_DEPENDENCIES = \
- $(top_builddir)/src/util/libgnunetutil.la
+ $(top_builddir)/src/util/libgnunetutil.la \
+ $(top_builddir)/src/namestore/libgnunetnamestore.la
libgnunet_plugin_block_gns_la_SOURCES = \
plugin_block_gns.c
libgnunet_plugin_block_gns_la_LIBADD = \
$(top_builddir)/src/util/libgnunetutil.la \
- $(top_builddir)/src/block/libgnunetblock.la
+ $(top_builddir)/src/block/libgnunetblock.la \
+ $(top_builddir)/src/namestore/libgnunetnamestore.la
libgnunet_plugin_block_gns_la_LDFLAGS = \
$(GN_PLUGIN_LDFLAGS)
libgnunet_plugin_block_gns_la_DEPENDENCIES = \
$(top_builddir)/src/util/libgnunetutil.la \
- $(top_builddir)/src/block/libgnunetblock.la
+ $(top_builddir)/src/block/libgnunetblock.la \
+ $(top_builddir)/src/namestore/libgnunetnamestore.la
#Build stub api
-libgnunetnamestore_la_SOURCES = \
- namestore_stub_api.c
-
-libgnunetnamestore_la_LIBADD = \
- $(top_builddir)/src/util/libgnunetutil.la $(XLIB)
-
-libgnunetnamestore_la_LDFLAGS = \
- $(GN_LIB_LDFLAGS)
-
-libgnunetnamestore_la_DEPENDENCIES = \
- $(top_builddir)/src/util/libgnunetutil.la
-
-@ENABLE_TEST_RUN_TRUE@TESTS = $(check_PROGRAMS) $(check_SCRIPTS)
+#libgnunetnamestore_la_SOURCES = \
+# namestore_stub_api.c
+#libgnunetnamestore_la_LIBADD = \
+# $(top_builddir)/src/util/libgnunetutil.la $(XLIB)
+#libgnunetnamestore_la_LDFLAGS = \
+# $(GN_LIB_LDFLAGS)
+#libgnunetnamestore_la_DEPENDENCIES = \
+# $(top_builddir)/src/util/libgnunetutil.la
+@ENABLE_TEST_RUN_TRUE@@LINUX_TRUE@TESTS = $(check_PROGRAMS)
EXTRA_DIST = \
- $(check_SCRIPTS) \
- test_gns_twopeer.conf
+ test_gns_defaults.conf \
+ test_gns_simple_lookup.conf \
+ test_gns_dht_default.conf
-all: all-am
+all: all-recursive
.SUFFIXES:
.SUFFIXES: .c .lo .o .obj
@@ -566,8 +841,6 @@ libgnunet_plugin_block_gns.la: $(libgnunet_plugin_block_gns_la_OBJECTS) $(libgnu
$(AM_V_CCLD)$(libgnunet_plugin_block_gns_la_LINK) -rpath $(plugindir) $(libgnunet_plugin_block_gns_la_OBJECTS) $(libgnunet_plugin_block_gns_la_LIBADD) $(LIBS)
libgnunetgns.la: $(libgnunetgns_la_OBJECTS) $(libgnunetgns_la_DEPENDENCIES)
$(AM_V_CCLD)$(libgnunetgns_la_LINK) -rpath $(libdir) $(libgnunetgns_la_OBJECTS) $(libgnunetgns_la_LIBADD) $(LIBS)
-libgnunetnamestore.la: $(libgnunetnamestore_la_OBJECTS) $(libgnunetnamestore_la_DEPENDENCIES)
- $(AM_V_CCLD)$(libgnunetnamestore_la_LINK) -rpath $(libdir) $(libgnunetnamestore_la_OBJECTS) $(libgnunetnamestore_la_LIBADD) $(LIBS)
install-binPROGRAMS: $(bin_PROGRAMS)
@$(NORMAL_INSTALL)
test -z "$(bindir)" || $(MKDIR_P) "$(DESTDIR)$(bindir)"
@@ -620,12 +893,48 @@ clean-checkPROGRAMS:
list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \
echo " rm -f" $$list; \
rm -f $$list
+gnunet-gns$(EXEEXT): $(gnunet_gns_OBJECTS) $(gnunet_gns_DEPENDENCIES)
+ @rm -f gnunet-gns$(EXEEXT)
+ $(AM_V_CCLD)$(LINK) $(gnunet_gns_OBJECTS) $(gnunet_gns_LDADD) $(LIBS)
+gnunet-gns-fcfsd$(EXEEXT): $(gnunet_gns_fcfsd_OBJECTS) $(gnunet_gns_fcfsd_DEPENDENCIES)
+ @rm -f gnunet-gns-fcfsd$(EXEEXT)
+ $(AM_V_CCLD)$(LINK) $(gnunet_gns_fcfsd_OBJECTS) $(gnunet_gns_fcfsd_LDADD) $(LIBS)
+gnunet-gns-proxy$(EXEEXT): $(gnunet_gns_proxy_OBJECTS) $(gnunet_gns_proxy_DEPENDENCIES)
+ @rm -f gnunet-gns-proxy$(EXEEXT)
+ $(AM_V_CCLD)$(LINK) $(gnunet_gns_proxy_OBJECTS) $(gnunet_gns_proxy_LDADD) $(LIBS)
gnunet-service-gns$(EXEEXT): $(gnunet_service_gns_OBJECTS) $(gnunet_service_gns_DEPENDENCIES)
@rm -f gnunet-service-gns$(EXEEXT)
$(AM_V_CCLD)$(LINK) $(gnunet_service_gns_OBJECTS) $(gnunet_service_gns_LDADD) $(LIBS)
-test_gns_twopeer$(EXEEXT): $(test_gns_twopeer_OBJECTS) $(test_gns_twopeer_DEPENDENCIES)
- @rm -f test_gns_twopeer$(EXEEXT)
- $(AM_V_CCLD)$(LINK) $(test_gns_twopeer_OBJECTS) $(test_gns_twopeer_LDADD) $(LIBS)
+test_gns_dht_delegated_lookup$(EXEEXT): $(test_gns_dht_delegated_lookup_OBJECTS) $(test_gns_dht_delegated_lookup_DEPENDENCIES)
+ @rm -f test_gns_dht_delegated_lookup$(EXEEXT)
+ $(AM_V_CCLD)$(LINK) $(test_gns_dht_delegated_lookup_OBJECTS) $(test_gns_dht_delegated_lookup_LDADD) $(LIBS)
+test_gns_dht_threepeer$(EXEEXT): $(test_gns_dht_threepeer_OBJECTS) $(test_gns_dht_threepeer_DEPENDENCIES)
+ @rm -f test_gns_dht_threepeer$(EXEEXT)
+ $(AM_V_CCLD)$(LINK) $(test_gns_dht_threepeer_OBJECTS) $(test_gns_dht_threepeer_LDADD) $(LIBS)
+test_gns_max_queries$(EXEEXT): $(test_gns_max_queries_OBJECTS) $(test_gns_max_queries_DEPENDENCIES)
+ @rm -f test_gns_max_queries$(EXEEXT)
+ $(AM_V_CCLD)$(LINK) $(test_gns_max_queries_OBJECTS) $(test_gns_max_queries_LDADD) $(LIBS)
+test_gns_pseu_shorten$(EXEEXT): $(test_gns_pseu_shorten_OBJECTS) $(test_gns_pseu_shorten_DEPENDENCIES)
+ @rm -f test_gns_pseu_shorten$(EXEEXT)
+ $(AM_V_CCLD)$(LINK) $(test_gns_pseu_shorten_OBJECTS) $(test_gns_pseu_shorten_LDADD) $(LIBS)
+test_gns_simple_delegated_lookup$(EXEEXT): $(test_gns_simple_delegated_lookup_OBJECTS) $(test_gns_simple_delegated_lookup_DEPENDENCIES)
+ @rm -f test_gns_simple_delegated_lookup$(EXEEXT)
+ $(AM_V_CCLD)$(LINK) $(test_gns_simple_delegated_lookup_OBJECTS) $(test_gns_simple_delegated_lookup_LDADD) $(LIBS)
+test_gns_simple_get_authority$(EXEEXT): $(test_gns_simple_get_authority_OBJECTS) $(test_gns_simple_get_authority_DEPENDENCIES)
+ @rm -f test_gns_simple_get_authority$(EXEEXT)
+ $(AM_V_CCLD)$(LINK) $(test_gns_simple_get_authority_OBJECTS) $(test_gns_simple_get_authority_LDADD) $(LIBS)
+test_gns_simple_lookup$(EXEEXT): $(test_gns_simple_lookup_OBJECTS) $(test_gns_simple_lookup_DEPENDENCIES)
+ @rm -f test_gns_simple_lookup$(EXEEXT)
+ $(AM_V_CCLD)$(LINK) $(test_gns_simple_lookup_OBJECTS) $(test_gns_simple_lookup_LDADD) $(LIBS)
+test_gns_simple_mx_lookup$(EXEEXT): $(test_gns_simple_mx_lookup_OBJECTS) $(test_gns_simple_mx_lookup_DEPENDENCIES)
+ @rm -f test_gns_simple_mx_lookup$(EXEEXT)
+ $(AM_V_CCLD)$(LINK) $(test_gns_simple_mx_lookup_OBJECTS) $(test_gns_simple_mx_lookup_LDADD) $(LIBS)
+test_gns_simple_shorten$(EXEEXT): $(test_gns_simple_shorten_OBJECTS) $(test_gns_simple_shorten_DEPENDENCIES)
+ @rm -f test_gns_simple_shorten$(EXEEXT)
+ $(AM_V_CCLD)$(LINK) $(test_gns_simple_shorten_OBJECTS) $(test_gns_simple_shorten_LDADD) $(LIBS)
+test_gns_simple_zkey_lookup$(EXEEXT): $(test_gns_simple_zkey_lookup_OBJECTS) $(test_gns_simple_zkey_lookup_DEPENDENCIES)
+ @rm -f test_gns_simple_zkey_lookup$(EXEEXT)
+ $(AM_V_CCLD)$(LINK) $(test_gns_simple_zkey_lookup_OBJECTS) $(test_gns_simple_zkey_lookup_LDADD) $(LIBS)
mostlyclean-compile:
-rm -f *.$(OBJEXT)
@@ -634,10 +943,23 @@ distclean-compile:
-rm -f *.tab.c
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gns_api.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gnunet-gns-fcfsd.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gnunet-gns-proxy.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gnunet-gns.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gnunet-service-gns.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/namestore_stub_api.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gnunet-service-gns_interceptor.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gnunet-service-gns_resolver.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/plugin_block_gns.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_gns_twopeer.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_gns_dht_delegated_lookup.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_gns_dht_threepeer.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_gns_max_queries.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_gns_pseu_shorten.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_gns_simple_delegated_lookup.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_gns_simple_get_authority.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_gns_simple_lookup.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_gns_simple_mx_lookup.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_gns_simple_shorten.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_gns_simple_zkey_lookup.Po@am__quote@
.c.o:
@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
@@ -689,6 +1011,76 @@ uninstall-pkgcfgDATA:
echo " ( cd '$(DESTDIR)$(pkgcfgdir)' && rm -f" $$files ")"; \
cd "$(DESTDIR)$(pkgcfgdir)" && rm -f $$files
+# This directory's subdirectories are mostly independent; you can cd
+# into them and run `make' without going through this Makefile.
+# To change the values of `make' variables: instead of editing Makefiles,
+# (1) if the variable is set in `config.status', edit `config.status'
+# (which will cause the Makefiles to be regenerated when you run `make');
+# (2) otherwise, pass the desired values on the `make' command line.
+$(RECURSIVE_TARGETS):
+ @fail= failcom='exit 1'; \
+ for f in x $$MAKEFLAGS; do \
+ case $$f in \
+ *=* | --[!k]*);; \
+ *k*) failcom='fail=yes';; \
+ esac; \
+ done; \
+ dot_seen=no; \
+ target=`echo $@ | sed s/-recursive//`; \
+ list='$(SUBDIRS)'; for subdir in $$list; do \
+ echo "Making $$target in $$subdir"; \
+ if test "$$subdir" = "."; then \
+ dot_seen=yes; \
+ local_target="$$target-am"; \
+ else \
+ local_target="$$target"; \
+ fi; \
+ ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \
+ || eval $$failcom; \
+ done; \
+ if test "$$dot_seen" = "no"; then \
+ $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \
+ fi; test -z "$$fail"
+
+$(RECURSIVE_CLEAN_TARGETS):
+ @fail= failcom='exit 1'; \
+ for f in x $$MAKEFLAGS; do \
+ case $$f in \
+ *=* | --[!k]*);; \
+ *k*) failcom='fail=yes';; \
+ esac; \
+ done; \
+ dot_seen=no; \
+ case "$@" in \
+ distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \
+ *) list='$(SUBDIRS)' ;; \
+ esac; \
+ rev=''; for subdir in $$list; do \
+ if test "$$subdir" = "."; then :; else \
+ rev="$$subdir $$rev"; \
+ fi; \
+ done; \
+ rev="$$rev ."; \
+ target=`echo $@ | sed s/-recursive//`; \
+ for subdir in $$rev; do \
+ echo "Making $$target in $$subdir"; \
+ if test "$$subdir" = "."; then \
+ local_target="$$target-am"; \
+ else \
+ local_target="$$target"; \
+ fi; \
+ ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \
+ || eval $$failcom; \
+ done && test -z "$$fail"
+tags-recursive:
+ list='$(SUBDIRS)'; for subdir in $$list; do \
+ test "$$subdir" = . || ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) tags); \
+ done
+ctags-recursive:
+ list='$(SUBDIRS)'; for subdir in $$list; do \
+ test "$$subdir" = . || ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) ctags); \
+ done
+
ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
unique=`for i in $$list; do \
@@ -699,10 +1091,23 @@ ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
mkid -fID $$unique
tags: TAGS
-TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+TAGS: tags-recursive $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
$(TAGS_FILES) $(LISP)
set x; \
here=`pwd`; \
+ if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \
+ include_option=--etags-include; \
+ empty_fix=.; \
+ else \
+ include_option=--include; \
+ empty_fix=; \
+ fi; \
+ list='$(SUBDIRS)'; for subdir in $$list; do \
+ if test "$$subdir" = .; then :; else \
+ test ! -f $$subdir/TAGS || \
+ set "$$@" "$$include_option=$$here/$$subdir/TAGS"; \
+ fi; \
+ done; \
list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
unique=`for i in $$list; do \
if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
@@ -721,7 +1126,7 @@ TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
fi; \
fi
ctags: CTAGS
-CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+CTAGS: ctags-recursive $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
$(TAGS_FILES) $(LISP)
list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
unique=`for i in $$list; do \
@@ -863,26 +1268,55 @@ distdir: $(DISTFILES)
|| exit 1; \
fi; \
done
+ @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \
+ if test "$$subdir" = .; then :; else \
+ test -d "$(distdir)/$$subdir" \
+ || $(MKDIR_P) "$(distdir)/$$subdir" \
+ || exit 1; \
+ fi; \
+ done
+ @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \
+ if test "$$subdir" = .; then :; else \
+ dir1=$$subdir; dir2="$(distdir)/$$subdir"; \
+ $(am__relativize); \
+ new_distdir=$$reldir; \
+ dir1=$$subdir; dir2="$(top_distdir)"; \
+ $(am__relativize); \
+ new_top_distdir=$$reldir; \
+ echo " (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir="$$new_top_distdir" distdir="$$new_distdir" \\"; \
+ echo " am__remove_distdir=: am__skip_length_check=: am__skip_mode_fix=: distdir)"; \
+ ($(am__cd) $$subdir && \
+ $(MAKE) $(AM_MAKEFLAGS) \
+ top_distdir="$$new_top_distdir" \
+ distdir="$$new_distdir" \
+ am__remove_distdir=: \
+ am__skip_length_check=: \
+ am__skip_mode_fix=: \
+ distdir) \
+ || exit 1; \
+ fi; \
+ done
check-am: all-am
- $(MAKE) $(AM_MAKEFLAGS) $(check_PROGRAMS) $(check_SCRIPTS)
+ $(MAKE) $(AM_MAKEFLAGS) $(check_PROGRAMS)
$(MAKE) $(AM_MAKEFLAGS) check-TESTS
-check: check-am
+check: check-recursive
all-am: Makefile $(LTLIBRARIES) $(PROGRAMS) $(DATA)
install-binPROGRAMS: install-libLTLIBRARIES
-installdirs:
+installdirs: installdirs-recursive
+installdirs-am:
for dir in "$(DESTDIR)$(libdir)" "$(DESTDIR)$(plugindir)" "$(DESTDIR)$(bindir)" "$(DESTDIR)$(pkgcfgdir)"; do \
test -z "$$dir" || $(MKDIR_P) "$$dir"; \
done
-install: install-am
-install-exec: install-exec-am
-install-data: install-data-am
-uninstall: uninstall-am
+install: install-recursive
+install-exec: install-exec-recursive
+install-data: install-data-recursive
+uninstall: uninstall-recursive
install-am: all-am
@$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
-installcheck: installcheck-am
+installcheck: installcheck-recursive
install-strip:
$(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
@@ -899,85 +1333,87 @@ distclean-generic:
maintainer-clean-generic:
@echo "This command is intended for maintainers to use"
@echo "it deletes files that may require special tools to rebuild."
-clean: clean-am
+clean: clean-recursive
clean-am: clean-binPROGRAMS clean-checkPROGRAMS clean-generic \
clean-libLTLIBRARIES clean-libtool clean-pluginLTLIBRARIES \
mostlyclean-am
-distclean: distclean-am
+distclean: distclean-recursive
-rm -rf ./$(DEPDIR)
-rm -f Makefile
distclean-am: clean-am distclean-compile distclean-generic \
distclean-tags
-dvi: dvi-am
+dvi: dvi-recursive
dvi-am:
-html: html-am
+html: html-recursive
html-am:
-info: info-am
+info: info-recursive
info-am:
install-data-am: install-pkgcfgDATA install-pluginLTLIBRARIES
-install-dvi: install-dvi-am
+install-dvi: install-dvi-recursive
install-dvi-am:
install-exec-am: install-binPROGRAMS install-libLTLIBRARIES
-install-html: install-html-am
+install-html: install-html-recursive
install-html-am:
-install-info: install-info-am
+install-info: install-info-recursive
install-info-am:
install-man:
-install-pdf: install-pdf-am
+install-pdf: install-pdf-recursive
install-pdf-am:
-install-ps: install-ps-am
+install-ps: install-ps-recursive
install-ps-am:
installcheck-am:
-maintainer-clean: maintainer-clean-am
+maintainer-clean: maintainer-clean-recursive
-rm -rf ./$(DEPDIR)
-rm -f Makefile
maintainer-clean-am: distclean-am maintainer-clean-generic
-mostlyclean: mostlyclean-am
+mostlyclean: mostlyclean-recursive
mostlyclean-am: mostlyclean-compile mostlyclean-generic \
mostlyclean-libtool
-pdf: pdf-am
+pdf: pdf-recursive
pdf-am:
-ps: ps-am
+ps: ps-recursive
ps-am:
uninstall-am: uninstall-binPROGRAMS uninstall-libLTLIBRARIES \
uninstall-pkgcfgDATA uninstall-pluginLTLIBRARIES
-.MAKE: check-am install-am install-strip
+.MAKE: $(RECURSIVE_CLEAN_TARGETS) $(RECURSIVE_TARGETS) check-am \
+ ctags-recursive install-am install-strip tags-recursive
-.PHONY: CTAGS GTAGS all all-am check check-TESTS check-am clean \
- clean-binPROGRAMS clean-checkPROGRAMS clean-generic \
- clean-libLTLIBRARIES clean-libtool clean-pluginLTLIBRARIES \
- ctags distclean distclean-compile distclean-generic \
+.PHONY: $(RECURSIVE_CLEAN_TARGETS) $(RECURSIVE_TARGETS) CTAGS GTAGS \
+ all all-am check check-TESTS check-am clean clean-binPROGRAMS \
+ clean-checkPROGRAMS clean-generic clean-libLTLIBRARIES \
+ clean-libtool clean-pluginLTLIBRARIES ctags ctags-recursive \
+ distclean distclean-compile distclean-generic \
distclean-libtool distclean-tags distdir dvi dvi-am html \
html-am info info-am install install-am install-binPROGRAMS \
install-data install-data-am install-dvi install-dvi-am \
@@ -986,11 +1422,12 @@ uninstall-am: uninstall-binPROGRAMS uninstall-libLTLIBRARIES \
install-man install-pdf install-pdf-am install-pkgcfgDATA \
install-pluginLTLIBRARIES install-ps install-ps-am \
install-strip installcheck installcheck-am installdirs \
- maintainer-clean maintainer-clean-generic mostlyclean \
- mostlyclean-compile mostlyclean-generic mostlyclean-libtool \
- pdf pdf-am ps ps-am tags uninstall uninstall-am \
- uninstall-binPROGRAMS uninstall-libLTLIBRARIES \
- uninstall-pkgcfgDATA uninstall-pluginLTLIBRARIES
+ installdirs-am maintainer-clean maintainer-clean-generic \
+ mostlyclean mostlyclean-compile mostlyclean-generic \
+ mostlyclean-libtool pdf pdf-am ps ps-am tags tags-recursive \
+ uninstall uninstall-am uninstall-binPROGRAMS \
+ uninstall-libLTLIBRARIES uninstall-pkgcfgDATA \
+ uninstall-pluginLTLIBRARIES
# Tell versions [3.59,3.63) of GNU make to not export all variables.
diff --git a/src/gns/gns.conf.in b/src/gns/gns.conf.in
index 422efdb..80fb8c8 100644
--- a/src/gns/gns.conf.in
+++ b/src/gns/gns.conf.in
@@ -5,13 +5,20 @@ HOME = $SERVICEHOME
CONFIG = $DEFAULTCONFIG
BINARY = gnunet-service-gns
UNIXPATH = /tmp/gnunet-service-gns.sock
-ZONEKEY = /tmp/zonekey
-TRUSTED = bob:/tmp/bobkey
-HIJACK_DNS = YES
-OPTIONS = -L INFO
+ZONEKEY = $SERVICEHOME/gns/zonekey.zkey
+HIJACK_DNS = NO
+AUTO_IMPORT_PKEY = YES
+AUTO_IMPORT_CONFIRMATION_REQ = NO
+MAX_PARALLEL_BACKGROUND_QUERIES = 25
+DEFAULT_LOOKUP_TIMEOUT = 10
+RECORD_PUT_INTERVAL = 60
+ZONE_PUT_INTERVAL = 900
+
+[fcfsd]
+HTTPPORT = 18080
+ZONEKEY = $SERVICEHOME/fcfsd/zonekey.zkey
+HOSTNAME = localhost
+HOME = $SERVICEHOME
+CONFIG = $DEFAULTCONFIG
+BINARY = gnunet-gns-fcfsd
-# Access to this service can compromise all DNS queries in this
-# system. Thus access should be restricted to the same UID.
-# (see https://gnunet.org/gnunet-access-control-model)
-UNIX_MATCH_UID = YES
-UNIX_MATCH_GID = YES
diff --git a/src/gns/gns.h b/src/gns/gns.h
index cb47c81..408b686 100644
--- a/src/gns/gns.h
+++ b/src/gns/gns.h
@@ -18,6 +18,8 @@
Boston, MA 02111-1307, USA.
*/
+#include "gnunet_gns_service.h"
+
/**
* @file gns/gns.h
* @brief IPC messages between GNS API and GNS service
@@ -26,6 +28,13 @@
#ifndef GNS_H
#define GNS_H
+#define GNUNET_GNS_TLD "gnunet"
+#define GNUNET_GNS_TLD_ZKEY "zkey"
+#define GNUNET_GNS_DHT_MAX_UPDATE_INTERVAL 3600
+
+#define MAX_DNS_LABEL_LENGTH 63
+#define MAX_DNS_NAME_LENGTH 253
+
GNUNET_NETWORK_STRUCT_BEGIN
/**
@@ -39,21 +48,24 @@ struct GNUNET_GNS_ClientLookupMessage
struct GNUNET_MessageHeader header;
/**
- * A key. TODO some uid
+ * Unique identifier for this request (for key collisions).
*/
- GNUNET_HashCode key;
+ uint32_t id GNUNET_PACKED;
/**
- * Unique identifier for this request (for key collisions).
+ * Should we look up in the default zone?
*/
- // FIXME: unaligned
- uint64_t unique_id;
+ uint32_t use_default_zone GNUNET_PACKED;
+
+ /**
+ * If use_default_zone is empty this zone is used for lookup
+ */
+ struct GNUNET_CRYPTO_ShortHashCode zone;
/**
* the type of record to look up
*/
- // FIXME: bad type - should be of GNUNET_GNS_RecordType
- int type;
+ enum GNUNET_GNS_RecordType type;
/* Followed by the name to look up */
};
@@ -62,7 +74,7 @@ struct GNUNET_GNS_ClientLookupMessage
/**
* Message from GNS service to client: new results.
*/
-struct GNUNET_GNS_ClientResultMessage
+struct GNUNET_GNS_ClientLookupResultMessage
{
/**
* Header of type GNUNET_MESSAGE_TYPE_GNS_CLIENT_RESULT
@@ -72,26 +84,103 @@ struct GNUNET_GNS_ClientResultMessage
/**
* Unique identifier for this request (for key collisions).
*/
- // FIXME: unaligned
- uint64_t unique_id;
-
- /**
- * A key. TODO some uid
- * // FIXME: why hash?
- */
- GNUNET_HashCode key;
+ uint32_t id GNUNET_PACKED;
/**
* The number of records contained in response
*/
- uint32_t num_records;
+ uint32_t rd_count;
// FIXME: what format has a GNS_Record?
- /* followed by num_records GNUNET_GNS_Records*/
+ /* followed by rd_count GNUNET_NAMESTORE_RecordData structs*/
};
+/**
+ * Message from client to GNS service to shorten names.
+ */
+struct GNUNET_GNS_ClientShortenMessage
+{
+ /**
+ * Header of type GNUNET_MESSAGE_TYPE_GNS_CLIENT_SHORTEN
+ */
+ struct GNUNET_MessageHeader header;
+ /**
+ * Unique identifier for this request
+ */
+ uint32_t id GNUNET_PACKED;
+
+ /**
+ * Should we look up in the default zone?
+ */
+ uint32_t use_default_zone GNUNET_PACKED;
+
+ /**
+ * If use_default_zone is empty this zone is used for lookup
+ */
+ struct GNUNET_CRYPTO_ShortHashCode zone;
+
+ /* Followed by the name to shorten up */
+};
+
+
+/**
+ * Message from GNS service to client: shorten result.
+ */
+struct GNUNET_GNS_ClientShortenResultMessage
+{
+ /**
+ * Header of type GNUNET_MESSAGE_TYPE_GNS_CLIENT_SHORTEN_RESULT
+ */
+ struct GNUNET_MessageHeader header;
+
+ /**
+ * Unique identifier for this request (for key collisions).
+ */
+ uint32_t id GNUNET_PACKED;
+
+ /* followed by the shortened name or '\0' for no result*/
+
+};
+
+/**
+ * Message from client to GNS service to lookup an authority of a name.
+ */
+struct GNUNET_GNS_ClientGetAuthMessage
+{
+ /**
+ * Header of type GNUNET_MESSAGE_TYPE_GNS_CLIENT_GET_AUTH
+ */
+ struct GNUNET_MessageHeader header;
+
+ /**
+ * Unique identifier for this request
+ */
+ uint32_t id GNUNET_PACKED;
+
+ /* Followed by the name to get authority for */
+};
+
+
+/**
+ * Message from GNS service to client: authority result.
+ */
+struct GNUNET_GNS_ClientGetAuthResultMessage
+{
+ /**
+ * Header of type GNUNET_MESSAGE_TYPE_GNS_CLIENT_GET_AUTH_RESULT
+ */
+ struct GNUNET_MessageHeader header;
+
+ /**
+ * Unique identifier for this request (for key collisions).
+ */
+ uint32_t id GNUNET_PACKED;
+
+ /* followed by the authority part of the name or '\0' for no result*/
+
+};
GNUNET_NETWORK_STRUCT_END
#endif
diff --git a/src/gns/gns_api.c b/src/gns/gns_api.c
index ec9c159..a92280f 100644
--- a/src/gns/gns_api.c
+++ b/src/gns/gns_api.c
@@ -19,7 +19,6 @@
*/
/**
- * TODO: Do we really need a client API?
*
* @file gns/gns_api.c
* @brief library to access the GNS service
@@ -36,111 +35,73 @@
#include "gns.h"
#include "gnunet_gns_service.h"
-#define DEBUG_GNS_API GNUNET_EXTRA_LOGGING
-
-#define LOG(kind,...) GNUNET_log_from (kind, "gns-api",__VA_ARGS__)
-
/* TODO into gnunet_protocols */
-#define GNUNET_MESSAGE_TYPE_GNS_CLIENT_LOOKUP 23
-#define GNUNET_MESSAGE_TYPE_GNS_CLIENT_RESULT 24
+#define GNUNET_MESSAGE_TYPE_GNS_LOOKUP 23
+#define GNUNET_MESSAGE_TYPE_GNS_LOOKUP_RESULT 24
+#define GNUNET_MESSAGE_TYPE_GNS_SHORTEN 25
+#define GNUNET_MESSAGE_TYPE_GNS_SHORTEN_RESULT 26
+#define GNUNET_MESSAGE_TYPE_GNS_GET_AUTH 27
+#define GNUNET_MESSAGE_TYPE_GNS_GET_AUTH_RESULT 28
/**
- * Entry in our list of messages to be (re-)transmitted.
+ * A QueueEntry.
*/
-struct PendingMessage
+struct GNUNET_GNS_QueueEntry
{
/**
- * This is a doubly-linked list.
- */
- struct PendingMessage *prev;
-
- /**
- * This is a doubly-linked list.
- */
- struct PendingMessage *next;
-
- /**
- * Message that is pending, allocated at the end
- * of this struct.
- */
- const struct GNUNET_MessageHeader *msg;
-
- /**
- * Handle to the GNS API context.
- */
- struct GNUNET_GNS_Handle *handle;
-
- /**
- * Continuation to call when the request has been
- * transmitted (for the first time) to the service; can be NULL.
- */
- GNUNET_SCHEDULER_Task cont;
-
- /**
- * Closure for 'cont'.
- */
- void *cont_cls;
-
- /**
- * Timeout task for this message
- */
- GNUNET_SCHEDULER_TaskIdentifier timeout_task;
-
- /**
- * Unique ID for this request
- */
- uint64_t unique_id;
-
- /**
- * Free the saved message once sent, set to GNUNET_YES for messages
- * that do not receive responses; GNUNET_NO if this pending message
- * is aliased from a 'struct GNUNET_DHT_RouteHandle' and will be freed
- * from there.
+ * DLL
*/
-
- int free_on_send;
+ struct GNUNET_GNS_QueueEntry *next;
+
/**
- * GNUNET_YES if this message is in our pending queue right now.
+ * DLL
*/
- int in_pending_queue;
+ struct GNUNET_GNS_QueueEntry *prev;
+ /* request id */
+ uint32_t r_id;
+
+ /* handle to gns */
+ struct GNUNET_GNS_Handle *gns_handle;
+
+ /* processor to call on shorten result */
+ GNUNET_GNS_ShortenResultProcessor shorten_proc;
+
+ /* processor to call on lookup result */
+ GNUNET_GNS_LookupResultProcessor lookup_proc;
+
+ /* processor to call on authority lookup result */
+ GNUNET_GNS_GetAuthResultProcessor auth_proc;
+
+ /* processor closure */
+ void *proc_cls;
+
};
+
/**
- * Handle to a Lookup request
+ * Entry in our list of messages to be (re-)transmitted.
*/
-struct GNUNET_GNS_LookupHandle
+struct PendingMessage
{
-
- /**
- * Iterator to call on data receipt
- */
- GNUNET_GNS_LookupIterator iter;
-
- /**
- * Closure for the iterator callback
- */
- void *iter_cls;
-
/**
- * Main handle to this GNS api
+ * This is a doubly-linked list.
*/
- struct GNUNET_GNS_Handle *gns_handle;
+ struct PendingMessage *prev;
/**
- * Key that this get request is for
+ * This is a doubly-linked list.
*/
- GNUNET_HashCode key;
+ struct PendingMessage *next;
/**
- * Unique identifier for this request (for key collisions).
+ * Size of the message.
*/
- uint64_t unique_id;
-
- struct PendingMessage *message;
+ size_t size;
};
+
/**
* Connection to the GNS service.
*/
@@ -161,39 +122,63 @@ struct GNUNET_GNS_Handle
* Currently pending transmission request (or NULL).
*/
struct GNUNET_CLIENT_TransmitHandle *th;
-
+
+ uint32_t r_id;
+
/**
- * Head of linked list of messages we would like to transmit.
+ * Head of linked list of shorten messages we would like to transmit.
*/
struct PendingMessage *pending_head;
/**
- * Tail of linked list of messages we would like to transmit.
+ * Tail of linked list of shorten messages we would like to transmit.
*/
struct PendingMessage *pending_tail;
+
+ /**
+ * Head of linked list of shorten messages we would like to transmit.
+ */
+ struct GNUNET_GNS_QueueEntry *shorten_head;
/**
- * Hash map containing the current outstanding unique requests.
+ * Tail of linked list of shorten messages we would like to transmit.
+ */
+ struct GNUNET_GNS_QueueEntry *shorten_tail;
+
+ /**
+ * Head of linked list of lookup messages we would like to transmit.
*/
- struct GNUNET_CONTAINER_MultiHashMap *active_requests;
+ struct GNUNET_GNS_QueueEntry *lookup_head;
- GNUNET_SCHEDULER_TaskIdentifier reconnect_task;
+ /**
+ * Tail of linked list of lookup messages we would like to transmit.
+ */
+ struct GNUNET_GNS_QueueEntry *lookup_tail;
+
+ /**
+ * Head of linked list of authority lookup messages we would like to transmit.
+ */
+ struct GNUNET_GNS_QueueEntry *get_auth_head;
/**
- * How quickly should we retry? Used for exponential back-off on
- * connect-errors.
+ * Tail of linked list of authority lookup messages we would like to transmit.
*/
- struct GNUNET_TIME_Relative retry_time;
+ struct GNUNET_GNS_QueueEntry *get_auth_tail;
/**
- * Generator for unique ids.
+ * Reconnect task
*/
- uint64_t uid_gen;
+ GNUNET_SCHEDULER_TaskIdentifier reconnect_task;
/**
* Did we start our receive loop yet?
*/
int in_receive;
+
+ /**
+ * Reconnect necessary
+ */
+ int reconnect;
};
/**
@@ -203,112 +188,52 @@ struct GNUNET_GNS_Handle
static void
process_pending_messages (struct GNUNET_GNS_Handle *handle);
-/**
- * Try to (re)connect to the GNS service.
- *
- * @return GNUNET_YES on success, GNUNET_NO on failure.
- */
-static int
-try_connect (struct GNUNET_GNS_Handle *handle)
-{
- if (handle->client != NULL)
- return GNUNET_OK;
- handle->in_receive = GNUNET_NO;
- handle->client = GNUNET_CLIENT_connect ("gns", handle->cfg);
- if (handle->client == NULL)
- {
- LOG (GNUNET_ERROR_TYPE_WARNING,
- _("Failed to connect to the GNS service!\n"));
- return GNUNET_NO;
- }
- return GNUNET_YES;
-}
/**
- * Add the request corresponding to the given handle
- * to the pending queue (if it is not already in there).
+ * Reconnect to GNS service.
*
- * @param cls the 'struct GNUNET_GNS_Handle*'
- * @param key key for the request (not used)
- * @param value the 'struct GNUNET_GNS_LookupHandle*'
- * @return GNUNET_YES (always)
+ * @param h the handle to the namestore service
*/
-static int
-add_request_to_pending (void *cls, const GNUNET_HashCode * key, void *value)
+static void
+reconnect (struct GNUNET_GNS_Handle *h)
{
- struct GNUNET_GNS_Handle *handle = cls;
- struct GNUNET_GNS_LookupHandle *rh = value;
-
- if (GNUNET_NO == rh->message->in_pending_queue)
- {
-#if DEBUG_DHT
- LOG (GNUNET_ERROR_TYPE_DEBUG,
- "Retransmitting request related to %s to GNS %p\n", GNUNET_h2s(key),
- handle);
-#endif
- GNUNET_CONTAINER_DLL_insert (handle->pending_head, handle->pending_tail,
- rh->message);
- rh->message->in_pending_queue = GNUNET_YES;
- }
- return GNUNET_YES;
+ GNUNET_assert (NULL == h->client);
+ GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
+ "Trying to connect to GNS...\n");
+ h->client = GNUNET_CLIENT_connect ("gns", h->cfg);
+ GNUNET_assert (NULL != h->client);
}
/**
- * Try reconnecting to the GNS service.
+ * Reconnect to GNS
*
- * @param cls GNUNET_GNS_Handle
- * @param tc scheduler context
+ * @param cls the handle
+ * @param tc task context
*/
static void
-try_reconnect (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
+reconnect_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
{
- struct GNUNET_GNS_Handle *handle = cls;
+ struct GNUNET_GNS_Handle *h = cls;
-#if DEBUG_GNS
- LOG (GNUNET_ERROR_TYPE_DEBUG, "Reconnecting with GNS %p\n", handle);
-#endif
- handle->reconnect_task = GNUNET_SCHEDULER_NO_TASK;
- if (handle->retry_time.rel_value < GNUNET_CONSTANTS_SERVICE_RETRY.rel_value)
- handle->retry_time = GNUNET_CONSTANTS_SERVICE_RETRY;
- else
- handle->retry_time = GNUNET_TIME_relative_multiply (handle->retry_time, 2);
- if (handle->retry_time.rel_value > GNUNET_CONSTANTS_SERVICE_TIMEOUT.rel_value)
- handle->retry_time = GNUNET_CONSTANTS_SERVICE_TIMEOUT;
- handle->reconnect_task = GNUNET_SCHEDULER_NO_TASK;
- if (GNUNET_YES != try_connect (handle))
- {
-#if DEBUG_GNS
- LOG (GNUNET_ERROR_TYPE_DEBUG, "GNS reconnect failed(!)\n");
-#endif
- return;
- }
- GNUNET_CONTAINER_multihashmap_iterate (handle->active_requests,
- &add_request_to_pending, handle);
- process_pending_messages (handle);
+ h->reconnect_task = GNUNET_SCHEDULER_NO_TASK;
+ reconnect (h);
}
/**
- * Try reconnecting to the GNS service.
+ * Disconnect from service and then reconnect.
*
- * @param handle handle to gns to (possibly) disconnect and reconnect
+ * @param h our handle
*/
static void
-do_disconnect (struct GNUNET_GNS_Handle *handle)
+force_reconnect (struct GNUNET_GNS_Handle *h)
{
- if (handle->client == NULL)
- return;
- GNUNET_assert (handle->reconnect_task == GNUNET_SCHEDULER_NO_TASK);
- if (NULL != handle->th)
- GNUNET_CLIENT_notify_transmit_ready_cancel (handle->th);
- handle->th = NULL;
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Disconnecting from GNS service, will try to reconnect in %llu ms\n",
- (unsigned long long) handle->retry_time.rel_value);
- GNUNET_CLIENT_disconnect (handle->client, GNUNET_NO);
- handle->client = NULL;
- handle->reconnect_task =
- GNUNET_SCHEDULER_add_delayed (handle->retry_time, &try_reconnect, handle);
+ h->reconnect = GNUNET_NO;
+ GNUNET_CLIENT_disconnect (h->client);
+ h->client = NULL;
+ h->reconnect_task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_SECONDS,
+ &reconnect_task,
+ h);
}
/**
@@ -324,7 +249,7 @@ transmit_pending (void *cls, size_t size, void *buf);
* @param msg the incoming message
*/
static void
-message_handler (void *cls, const struct GNUNET_MessageHeader *msg);
+process_message (void *cls, const struct GNUNET_MessageHeader *msg);
/**
* Try to send messages from list of messages to send
@@ -332,30 +257,35 @@ message_handler (void *cls, const struct GNUNET_MessageHeader *msg);
static void
process_pending_messages (struct GNUNET_GNS_Handle *handle)
{
- struct PendingMessage *head;
+ struct PendingMessage *p;
if (handle->client == NULL)
{
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "process_pending_messages called, but client is null, reconnecting\n");
- do_disconnect (handle);
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "process_pending_messages called, but client is null\n");
return;
}
+
if (handle->th != NULL)
return;
- if (NULL == (head = handle->pending_head))
+
+ if (NULL == (p = handle->pending_head))
return;
+
+ GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
+ "Trying to transmit %d bytes...\n", p->size);
+
handle->th =
GNUNET_CLIENT_notify_transmit_ready (handle->client,
- ntohs (head->msg->size),
+ p->size,
GNUNET_TIME_UNIT_FOREVER_REL,
- GNUNET_YES, &transmit_pending,
+ GNUNET_NO, &transmit_pending,
handle);
if (NULL != handle->th)
return;
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "notify_transmit_ready returned NULL, reconnecting\n");
- do_disconnect (handle);
+
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "notify_transmit_ready returned NULL!\n");
}
@@ -366,51 +296,45 @@ static size_t
transmit_pending (void *cls, size_t size, void *buf)
{
struct GNUNET_GNS_Handle *handle = cls;
- struct PendingMessage *head;
+ struct PendingMessage *p;
size_t tsize;
+ char *cbuf;
handle->th = NULL;
- if (buf == NULL)
+
+ if ((size == 0) || (buf == NULL))
{
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Transmission to GNS service failed! Reconnecting!\n");
- do_disconnect (handle);
+ "Transmission to GNS service failed!\n");
+ force_reconnect(handle);
return 0;
}
- if (NULL == (head = handle->pending_head))
- return 0;
+
+ tsize = 0;
+ cbuf = buf;
- tsize = ntohs (head->msg->size);
- if (size < tsize)
- {
- process_pending_messages (handle);
+ if (NULL == (p = handle->pending_head))
return 0;
- }
- memcpy (buf, head->msg, tsize);
- GNUNET_CONTAINER_DLL_remove (handle->pending_head, handle->pending_tail,
- head);
- head->in_pending_queue = GNUNET_NO;
- if (head->timeout_task != GNUNET_SCHEDULER_NO_TASK)
- {
- GNUNET_SCHEDULER_cancel (head->timeout_task);
- head->timeout_task = GNUNET_SCHEDULER_NO_TASK;
- }
- if (GNUNET_YES == head->free_on_send)
- GNUNET_free (head);
- process_pending_messages (handle);
-#if DEBUG_GNS
- LOG (GNUNET_ERROR_TYPE_DEBUG,
- "Forwarded request of %u bytes to GNS service\n", (unsigned int) tsize);
-#endif
- if (GNUNET_NO == handle->in_receive)
+
+ while ((NULL != (p = handle->pending_head)) && (p->size <= size))
{
-#if DEBUG_GNS
- LOG (GNUNET_ERROR_TYPE_DEBUG, "Starting to process replies from GNS\n");
-#endif
- handle->in_receive = GNUNET_YES;
- GNUNET_CLIENT_receive (handle->client, &message_handler, handle,
- GNUNET_TIME_UNIT_FOREVER_REL);
+ memcpy (&cbuf[tsize], &p[1], p->size);
+ tsize += p->size;
+ size -= p->size;
+ GNUNET_CONTAINER_DLL_remove (handle->pending_head, handle->pending_tail, p);
+ if (GNUNET_YES != handle->in_receive)
+ {
+ GNUNET_CLIENT_receive (handle->client, &process_message, handle,
+ GNUNET_TIME_UNIT_FOREVER_REL);
+ handle->in_receive = GNUNET_YES;
+ }
+ GNUNET_free(p);
}
+
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Sending %d bytes\n", tsize);
+
+ process_pending_messages(handle);
return tsize;
}
@@ -418,54 +342,126 @@ transmit_pending (void *cls, size_t size, void *buf)
* Process a given reply that might match the given
* request.
*
- * @param cls the 'struct GNUNET_GNS_ClientResultMessage'
- * @param key query of the request
- * @param value the 'struct GNUNET_GNS_LookupHandle' of a request matching the same key
- * @return GNUNET_YES to continue to iterate over all results,
- * GNUNET_NO if the reply is malformed
+ * @param qe a queue entry
+ * @param msg the shorten msg received
*/
-static int
-process_reply (void *cls, const GNUNET_HashCode * key, void *value)
+static void
+process_shorten_reply (struct GNUNET_GNS_QueueEntry *qe,
+ const struct GNUNET_GNS_ClientShortenResultMessage *msg)
{
- const struct GNUNET_GNS_ClientResultMessage *gns_msg = cls;
- struct GNUNET_GNS_LookupHandle *lookup_handle = value;
- const char *name = (const char*) &lookup_handle[1];
- const struct GNUNET_NAMESTORE_RecordData *records;
- uint32_t num_records;
- size_t meta_length;
- size_t msize;
+ struct GNUNET_GNS_Handle *h = qe->gns_handle;
+ const char *short_name;
+
+ GNUNET_CONTAINER_DLL_remove(h->shorten_head, h->shorten_tail, qe);
- if (gns_msg->unique_id != lookup_handle->unique_id)
+ short_name = (char*)(&msg[1]);
+
+ if (ntohs (((struct GNUNET_MessageHeader*)msg)->size) <
+ sizeof (struct GNUNET_GNS_ClientShortenResultMessage))
{
- /* UID mismatch */
-#if DEBUG_GNS
- LOG (GNUNET_ERROR_TYPE_DEBUG,
- "Ignoring reply for %s: UID mismatch: %llu/%llu\n", GNUNET_h2s (key),
- gns_msg->unique_id, lookup_handle->unique_id);
-#endif
- return GNUNET_YES;
+ GNUNET_break (0);
+ force_reconnect (h);
+ GNUNET_free(qe);
+ return;
}
- msize = ntohs (gns_msg->header.size);
- num_records = ntohl (gns_msg->num_records);
- meta_length =
- sizeof (struct GNUNET_GNS_ClientResultMessage) +
- sizeof (struct GNUNET_NAMESTORE_RecordData) * (num_records);
- if ((msize < meta_length) ||
- (num_records >
- GNUNET_SERVER_MAX_MESSAGE_SIZE / sizeof (struct GNUNET_NAMESTORE_RecordData)))
+
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Received shortened reply `%s' from GNS service\n",
+ short_name);
+
+ GNUNET_CLIENT_receive (h->client, &process_message, h,
+ GNUNET_TIME_UNIT_FOREVER_REL);
+ qe->shorten_proc(qe->proc_cls, short_name);
+ GNUNET_free(qe);
+
+}
+
+
+/**
+ * Process a given reply that might match the given
+ * request.
+ *
+ * @param qe the handle to the request
+ * @param msg the message to process
+ */
+static void
+process_get_auth_reply (struct GNUNET_GNS_QueueEntry *qe,
+ const struct GNUNET_GNS_ClientGetAuthResultMessage *msg)
+{
+ struct GNUNET_GNS_Handle *h = qe->gns_handle;
+ const char *auth_name;
+
+ GNUNET_CONTAINER_DLL_remove(h->get_auth_head, h->get_auth_tail, qe);
+
+ auth_name = (char*)(&msg[1]);
+
+ if (ntohs (((struct GNUNET_MessageHeader*)msg)->size) <
+ sizeof (struct GNUNET_GNS_ClientGetAuthResultMessage))
{
+ GNUNET_free(qe);
GNUNET_break (0);
- return GNUNET_NO;
+ force_reconnect (h);
+ return;
}
-#if DEBUG_GNS
- LOG (GNUNET_ERROR_TYPE_DEBUG, "Giving %u byte reply for %s to application\n",
- (unsigned int) (msize - meta_length), GNUNET_h2s (key));
-#endif
- records = (const struct GNUNET_NAMESTORE_RecordData *) &gns_msg[1];
- lookup_handle->iter (lookup_handle->iter_cls, name, records, num_records);
- return GNUNET_YES;
+
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Received GET_AUTH reply `%s' from GNS service\n",
+ auth_name);
+
+ GNUNET_CLIENT_receive (h->client, &process_message, h,
+ GNUNET_TIME_UNIT_FOREVER_REL);
+ qe->auth_proc(qe->proc_cls, auth_name);
+ GNUNET_free(qe);
+
}
+/**
+ * Process a given reply to the lookup request
+ *
+ * @param qe a queue entry
+ * @param msg the lookup message received
+ */
+static void
+process_lookup_reply (struct GNUNET_GNS_QueueEntry *qe,
+ const struct GNUNET_GNS_ClientLookupResultMessage *msg)
+{
+ struct GNUNET_GNS_Handle *h = qe->gns_handle;
+ int rd_count = ntohl(msg->rd_count);
+ size_t len = ntohs (((struct GNUNET_MessageHeader*)msg)->size);
+ struct GNUNET_NAMESTORE_RecordData rd[rd_count];
+
+ GNUNET_CONTAINER_DLL_remove(h->lookup_head, h->lookup_tail, qe);
+
+ if (len < sizeof (struct GNUNET_GNS_ClientLookupResultMessage))
+ {
+ GNUNET_free(qe);
+ GNUNET_break (0);
+ force_reconnect (h);
+ return;
+ }
+
+ len -= sizeof(struct GNUNET_GNS_ClientLookupResultMessage);
+ GNUNET_CLIENT_receive (h->client, &process_message, h,
+ GNUNET_TIME_UNIT_FOREVER_REL);
+ if (GNUNET_SYSERR == GNUNET_NAMESTORE_records_deserialize (len,
+ (char*)&msg[1],
+ rd_count,
+ rd))
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "Failed to serialize lookup reply from GNS service!\n");
+ qe->lookup_proc(qe->proc_cls, 0, NULL);
+ }
+ else
+ {
+
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Received lookup reply from GNS service (count=%d)\n",
+ ntohl(msg->rd_count));
+ qe->lookup_proc(qe->proc_cls, rd_count, rd);
+ }
+ GNUNET_free(qe);
+}
/**
* Handler for messages received from the GNS service
@@ -474,43 +470,112 @@ process_reply (void *cls, const GNUNET_HashCode * key, void *value)
* @param msg the incoming message
*/
static void
-message_handler (void *cls, const struct GNUNET_MessageHeader *msg)
+process_message (void *cls, const struct GNUNET_MessageHeader *msg)
{
struct GNUNET_GNS_Handle *handle = cls;
- const struct GNUNET_GNS_ClientResultMessage *gns_msg;
-
+ struct GNUNET_GNS_QueueEntry *qe;
+ const struct GNUNET_GNS_ClientLookupResultMessage *lookup_msg;
+ const struct GNUNET_GNS_ClientShortenResultMessage *shorten_msg;
+ const struct GNUNET_GNS_ClientGetAuthResultMessage *get_auth_msg;
+ uint16_t type;
+ uint32_t r_id;
+
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Got message\n");
if (msg == NULL)
{
-#if DEBUG_GNS
- LOG (GNUNET_ERROR_TYPE_DEBUG,
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
"Error receiving data from GNS service, reconnecting\n");
-#endif
- do_disconnect (handle);
+ force_reconnect (handle);
return;
}
- if (ntohs (msg->type) != GNUNET_MESSAGE_TYPE_GNS_CLIENT_RESULT)
+
+ type = ntohs (msg->type);
+
+ if (type == GNUNET_MESSAGE_TYPE_GNS_LOOKUP_RESULT)
{
- GNUNET_break (0);
- do_disconnect (handle);
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Got lookup msg\n");
+ lookup_msg = (const struct GNUNET_GNS_ClientLookupResultMessage *) msg;
+ r_id = ntohl (lookup_msg->id);
+
+ if (r_id > handle->r_id)
+ {
+ /** no request found */
+ GNUNET_break_op (0);
+ GNUNET_CLIENT_receive (handle->client, &process_message, handle,
+ GNUNET_TIME_UNIT_FOREVER_REL);
+ return;
+ }
+
+ for (qe = handle->lookup_head; qe != NULL; qe = qe->next)
+ {
+ if (qe->r_id == r_id)
+ break;
+ }
+ if (qe)
+ process_lookup_reply(qe, lookup_msg);
+
return;
+
}
- if (ntohs (msg->size) < sizeof (struct GNUNET_GNS_ClientResultMessage))
+ else if (type == GNUNET_MESSAGE_TYPE_GNS_SHORTEN_RESULT)
{
- GNUNET_break (0);
- do_disconnect (handle);
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Got SHORTEN_RESULT msg\n");
+ shorten_msg = (struct GNUNET_GNS_ClientShortenResultMessage *) msg;
+
+ r_id = ntohl (shorten_msg->id);
+
+ if (r_id > handle->r_id)
+ {
+ /** no request found */
+ GNUNET_break_op (0);
+ GNUNET_CLIENT_receive (handle->client, &process_message, handle,
+ GNUNET_TIME_UNIT_FOREVER_REL);
+ return;
+ }
+
+ for (qe = handle->shorten_head; qe != NULL; qe = qe->next)
+ {
+ if (qe->r_id == r_id)
+ break;
+ }
+ if (qe)
+ process_shorten_reply(qe, shorten_msg);
return;
}
- gns_msg = (const struct GNUNET_GNS_ClientResultMessage *) msg;
-#if DEBUG_GNS
- LOG (GNUNET_ERROR_TYPE_DEBUG, "Received reply for `%s' from GNS service %p\n",
- &gns_msg->name, handle);
-#endif
- /* TODO uniquely identify requests... maybe hash(name) or uid */
- GNUNET_CONTAINER_multihashmap_get_multiple (handle->active_requests,
- &gns_msg->key, &process_reply,
- (void *) gns_msg);
- GNUNET_CLIENT_receive (handle->client, &message_handler, handle,
- GNUNET_TIME_UNIT_FOREVER_REL);
+ else if (type == GNUNET_MESSAGE_TYPE_GNS_GET_AUTH_RESULT)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Got GET_AUTH_RESULT msg\n");
+ get_auth_msg = (struct GNUNET_GNS_ClientGetAuthResultMessage *) msg;
+
+ r_id = ntohl (get_auth_msg->id);
+
+ if (r_id > handle->r_id)
+ {
+ /** no request found */
+ GNUNET_break_op (0);
+ GNUNET_CLIENT_receive (handle->client, &process_message, handle,
+ GNUNET_TIME_UNIT_FOREVER_REL);
+ return;
+ }
+
+ for (qe = handle->get_auth_head; qe != NULL; qe = qe->next)
+ {
+ if (qe->r_id == r_id)
+ break;
+ }
+ if (qe)
+ process_get_auth_reply(qe, get_auth_msg);
+ return;
+ }
+
+
+ if (GNUNET_YES == handle->reconnect)
+ force_reconnect (handle);
+
}
@@ -518,25 +583,21 @@ message_handler (void *cls, const struct GNUNET_MessageHeader *msg)
* Initialize the connection with the GNS service.
*
* @param cfg configuration to use
- * @param ht_len size of the internal hash table to use for parallel requests
* @return handle to the GNS service, or NULL on error
*/
struct GNUNET_GNS_Handle *
-GNUNET_GNS_connect (const struct GNUNET_CONFIGURATION_Handle *cfg,
- unsigned int ht_len)
+GNUNET_GNS_connect (const struct GNUNET_CONFIGURATION_Handle *cfg)
{
struct GNUNET_GNS_Handle *handle;
handle = GNUNET_malloc (sizeof (struct GNUNET_GNS_Handle));
+ handle->reconnect = GNUNET_NO;
handle->cfg = cfg;
- handle->uid_gen =
- GNUNET_CRYPTO_random_u64 (GNUNET_CRYPTO_QUALITY_WEAK, UINT64_MAX);
- handle->active_requests = GNUNET_CONTAINER_multihashmap_create (ht_len);
- if (GNUNET_NO == try_connect (handle))
- {
- GNUNET_GNS_disconnect (handle);
- return NULL;
- }
+ reconnect (handle);
+ //handle->reconnect_task = GNUNET_SCHEDULER_add_now (&reconnect_task, handle);
+ handle->reconnect_task = GNUNET_SCHEDULER_NO_TASK;
+ handle->r_id = 0;
+ handle->in_receive = GNUNET_NO;
return handle;
}
@@ -549,35 +610,52 @@ GNUNET_GNS_connect (const struct GNUNET_CONFIGURATION_Handle *cfg,
void
GNUNET_GNS_disconnect (struct GNUNET_GNS_Handle *handle)
{
+ GNUNET_CLIENT_disconnect (handle->client);
+ if (GNUNET_SCHEDULER_NO_TASK != handle->reconnect_task)
+ {
+ GNUNET_SCHEDULER_cancel (handle->reconnect_task);
+ handle->reconnect_task = GNUNET_SCHEDULER_NO_TASK;
+ }
+ GNUNET_free(handle);
/* disco from GNS */
}
+/*
+ * Helper function to generate request ids
+ *
+ * @param h handle
+ * @return a new id
+ */
+static uint32_t
+get_request_id (struct GNUNET_GNS_Handle *h)
+{
+ uint32_t r_id = h->r_id;
+ h->r_id++;
+ return r_id;
+}
/**
* Perform an asynchronous Lookup operation on the GNS.
- * TODO:
- * - Still not sure what we query for... "names" it is for now
- * - Do we need such sophisticated message queueing like dht? simplify?
*
* @param handle handle to the GNS service
- * @param timeout how long to wait for transmission of this request to the service
* @param name the name to look up
- * @param iter function to call on each result
- * @param iter_cls closure for iter
- * @return handle to stop the async get
+ * @param zone the zone to start the resolution in
+ * @param type the record type to look up
+ * @param proc processor to call on result
+ * @param proc_cls closure for processor
+ * @return handle to the get
*/
-struct GNUNET_GNS_LookupHandle *
-GNUNET_GNS_lookup_start (struct GNUNET_GNS_Handle *handle,
- struct GNUNET_TIME_Relative timeout,
- const char * name,
- enum GNUNET_GNS_RecordType type,
- GNUNET_GNS_LookupIterator iter,
- void *iter_cls)
+struct GNUNET_GNS_QueueEntry *
+GNUNET_GNS_lookup_zone (struct GNUNET_GNS_Handle *handle,
+ const char * name,
+ struct GNUNET_CRYPTO_ShortHashCode *zone,
+ enum GNUNET_GNS_RecordType type,
+ GNUNET_GNS_LookupResultProcessor proc,
+ void *proc_cls)
{
- /* IPC to look for local entries, start dht lookup, return lookup_handle */
+ /* IPC to shorten gns names, return shorten_handle */
struct GNUNET_GNS_ClientLookupMessage *lookup_msg;
- struct GNUNET_GNS_LookupHandle *lookup_handle;
- GNUNET_HashCode key;
+ struct GNUNET_GNS_QueueEntry *qe;
size_t msize;
struct PendingMessage *pending;
@@ -586,49 +664,210 @@ GNUNET_GNS_lookup_start (struct GNUNET_GNS_Handle *handle,
return NULL;
}
- GNUNET_CRYPTO_hash (name, strlen(name), &key);
+ msize = sizeof (struct GNUNET_GNS_ClientLookupMessage) + strlen(name) + 1;
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Trying to lookup %s in GNS\n", name);
+
+ qe = GNUNET_malloc(sizeof (struct GNUNET_GNS_QueueEntry));
+ qe->gns_handle = handle;
+ qe->lookup_proc = proc;
+ qe->proc_cls = proc_cls;
+ qe->r_id = get_request_id(handle);
+ GNUNET_CONTAINER_DLL_insert_tail(handle->lookup_head,
+ handle->lookup_tail, qe);
- msize = sizeof (struct GNUNET_GNS_ClientLookupMessage) + strlen(name);
-#if DEBUG_GNS
- LOG (GNUNET_ERROR_TYPE_DEBUG, "Starting lookup for %s in GNS %p\n",
- name, handle);
-#endif
pending = GNUNET_malloc (sizeof (struct PendingMessage) + msize);
+ memset(pending, 0, (sizeof (struct PendingMessage) + msize));
+
+ pending->size = msize;
+
lookup_msg = (struct GNUNET_GNS_ClientLookupMessage *) &pending[1];
- pending->msg = &lookup_msg->header;
- pending->handle = handle;
- pending->free_on_send = GNUNET_NO;
+ lookup_msg->header.type = htons (GNUNET_MESSAGE_TYPE_GNS_LOOKUP);
lookup_msg->header.size = htons (msize);
- lookup_msg->header.type = htons (GNUNET_MESSAGE_TYPE_GNS_CLIENT_LOOKUP);
- lookup_msg->key = key;
+ lookup_msg->id = htonl(qe->r_id);
+
+ if (NULL != zone)
+ {
+ lookup_msg->use_default_zone = htonl(0);
+ memcpy(&lookup_msg->zone, zone, sizeof(struct GNUNET_CRYPTO_ShortHashCode));
+ }
+ else
+ {
+ lookup_msg->use_default_zone = htonl(1);
+ memset(&lookup_msg->zone, 0, sizeof(struct GNUNET_CRYPTO_ShortHashCode));
+ }
+
+ lookup_msg->type = htonl(type);
+
memcpy(&lookup_msg[1], name, strlen(name));
- handle->uid_gen++;
- lookup_msg->unique_id = handle->uid_gen;
- GNUNET_CONTAINER_DLL_insert (handle->pending_head, handle->pending_tail,
+
+ GNUNET_CONTAINER_DLL_insert_tail (handle->pending_head, handle->pending_tail,
pending);
- pending->in_pending_queue = GNUNET_YES;
- lookup_handle = GNUNET_malloc (sizeof (struct GNUNET_GNS_LookupHandle));
- lookup_handle->iter = iter;
- lookup_handle->iter_cls = iter_cls;
- lookup_handle->message = pending;
- lookup_handle->unique_id = lookup_msg->unique_id;
- GNUNET_CONTAINER_multihashmap_put (handle->active_requests, &lookup_msg->key,
- lookup_handle,
- GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE);
+
process_pending_messages (handle);
- return lookup_handle;
+ return qe;
}
+/**
+ * Perform an asynchronous Lookup operation on the GNS.
+ *
+ * @param handle handle to the GNS service
+ * @param name the name to look up
+ * @param type the record type to look up
+ * @param proc processor to call on result
+ * @param proc_cls closure for processor
+ * @return handle to the get
+ */
+struct GNUNET_GNS_QueueEntry *
+GNUNET_GNS_lookup (struct GNUNET_GNS_Handle *handle,
+ const char * name,
+ enum GNUNET_GNS_RecordType type,
+ GNUNET_GNS_LookupResultProcessor proc,
+ void *proc_cls)
+{
+ return GNUNET_GNS_lookup_zone (handle, name, NULL, type, proc, proc_cls);
+}
/**
- * Stop async GNS lookup.
+ * Perform a name shortening operation on the GNS.
*
- * @param lookup_handle handle to the GNS lookup operation to stop
+ * @param handle handle to the GNS service
+ * @param name the name to look up
+ * @param zone the zone to start the resolution in
+ * @param proc function to call on result
+ * @param proc_cls closure for processor
+ * @return handle to the operation
*/
-void
-GNUNET_GNS_lookup_stop (struct GNUNET_GNS_LookupHandle *lookup_handle)
+struct GNUNET_GNS_QueueEntry *
+GNUNET_GNS_shorten_zone (struct GNUNET_GNS_Handle *handle,
+ const char * name,
+ struct GNUNET_CRYPTO_ShortHashCode *zone,
+ GNUNET_GNS_ShortenResultProcessor proc,
+ void *proc_cls)
{
- /* TODO Stop dht lookups */
+ /* IPC to shorten gns names, return shorten_handle */
+ struct GNUNET_GNS_ClientShortenMessage *shorten_msg;
+ struct GNUNET_GNS_QueueEntry *qe;
+ size_t msize;
+ struct PendingMessage *pending;
+
+ if (NULL == name)
+ {
+ return NULL;
+ }
+
+ msize = sizeof (struct GNUNET_GNS_ClientShortenMessage) + strlen(name) + 1;
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Trying to shorten %s in GNS\n", name);
+
+ qe = GNUNET_malloc(sizeof (struct GNUNET_GNS_QueueEntry));
+ qe->gns_handle = handle;
+ qe->shorten_proc = proc;
+ qe->proc_cls = proc_cls;
+ qe->r_id = get_request_id(handle);
+ GNUNET_CONTAINER_DLL_insert_tail(handle->shorten_head,
+ handle->shorten_tail, qe);
+
+ pending = GNUNET_malloc (sizeof (struct PendingMessage) + msize);
+ memset(pending, 0, (sizeof (struct PendingMessage) + msize));
+
+ pending->size = msize;
+
+ shorten_msg = (struct GNUNET_GNS_ClientShortenMessage *) &pending[1];
+ shorten_msg->header.type = htons (GNUNET_MESSAGE_TYPE_GNS_SHORTEN);
+ shorten_msg->header.size = htons (msize);
+ shorten_msg->id = htonl(qe->r_id);
+
+ if (NULL != zone)
+ {
+ shorten_msg->use_default_zone = htonl(0);
+ memcpy(&shorten_msg->zone, zone,
+ sizeof(struct GNUNET_CRYPTO_ShortHashCode));
+ }
+ else
+ {
+ shorten_msg->use_default_zone = htonl(1);
+ memset(&shorten_msg->zone, 0, sizeof(struct GNUNET_CRYPTO_ShortHashCode));
+ }
+
+ memcpy(&shorten_msg[1], name, strlen(name));
+
+ GNUNET_CONTAINER_DLL_insert_tail (handle->pending_head, handle->pending_tail,
+ pending);
+
+ process_pending_messages (handle);
+ return qe;
+}
+
+/**
+ * Perform a name shortening operation on the GNS.
+ *
+ * @param handle handle to the GNS service
+ * @param name the name to look up
+ * @param proc function to call on result
+ * @param proc_cls closure for processor
+ * @return handle to the operation
+ */
+struct GNUNET_GNS_QueueEntry *
+GNUNET_GNS_shorten (struct GNUNET_GNS_Handle *handle,
+ const char * name,
+ GNUNET_GNS_ShortenResultProcessor proc,
+ void *proc_cls)
+{
+ return GNUNET_GNS_shorten_zone (handle, name, NULL, proc, proc_cls);
+}
+/**
+ * Perform an authority lookup for a given name.
+ *
+ * @param handle handle to the GNS service
+ * @param name the name to look up authority for
+ * @param proc function to call on result
+ * @param proc_cls closure for processor
+ * @return handle to the operation
+ */
+struct GNUNET_GNS_QueueEntry *
+GNUNET_GNS_get_authority (struct GNUNET_GNS_Handle *handle,
+ const char * name,
+ GNUNET_GNS_GetAuthResultProcessor proc,
+ void *proc_cls)
+{
+ struct GNUNET_GNS_ClientGetAuthMessage *get_auth_msg;
+ struct GNUNET_GNS_QueueEntry *qe;
+ size_t msize;
+ struct PendingMessage *pending;
+
+ if (NULL == name)
+ {
+ return NULL;
+ }
+
+ msize = sizeof (struct GNUNET_GNS_ClientGetAuthMessage) + strlen(name) + 1;
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Trying to look up authority for %s in GNS\n", name);
+
+ qe = GNUNET_malloc(sizeof (struct GNUNET_GNS_QueueEntry));
+ qe->gns_handle = handle;
+ qe->auth_proc = proc;
+ qe->proc_cls = proc_cls;
+ qe->r_id = get_request_id(handle);
+ GNUNET_CONTAINER_DLL_insert_tail(handle->get_auth_head,
+ handle->get_auth_tail, qe);
+
+ pending = GNUNET_malloc (sizeof (struct PendingMessage) + msize);
+ memset(pending, 0, (sizeof (struct PendingMessage) + msize));
+
+ pending->size = msize;
+
+ get_auth_msg = (struct GNUNET_GNS_ClientGetAuthMessage *) &pending[1];
+ get_auth_msg->header.type = htons (GNUNET_MESSAGE_TYPE_GNS_GET_AUTH);
+ get_auth_msg->header.size = htons (msize);
+ get_auth_msg->id = htonl(qe->r_id);
+
+ memcpy(&get_auth_msg[1], name, strlen(name));
+
+ GNUNET_CONTAINER_DLL_insert_tail (handle->pending_head, handle->pending_tail,
+ pending);
+
+ process_pending_messages (handle);
+ return qe;
}
diff --git a/src/gns/gns_proxy_proto.h b/src/gns/gns_proxy_proto.h
new file mode 100644
index 0000000..ef30d5c
--- /dev/null
+++ b/src/gns/gns_proxy_proto.h
@@ -0,0 +1,49 @@
+
+#define SOCKS_VERSION_5 0x05
+#define SOCKS_AUTH_NONE 0
+
+/* The socks phases */
+enum
+{
+ SOCKS5_INIT,
+ SOCKS5_REQUEST,
+ SOCKS5_DATA_TRANSFER
+};
+
+/* Client hello */
+struct socks5_client_hello
+{
+ uint8_t version;
+ uint8_t num_auth_methods;
+ char* auth_methods;
+};
+
+/* Client socks request */
+struct socks5_client_request
+{
+ uint8_t version;
+ uint8_t command;
+ uint8_t resvd;
+ uint8_t addr_type;
+ /*
+ * followed by either an ip4/ipv6 address
+ * or a domain name with a length field in front
+ */
+};
+
+/* Server hello */
+struct socks5_server_hello
+{
+ uint8_t version;
+ uint8_t auth_method;
+};
+
+/* Server response to client requests */
+struct socks5_server_response
+{
+ uint8_t version;
+ uint8_t reply;
+ uint8_t reserved;
+ uint8_t addr_type;
+ uint8_t add_port[18];
+};
diff --git a/src/gns/gnunet-gns-fcfsd.c b/src/gns/gnunet-gns-fcfsd.c
new file mode 100644
index 0000000..cd4e8e7
--- /dev/null
+++ b/src/gns/gnunet-gns-fcfsd.c
@@ -0,0 +1,811 @@
+/*
+ This file is part of GNUnet.
+ (C) 2012 Christian Grothoff (and other contributing authors)
+
+ GNUnet is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 3, or (at your
+ option) any later version.
+
+ GNUnet is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GNUnet; see the file COPYING. If not, write to the
+ Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+/**
+ * @file gnunet-gns-fcfsd.c
+ * @brief HTTP daemon that offers first-come-first-serve GNS domain registration
+ * @author Christian Grothoff
+ *
+ * TODO:
+ * - the code currently contains a 'race' between checking that the
+ * domain name is available and allocating it to the new public key
+ * (should this race be solved by namestore or by fcfsd?)
+ * - nicer error reporting to browser
+ * - figure out where this binary should go (is gns the right directory!?)
+ */
+#include "platform.h"
+#include <gnunet_util_lib.h>
+#include <microhttpd.h>
+#include <gnunet_namestore_service.h>
+
+/**
+ * Invalid method page.
+ */
+#define METHOD_ERROR "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\"><html lang=\"en\" xmlns=\"http://www.w3.org/1999/xhtml\"><html><head><title>Illegal request</title></head><body>Go away.</body></html>"
+
+/**
+ * Front page. (/)
+ */
+#define MAIN_PAGE "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\"><html lang=\"en\" xmlns=\"http://www.w3.org/1999/xhtml\"><html><head><title>GNUnet FCFS Authority Name Registration Service</title></head><body><form action=\"S\" method=\"post\">What is your desired domain name? <input type=\"text\" name=\"domain\" /> <p> What is your public key? <input type=\"text\" name=\"pkey\" /> <input type=\"submit\" value=\"Next\" /></body></html>"
+
+/**
+ * Second page (/S)
+ */
+#define SUBMIT_PAGE "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\"><html lang=\"en\" xmlns=\"http://www.w3.org/1999/xhtml\"><html><head><title>%s</title></head><body>%s</body></html>"
+
+/**
+ * Mime type for HTML pages.
+ */
+#define MIME_HTML "text/html"
+
+/**
+ * Name of our cookie.
+ */
+#define COOKIE_NAME "gns-fcfs"
+
+
+/**
+ * Phases a request goes through.
+ */
+enum Phase
+ {
+ /**
+ * Start phase (parsing POST, checking).
+ */
+ RP_START = 0,
+
+ /**
+ * Lookup to see if the domain name is taken.
+ */
+ RP_LOOKUP,
+
+ /**
+ * Storing of the record.
+ */
+ RP_PUT,
+
+ /**
+ * We're done with success.
+ */
+ RP_SUCCESS,
+
+ /**
+ * Send failure message.
+ */
+ RP_FAIL
+ };
+
+
+/**
+ * Data kept per request.
+ */
+struct Request
+{
+
+ /**
+ * Associated session.
+ */
+ struct Session *session;
+
+ /**
+ * Post processor handling form data (IF this is
+ * a POST request).
+ */
+ struct MHD_PostProcessor *pp;
+
+ /**
+ * URL to serve in response to this POST (if this request
+ * was a 'POST')
+ */
+ const char *post_url;
+
+ /**
+ * Active request with the namestore.
+ */
+ struct GNUNET_NAMESTORE_QueueEntry *qe;
+
+ /**
+ * Current processing phase.
+ */
+ enum Phase phase;
+
+ /**
+ * Domain name submitted via form.
+ */
+ char domain_name[64];
+
+ /**
+ * Public key submitted via form.
+ */
+ char public_key[64];
+
+};
+
+
+/**
+ * MHD deamon reference.
+ */
+static struct MHD_Daemon *httpd;
+
+/**
+ * Main HTTP task.
+ */
+static GNUNET_SCHEDULER_TaskIdentifier httpd_task;
+
+/**
+ * Handle to the namestore.
+ */
+static struct GNUNET_NAMESTORE_Handle *ns;
+
+/**
+ * Hash of the public key of the fcfsd zone.
+ */
+static struct GNUNET_CRYPTO_ShortHashCode fcfsd_zone;
+
+/**
+ * Private key for the fcfsd zone.
+ */
+static struct GNUNET_CRYPTO_RsaPrivateKey *fcfs_zone_pkey;
+
+
+/**
+ * Handler that returns a simple static HTTP page.
+ *
+ * @param connection connection to use
+ * @return MHD_YES on success
+ */
+static int
+serve_main_page (struct MHD_Connection *connection)
+{
+ int ret;
+ struct MHD_Response *response;
+
+ /* return static form */
+ response = MHD_create_response_from_buffer (strlen (MAIN_PAGE),
+ (void *) MAIN_PAGE,
+ MHD_RESPMEM_PERSISTENT);
+ MHD_add_response_header (response,
+ MHD_HTTP_HEADER_CONTENT_TYPE,
+ MIME_HTML);
+ ret = MHD_queue_response (connection,
+ MHD_HTTP_OK,
+ response);
+ MHD_destroy_response (response);
+ return ret;
+}
+
+
+/**
+ * Send the 'SUBMIT_PAGE'.
+ *
+ * @param info information string to send to the user
+ * @param request request information
+ * @param connection connection to use
+ */
+static int
+fill_s_reply (const char *info,
+ struct Request *request,
+ struct MHD_Connection *connection)
+{
+ int ret;
+ char *reply;
+ struct MHD_Response *response;
+
+ GNUNET_asprintf (&reply,
+ SUBMIT_PAGE,
+ info,
+ info);
+ /* return static form */
+ response = MHD_create_response_from_buffer (strlen (reply),
+ (void *) reply,
+ MHD_RESPMEM_MUST_FREE);
+ MHD_add_response_header (response,
+ MHD_HTTP_HEADER_CONTENT_TYPE,
+ MIME_HTML);
+ ret = MHD_queue_response (connection,
+ MHD_HTTP_OK,
+ response);
+ MHD_destroy_response (response);
+ return ret;
+}
+
+
+/**
+ * Iterator over key-value pairs where the value
+ * maybe made available in increments and/or may
+ * not be zero-terminated. Used for processing
+ * POST data.
+ *
+ * @param cls user-specified closure
+ * @param kind type of the value
+ * @param key 0-terminated key for the value
+ * @param filename name of the uploaded file, NULL if not known
+ * @param content_type mime-type of the data, NULL if not known
+ * @param transfer_encoding encoding of the data, NULL if not known
+ * @param data pointer to size bytes of data at the
+ * specified offset
+ * @param off offset of data in the overall value
+ * @param size number of bytes in data available
+ * @return MHD_YES to continue iterating,
+ * MHD_NO to abort the iteration
+ */
+static int
+post_iterator (void *cls,
+ enum MHD_ValueKind kind,
+ const char *key,
+ const char *filename,
+ const char *content_type,
+ const char *transfer_encoding,
+ const char *data, uint64_t off, size_t size)
+{
+ struct Request *request = cls;
+
+ if (0 == strcmp ("domain", key))
+ {
+ if (size + off >= sizeof(request->domain_name))
+ size = sizeof (request->domain_name) - off - 1;
+ memcpy (&request->domain_name[off],
+ data,
+ size);
+ request->domain_name[size+off] = '\0';
+ return MHD_YES;
+ }
+ if (0 == strcmp ("pkey", key))
+ {
+ if (size + off >= sizeof(request->public_key))
+ size = sizeof (request->public_key) - off - 1;
+ memcpy (&request->public_key[off],
+ data,
+ size);
+ request->public_key[size+off] = '\0';
+ return MHD_YES;
+ }
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ _("Unsupported form value `%s'\n"),
+ key);
+ return MHD_YES;
+}
+
+
+/**
+ * Task run whenever HTTP server operations are pending.
+ *
+ * @param cls unused
+ * @param tc scheduler context
+ */
+static void
+do_httpd (void *cls,
+ const struct GNUNET_SCHEDULER_TaskContext *tc);
+
+
+/**
+ * Schedule task to run MHD server now.
+ */
+static void
+run_httpd_now ()
+{
+ if (GNUNET_SCHEDULER_NO_TASK != httpd_task)
+ {
+ GNUNET_SCHEDULER_cancel (httpd_task);
+ httpd_task = GNUNET_SCHEDULER_NO_TASK;
+ }
+ httpd_task = GNUNET_SCHEDULER_add_now (&do_httpd, NULL);
+}
+
+
+/**
+ * Continuation called to notify client about result of the
+ * operation.
+ *
+ * @param cls closure
+ * @param success GNUNET_SYSERR on failure (including timeout/queue drop/failure to validate)
+ * GNUNET_NO if content was already there
+ * GNUNET_YES (or other positive value) on success
+ * @param emsg NULL on success, otherwise an error message
+ */
+static void
+put_continuation (void *cls,
+ int32_t success,
+ const char *emsg)
+{
+ struct Request *request = cls;
+
+ request->qe = NULL;
+ if (0 >= success)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+ _("Failed to create record for domain `%s': %s\n"),
+ request->domain_name,
+ emsg);
+ request->phase = RP_FAIL;
+ }
+ else
+ request->phase = RP_SUCCESS;
+ run_httpd_now ();
+}
+
+
+/**
+ * Test if a name mapping was found, if so, refuse. If not, initiate storing of the record.
+ *
+ * @param cls closure
+ * @param zone_key public key of the zone
+ * @param expire when does the corresponding block in the DHT expire (until
+ * when should we never do a DHT lookup for the same name again)?;
+ * GNUNET_TIME_UNIT_ZERO_ABS if there are no records of any type in the namestore,
+ * or the expiration time of the block in the namestore (even if there are zero
+ * records matching the desired record type)
+ * @param name name that is being mapped (at most 255 characters long)
+ * @param rd_count number of entries in 'rd' array
+ * @param rd array of records with data to store
+ * @param signature signature of the record block, NULL if signature is unavailable (i.e.
+ * because the user queried for a particular record type only)
+ */
+static void
+zone_to_name_cb (void *cls,
+ const struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *zone_key,
+ struct GNUNET_TIME_Absolute expire,
+ const char *name,
+ unsigned int rd_count,
+ const struct GNUNET_NAMESTORE_RecordData *rd,
+ const struct GNUNET_CRYPTO_RsaSignature *signature)
+{
+ struct Request *request = cls;
+ struct GNUNET_NAMESTORE_RecordData r;
+ struct GNUNET_CRYPTO_ShortHashCode pub;
+
+ request->qe = NULL;
+ if (NULL != name)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+ _("Found existing name `%s' for the given key\n"),
+ name);
+ request->phase = RP_FAIL;
+ run_httpd_now ();
+ return;
+ }
+ GNUNET_assert (GNUNET_OK ==
+ GNUNET_CRYPTO_short_hash_from_string2 (request->public_key,
+ strlen (request->public_key),
+ &pub));
+ r.data = &pub;
+ r.data_size = sizeof (pub);
+ r.expiration = GNUNET_TIME_UNIT_FOREVER_ABS;
+ r.record_type = GNUNET_NAMESTORE_TYPE_PKEY;
+ r.flags = GNUNET_NAMESTORE_RF_AUTHORITY;
+ request->qe = GNUNET_NAMESTORE_record_create (ns,
+ fcfs_zone_pkey,
+ request->domain_name,
+ &r,
+ &put_continuation,
+ request);
+}
+
+
+/**
+ * Process a record that was stored in the namestore. Used to check if
+ * the requested name already exists in the namestore. If not,
+ * proceed to check if the requested key already exists.
+ *
+ * @param cls closure
+ * @param zone_key public key of the zone
+ * @param expire when does the corresponding block in the DHT expire (until
+ * when should we never do a DHT lookup for the same name again)?;
+ * GNUNET_TIME_UNIT_ZERO_ABS if there are no records of any type in the namestore,
+ * or the expiration time of the block in the namestore (even if there are zero
+ * records matching the desired record type)
+ * @param name name that is being mapped (at most 255 characters long)
+ * @param rd_count number of entries in 'rd' array
+ * @param rd array of records with data to store
+ * @param signature signature of the record block, NULL if signature is unavailable (i.e.
+ * because the user queried for a particular record type only)
+ */
+static void
+lookup_result_processor (void *cls,
+ const struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *zone_key,
+ struct GNUNET_TIME_Absolute expire,
+ const char *name,
+ unsigned int rd_count,
+ const struct GNUNET_NAMESTORE_RecordData *rd,
+ const struct GNUNET_CRYPTO_RsaSignature *signature)
+{
+ struct Request *request = cls;
+ struct GNUNET_CRYPTO_ShortHashCode pub;
+
+ request->qe = NULL;
+ GNUNET_assert (GNUNET_OK ==
+ GNUNET_CRYPTO_short_hash_from_string2 (request->public_key,
+ strlen (request->public_key),
+ &pub));
+ if (0 != rd_count)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+ _("Found %u existing records for domain `%s'\n"),
+ rd_count,
+ request->domain_name);
+ request->phase = RP_FAIL;
+ run_httpd_now ();
+ return;
+ }
+ request->qe = GNUNET_NAMESTORE_zone_to_name (ns,
+ &fcfsd_zone,
+ &pub,
+ &zone_to_name_cb,
+ request);
+}
+
+
+/**
+ * Main MHD callback for handling requests.
+ *
+ * @param cls unused
+ * @param connection MHD connection handle
+ * @param url the requested url
+ * @param method the HTTP method used ("GET", "PUT", etc.)
+ * @param version the HTTP version string (i.e. "HTTP/1.1")
+ * @param upload_data the data being uploaded (excluding HEADERS,
+ * for a POST that fits into memory and that is encoded
+ * with a supported encoding, the POST data will NOT be
+ * given in upload_data and is instead available as
+ * part of MHD_get_connection_values; very large POST
+ * data *will* be made available incrementally in
+ * upload_data)
+ * @param upload_data_size set initially to the size of the
+ * upload_data provided; the method must update this
+ * value to the number of bytes NOT processed;
+ * @param ptr pointer to location where we store the 'struct Request'
+ * @return MHD_YES if the connection was handled successfully,
+ * MHD_NO if the socket must be closed due to a serious
+ * error while handling the request
+ */
+static int
+create_response (void *cls,
+ struct MHD_Connection *connection,
+ const char *url,
+ const char *method,
+ const char *version,
+ const char *upload_data,
+ size_t *upload_data_size,
+ void **ptr)
+{
+ struct MHD_Response *response;
+ struct Request *request;
+ int ret;
+ struct GNUNET_CRYPTO_ShortHashCode pub;
+
+ if ( (0 == strcmp (method, MHD_HTTP_METHOD_GET)) ||
+ (0 == strcmp (method, MHD_HTTP_METHOD_HEAD)) )
+ {
+ ret = serve_main_page (connection);
+ if (ret != MHD_YES)
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ _("Failed to create page for `%s'\n"),
+ url);
+ return ret;
+ }
+ if (0 == strcmp (method, MHD_HTTP_METHOD_POST))
+ {
+ request = *ptr;
+ if (NULL == request)
+ {
+ request = GNUNET_malloc (sizeof (struct Request));
+ *ptr = request;
+ request->pp = MHD_create_post_processor (connection, 1024,
+ &post_iterator, request);
+ if (NULL == request->pp)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ _("Failed to setup post processor for `%s'\n"),
+ url);
+ return MHD_NO; /* internal error */
+ }
+ return MHD_YES;
+ }
+ if (NULL != request->pp)
+ {
+ /* evaluate POST data */
+ MHD_post_process (request->pp,
+ upload_data,
+ *upload_data_size);
+ if (0 != *upload_data_size)
+ {
+ *upload_data_size = 0;
+ return MHD_YES;
+ }
+ /* done with POST data, serve response */
+ MHD_destroy_post_processor (request->pp);
+ request->pp = NULL;
+ }
+ if (GNUNET_OK !=
+ GNUNET_CRYPTO_short_hash_from_string2 (request->public_key,
+ strlen (request->public_key),
+ &pub))
+ {
+ /* parse error */
+ return fill_s_reply ("Failed to parse given public key",
+ request, connection);
+ }
+ switch (request->phase)
+ {
+ case RP_START:
+ request->phase = RP_LOOKUP;
+ request->qe = GNUNET_NAMESTORE_lookup_record (ns,
+ &fcfsd_zone,
+ request->domain_name,
+ GNUNET_NAMESTORE_TYPE_PKEY,
+ &lookup_result_processor,
+ request);
+ break;
+ case RP_LOOKUP:
+ break;
+ case RP_PUT:
+ break;
+ case RP_FAIL:
+ return fill_s_reply ("Request failed, sorry.",
+ request, connection);
+ case RP_SUCCESS:
+ return fill_s_reply ("Success.",
+ request, connection);
+ default:
+ GNUNET_break (0);
+ return MHD_NO;
+ }
+ return MHD_YES; /* will have a reply later... */
+ }
+ /* unsupported HTTP method */
+ response = MHD_create_response_from_buffer (strlen (METHOD_ERROR),
+ (void *) METHOD_ERROR,
+ MHD_RESPMEM_PERSISTENT);
+ ret = MHD_queue_response (connection,
+ MHD_HTTP_METHOD_NOT_ACCEPTABLE,
+ response);
+ MHD_destroy_response (response);
+ return ret;
+}
+
+
+/**
+ * Callback called upon completion of a request.
+ * Decrements session reference counter.
+ *
+ * @param cls not used
+ * @param connection connection that completed
+ * @param con_cls session handle
+ * @param toe status code
+ */
+static void
+request_completed_callback (void *cls,
+ struct MHD_Connection *connection,
+ void **con_cls,
+ enum MHD_RequestTerminationCode toe)
+{
+ struct Request *request = *con_cls;
+
+ if (NULL == request)
+ return;
+ if (NULL != request->pp)
+ MHD_destroy_post_processor (request->pp);
+ if (NULL != request->qe)
+ GNUNET_NAMESTORE_cancel (request->qe);
+ GNUNET_free (request);
+}
+
+
+/**
+ * Schedule tasks to run MHD server.
+ */
+static void
+run_httpd ()
+{
+ fd_set rs;
+ fd_set ws;
+ fd_set es;
+ struct GNUNET_NETWORK_FDSet *wrs;
+ struct GNUNET_NETWORK_FDSet *wws;
+ struct GNUNET_NETWORK_FDSet *wes;
+ int max;
+ int haveto;
+ unsigned MHD_LONG_LONG timeout;
+ struct GNUNET_TIME_Relative tv;
+
+ FD_ZERO (&rs);
+ FD_ZERO (&ws);
+ FD_ZERO (&es);
+ wrs = GNUNET_NETWORK_fdset_create ();
+ wes = GNUNET_NETWORK_fdset_create ();
+ wws = GNUNET_NETWORK_fdset_create ();
+ max = -1;
+ GNUNET_assert (MHD_YES == MHD_get_fdset (httpd, &rs, &ws, &es, &max));
+ haveto = MHD_get_timeout (httpd, &timeout);
+ if (haveto == MHD_YES)
+ tv.rel_value = (uint64_t) timeout;
+ else
+ tv = GNUNET_TIME_UNIT_FOREVER_REL;
+ GNUNET_NETWORK_fdset_copy_native (wrs, &rs, max + 1);
+ GNUNET_NETWORK_fdset_copy_native (wws, &ws, max + 1);
+ GNUNET_NETWORK_fdset_copy_native (wes, &es, max + 1);
+ httpd_task =
+ GNUNET_SCHEDULER_add_select (GNUNET_SCHEDULER_PRIORITY_HIGH,
+ tv, wrs, wws,
+ &do_httpd, NULL);
+ GNUNET_NETWORK_fdset_destroy (wrs);
+ GNUNET_NETWORK_fdset_destroy (wws);
+ GNUNET_NETWORK_fdset_destroy (wes);
+}
+
+
+/**
+ * Task run whenever HTTP server operations are pending.
+ *
+ * @param cls unused
+ * @param tc scheduler context
+ */
+static void
+do_httpd (void *cls,
+ const struct GNUNET_SCHEDULER_TaskContext *tc)
+{
+ httpd_task = GNUNET_SCHEDULER_NO_TASK;
+ MHD_run (httpd);
+ run_httpd ();
+}
+
+
+/**
+ * Task run on shutdown. Cleans up everything.
+ *
+ * @param cls unused
+ * @param tc scheduler context
+ */
+static void
+do_shutdown (void *cls,
+ const struct GNUNET_SCHEDULER_TaskContext *tc)
+{
+ if (GNUNET_SCHEDULER_NO_TASK != httpd_task)
+ {
+ GNUNET_SCHEDULER_cancel (httpd_task);
+ httpd_task = GNUNET_SCHEDULER_NO_TASK;
+ }
+ if (NULL != ns)
+ {
+ GNUNET_NAMESTORE_disconnect (ns, GNUNET_NO);
+ ns = NULL;
+ }
+ if (NULL != httpd)
+ {
+ MHD_stop_daemon (httpd);
+ httpd = NULL;
+ }
+ if (NULL != fcfs_zone_pkey)
+ {
+ GNUNET_CRYPTO_rsa_key_free (fcfs_zone_pkey);
+ fcfs_zone_pkey = NULL;
+ }
+}
+
+
+/**
+ * Main function that will be run.
+ *
+ * @param cls closure
+ * @param args remaining command-line arguments
+ * @param cfgfile name of the configuration file used (for saving, can be NULL!)
+ * @param cfg configuration
+ */
+static void
+run (void *cls, char *const *args, const char *cfgfile,
+ const struct GNUNET_CONFIGURATION_Handle *cfg)
+{
+ char *keyfile;
+ unsigned long long port;
+ struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded pub;
+
+ if (GNUNET_OK !=
+ GNUNET_CONFIGURATION_get_value_number (cfg,
+ "fcfsd",
+ "HTTPPORT",
+ &port))
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ _("Option `%s' not specified in configuration section `%s'\n"),
+ "HTTPPORT",
+ "fcfsd");
+ return;
+ }
+ if (GNUNET_OK !=
+ GNUNET_CONFIGURATION_get_value_filename (cfg,
+ "fcfsd",
+ "ZONEKEY",
+ &keyfile))
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ _("Option `%s' not specified in configuration section `%s'\n"),
+ "ZONEKEY",
+ "fcfsd");
+ return;
+ }
+ fcfs_zone_pkey = GNUNET_CRYPTO_rsa_key_create_from_file (keyfile);
+ GNUNET_free (keyfile);
+ if (NULL == fcfs_zone_pkey)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ _("Failed to read or create private zone key\n"));
+ return;
+ }
+ GNUNET_CRYPTO_rsa_key_get_public (fcfs_zone_pkey,
+ &pub);
+ GNUNET_CRYPTO_short_hash (&pub, sizeof (pub), &fcfsd_zone);
+ ns = GNUNET_NAMESTORE_connect (cfg);
+ if (NULL == ns)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ _("Failed to connect to namestore\n"));
+ return;
+ }
+ httpd = MHD_start_daemon (MHD_USE_DEBUG,
+ (uint16_t) port,
+ NULL, NULL,
+ &create_response, NULL,
+ MHD_OPTION_CONNECTION_LIMIT, (unsigned int) 128,
+ MHD_OPTION_PER_IP_CONNECTION_LIMIT, (unsigned int) 1,
+ MHD_OPTION_CONNECTION_TIMEOUT, (unsigned int) 16,
+ MHD_OPTION_CONNECTION_MEMORY_LIMIT, (size_t) (4 * 1024),
+ MHD_OPTION_NOTIFY_COMPLETED, &request_completed_callback, NULL,
+ MHD_OPTION_END);
+ if (NULL == httpd)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ _("Failed to start HTTP server\n"));
+ GNUNET_NAMESTORE_disconnect (ns, GNUNET_NO);
+ ns = NULL;
+ return;
+ }
+ run_httpd ();
+ GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL,
+ &do_shutdown, NULL);
+}
+
+
+/**
+ * The main function for the fcfs daemon.
+ *
+ * @param argc number of arguments from the command line
+ * @param argv command line arguments
+ * @return 0 ok, 1 on error
+ */
+int
+main (int argc, char *const *argv)
+{
+ static const struct GNUNET_GETOPT_CommandLineOption options[] = {
+ GNUNET_GETOPT_OPTION_END
+ };
+
+ int ret;
+
+ GNUNET_log_setup ("fcfsd", "WARNING", NULL);
+ ret =
+ (GNUNET_OK ==
+ GNUNET_PROGRAM_run (argc, argv, "fcfsd",
+ _("GNUnet GNS first come first serve registration service"),
+ options,
+ &run, NULL)) ? 0 : 1;
+
+ return ret;
+}
+
+/* end of gnunet-gns-fcfsd.c */
diff --git a/src/gns/gnunet-gns-proxy.c b/src/gns/gnunet-gns-proxy.c
new file mode 100644
index 0000000..876f531
--- /dev/null
+++ b/src/gns/gnunet-gns-proxy.c
@@ -0,0 +1,815 @@
+/*
+ This file is part of GNUnet.
+ (C) 2012 Christian Grothoff (and other contributing authors)
+
+ GNUnet is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 3, or (at your
+ option) any later version.
+
+ GNUnet is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GNUnet; see the file COPYING. If not, write to the
+ Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+
+#include "platform.h"
+#include <gnunet_util_lib.h>
+#include <microhttpd.h>
+#include "gns_proxy_proto.h"
+#include "gns.h"
+
+#define GNUNET_GNS_PROXY_PORT 7777
+
+//TODO maybe make this an api call
+/**
+ * Checks if name is in tld
+ *
+ * @param name the name to check
+ * @param tld the TLD to check for
+ * @return GNUNET_YES or GNUNET_NO
+ */
+int
+is_tld(const char* name, const char* tld)
+{
+ int offset = 0;
+
+ if (strlen(name) <= strlen(tld))
+ {
+ return GNUNET_NO;
+ }
+
+ offset = strlen(name)-strlen(tld);
+ if (strcmp (name+offset, tld) != 0)
+ {
+ GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
+ "%s is not in .%s TLD\n", name, tld);
+ return GNUNET_NO;
+ }
+
+ return GNUNET_YES;
+}
+
+struct Socks5Request
+{
+ struct GNUNET_NETWORK_Handle *sock;
+ struct GNUNET_NETWORK_Handle *remote_sock;
+
+ int state;
+
+ GNUNET_SCHEDULER_TaskIdentifier rtask;
+ GNUNET_SCHEDULER_TaskIdentifier fwdrtask;
+ GNUNET_SCHEDULER_TaskIdentifier wtask;
+ GNUNET_SCHEDULER_TaskIdentifier fwdwtask;
+
+ char rbuf[2048];
+ char wbuf[2048];
+ unsigned int rbuf_len;
+ unsigned int wbuf_len;
+};
+
+unsigned long port = GNUNET_GNS_PROXY_PORT;
+static struct GNUNET_NETWORK_Handle *lsock;
+GNUNET_SCHEDULER_TaskIdentifier ltask;
+static struct MHD_Daemon *httpd;
+static GNUNET_SCHEDULER_TaskIdentifier httpd_task;
+
+static int
+con_val_iter (void *cls,
+ enum MHD_ValueKind kind,
+ const char *key,
+ const char *value)
+{
+ char* buf = (char*)cls;
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "%s:%s\n", key, value);
+
+ if (0 == strcmp ("Host", key))
+ {
+ strcpy (buf, value);
+ return MHD_NO;
+ }
+ return MHD_YES;
+}
+
+/**
+ * Main MHD callback for handling requests.
+ *
+ * @param cls unused
+ * @param connection MHD connection handle
+ * @param method the HTTP method used ("GET", "PUT", etc.)
+ * @param version the HTTP version string (i.e. "HTTP/1.1")
+ * @param upload_data the data being uploaded (excluding HEADERS,
+ * for a POST that fits into memory and that is encoded
+ * with a supported encoding, the POST data will NOT be
+ * given in upload_data and is instead available as
+ * part of MHD_get_connection_values; very large POST
+ * data *will* be made available incrementally in
+ * upload_data)
+ * @param upload_data_size set initially to the size of the
+ * upload_data provided; the method must update this
+ * value to the number of bytes NOT processed;
+ * @param ptr pointer to location where we store the 'struct Request'
+ * @return MHD_YES if the connection was handled successfully,
+ * MHD_NO if the socket must be closed due to a serious
+ * error while handling the request
+ */
+static int
+create_response (void *cls,
+ struct MHD_Connection *con,
+ const char *url,
+ const char *meth,
+ const char *ver,
+ const char *upload_data,
+ size_t *upload_data_size,
+ void **con_cls)
+{
+ static int dummy;
+ const char* page = "<html><head><title>gnoxy</title>"\
+ "</head><body>gnoxy demo</body></html>";
+ struct MHD_Response *response;
+ char host[265];
+ int ret;
+
+ if (0 != strcmp (meth, "GET"))
+ return MHD_NO;
+ if (&dummy != *con_cls)
+ {
+ *con_cls = &dummy;
+ return MHD_YES;
+ }
+
+ if (0 != *upload_data_size)
+ return MHD_NO;
+
+ *con_cls = NULL;
+
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "url %s\n", url);
+
+ MHD_get_connection_values (con,
+ MHD_HEADER_KIND,
+ &con_val_iter, host);
+
+ response = MHD_create_response_from_buffer (strlen (page),
+ (void*)page,
+ MHD_RESPMEM_PERSISTENT);
+ ret = MHD_queue_response (con,
+ MHD_HTTP_OK,
+ response);
+ MHD_destroy_response (response);
+ return ret;
+}
+
+/**
+ * Task run whenever HTTP server operations are pending.
+ *
+ * @param cls unused
+ * @param tc sched context
+ */
+static void
+do_httpd (void *cls,
+ const struct GNUNET_SCHEDULER_TaskContext *tc);
+
+/**
+ * Schedule MHD
+ */
+static void
+run_httpd ()
+{
+ fd_set rs;
+ fd_set ws;
+ fd_set es;
+ struct GNUNET_NETWORK_FDSet *wrs;
+ struct GNUNET_NETWORK_FDSet *wws;
+ struct GNUNET_NETWORK_FDSet *wes;
+ int max;
+ int haveto;
+ unsigned MHD_LONG_LONG timeout;
+ struct GNUNET_TIME_Relative tv;
+
+ FD_ZERO (&rs);
+ FD_ZERO (&ws);
+ FD_ZERO (&es);
+ wrs = GNUNET_NETWORK_fdset_create ();
+ wes = GNUNET_NETWORK_fdset_create ();
+ wws = GNUNET_NETWORK_fdset_create ();
+ max = -1;
+ GNUNET_assert (MHD_YES == MHD_get_fdset (httpd, &rs, &ws, &es, &max));
+ haveto = MHD_get_timeout (httpd, &timeout);
+
+ if (haveto == MHD_YES)
+ tv.rel_value = (uint64_t) timeout;
+ else
+ tv = GNUNET_TIME_UNIT_FOREVER_REL;
+ GNUNET_NETWORK_fdset_copy_native (wrs, &rs, max + 1);
+ GNUNET_NETWORK_fdset_copy_native (wws, &ws, max + 1);
+ GNUNET_NETWORK_fdset_copy_native (wes, &es, max + 1);
+
+ if (httpd_task != GNUNET_SCHEDULER_NO_TASK)
+ GNUNET_SCHEDULER_cancel (httpd_task);
+ httpd_task =
+ GNUNET_SCHEDULER_add_select (GNUNET_SCHEDULER_PRIORITY_HIGH,
+ tv, wrs, wws,
+ &do_httpd, NULL);
+ GNUNET_NETWORK_fdset_destroy (wrs);
+ GNUNET_NETWORK_fdset_destroy (wws);
+ GNUNET_NETWORK_fdset_destroy (wes);
+}
+
+/**
+ * Task run whenever HTTP server operations are pending.
+ *
+ * @param cls unused
+ * @param tc sched context
+ */
+static void
+do_httpd (void *cls,
+ const struct GNUNET_SCHEDULER_TaskContext *tc)
+{
+ httpd_task = GNUNET_SCHEDULER_NO_TASK;
+ MHD_run (httpd);
+ run_httpd ();
+}
+
+/**
+ * Read data from socket
+ *
+ * @param cls the closure
+ * @param tc scheduler context
+ */
+static void
+do_read (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc);
+
+/**
+ * Read from remote end
+ *
+ * @param cls closure
+ * @param tc scheduler context
+ */
+static void
+do_read_remote (void* cls, const struct GNUNET_SCHEDULER_TaskContext *tc);
+
+/**
+ * Write data to remote socket
+ *
+ * @param cls the closure
+ * @param tc scheduler context
+ */
+static void
+do_write_remote (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
+{
+ struct Socks5Request *s5r = cls;
+ unsigned int len;
+
+ s5r->fwdwtask = GNUNET_SCHEDULER_NO_TASK;
+
+ if ((NULL != tc->read_ready) &&
+ (GNUNET_NETWORK_fdset_isset (tc->write_ready, s5r->remote_sock)) &&
+ (len = GNUNET_NETWORK_socket_send (s5r->remote_sock, s5r->rbuf,
+ s5r->rbuf_len)))
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Successfully sent %d bytes to remote socket\n",
+ len);
+ }
+ else
+ {
+ GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "write remote");
+ //Really!?!?!?
+ if (s5r->rtask != GNUNET_SCHEDULER_NO_TASK)
+ GNUNET_SCHEDULER_cancel (s5r->rtask);
+ if (s5r->wtask != GNUNET_SCHEDULER_NO_TASK)
+ GNUNET_SCHEDULER_cancel (s5r->wtask);
+ if (s5r->fwdrtask != GNUNET_SCHEDULER_NO_TASK)
+ GNUNET_SCHEDULER_cancel (s5r->fwdrtask);
+ GNUNET_NETWORK_socket_close (s5r->remote_sock);
+ GNUNET_NETWORK_socket_close (s5r->sock);
+ GNUNET_free(s5r);
+ return;
+ }
+
+ s5r->rtask =
+ GNUNET_SCHEDULER_add_read_net (GNUNET_TIME_UNIT_FOREVER_REL,
+ s5r->sock,
+ &do_read, s5r);
+}
+
+
+/**
+ * Write data to socket
+ *
+ * @param cls the closure
+ * @param tc scheduler context
+ */
+static void
+do_write (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
+{
+ struct Socks5Request *s5r = cls;
+ unsigned int len;
+
+ s5r->wtask = GNUNET_SCHEDULER_NO_TASK;
+
+ if ((NULL != tc->read_ready) &&
+ (GNUNET_NETWORK_fdset_isset (tc->write_ready, s5r->sock)) &&
+ (len = GNUNET_NETWORK_socket_send (s5r->sock, s5r->wbuf,
+ s5r->wbuf_len)))
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Successfully sent %d bytes to socket\n",
+ len);
+ }
+ else
+ {
+
+ GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "write");
+ //Really!?!?!?
+ if (s5r->rtask != GNUNET_SCHEDULER_NO_TASK)
+ GNUNET_SCHEDULER_cancel (s5r->rtask);
+ if (s5r->fwdwtask != GNUNET_SCHEDULER_NO_TASK)
+ GNUNET_SCHEDULER_cancel (s5r->fwdwtask);
+ if (s5r->fwdrtask != GNUNET_SCHEDULER_NO_TASK)
+ GNUNET_SCHEDULER_cancel (s5r->fwdrtask);
+ GNUNET_NETWORK_socket_close (s5r->remote_sock);
+ GNUNET_NETWORK_socket_close (s5r->sock);
+ GNUNET_free(s5r);
+ return;
+ }
+
+ if ((s5r->state == SOCKS5_DATA_TRANSFER) &&
+ (s5r->fwdrtask == GNUNET_SCHEDULER_NO_TASK))
+ s5r->fwdrtask =
+ GNUNET_SCHEDULER_add_read_net (GNUNET_TIME_UNIT_FOREVER_REL,
+ s5r->remote_sock,
+ &do_read_remote, s5r);
+}
+
+/**
+ * Read from remote end
+ *
+ * @param cls closure
+ * @param tc scheduler context
+ */
+static void
+do_read_remote (void* cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
+{
+ struct Socks5Request *s5r = cls;
+
+ s5r->fwdrtask = GNUNET_SCHEDULER_NO_TASK;
+
+
+ if ((NULL != tc->write_ready) &&
+ (GNUNET_NETWORK_fdset_isset (tc->read_ready, s5r->remote_sock)) &&
+ (s5r->wbuf_len = GNUNET_NETWORK_socket_recv (s5r->remote_sock, s5r->wbuf,
+ sizeof (s5r->wbuf))))
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Successfully read %d bytes from remote socket\n",
+ s5r->wbuf_len);
+ }
+ else
+ {
+ if (s5r->wbuf_len == 0)
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "0 bytes received from remote... graceful shutdown!\n");
+ if (s5r->fwdwtask != GNUNET_SCHEDULER_NO_TASK)
+ GNUNET_SCHEDULER_cancel (s5r->fwdwtask);
+ if (s5r->rtask != GNUNET_SCHEDULER_NO_TASK)
+ GNUNET_SCHEDULER_cancel (s5r->rtask);
+
+ GNUNET_NETWORK_socket_close (s5r->remote_sock);
+ s5r->remote_sock = NULL;
+ GNUNET_NETWORK_socket_close (s5r->sock);
+ GNUNET_free(s5r);
+
+ return;
+ }
+
+ s5r->wtask = GNUNET_SCHEDULER_add_write_net (GNUNET_TIME_UNIT_FOREVER_REL,
+ s5r->sock,
+ &do_write, s5r);
+
+}
+
+
+static int
+add_handle_to_mhd (struct GNUNET_NETWORK_Handle *h)
+{
+ int fd;
+ struct sockaddr *addr;
+ socklen_t len;
+
+ fd = GNUNET_NETWORK_get_fd (h);
+ addr = GNUNET_NETWORK_get_addr (h);
+ len = GNUNET_NETWORK_get_addrlen (h);
+
+ return MHD_add_connection (httpd, fd, addr, len);
+}
+
+/**
+ * Read data from incoming connection
+ *
+ * @param cls the closure
+ * @param tc the scheduler context
+ */
+static void
+do_read (void* cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
+{
+ struct Socks5Request *s5r = cls;
+ struct socks5_client_hello *c_hello;
+ struct socks5_server_hello *s_hello;
+ struct socks5_client_request *c_req;
+ struct socks5_server_response *s_resp;
+
+ char domain[256];
+ uint8_t dom_len;
+ uint16_t req_port;
+ struct hostent *phost;
+ uint32_t remote_ip;
+ struct sockaddr_in remote_addr;
+ struct in_addr *r_sin_addr;
+
+ s5r->rtask = GNUNET_SCHEDULER_NO_TASK;
+
+ if ((NULL != tc->write_ready) &&
+ (GNUNET_NETWORK_fdset_isset (tc->read_ready, s5r->sock)) &&
+ (s5r->rbuf_len = GNUNET_NETWORK_socket_recv (s5r->sock, s5r->rbuf,
+ sizeof (s5r->rbuf))))
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Successfully read %d bytes from socket\n",
+ s5r->rbuf_len);
+ }
+ else
+ {
+ if (s5r->rbuf_len != 0)
+ GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "read");
+ else
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "client disco!\n");
+
+ if (s5r->fwdrtask != GNUNET_SCHEDULER_NO_TASK)
+ GNUNET_SCHEDULER_cancel (s5r->fwdrtask);
+ if (s5r->wtask != GNUNET_SCHEDULER_NO_TASK)
+ GNUNET_SCHEDULER_cancel (s5r->wtask);
+ if (s5r->fwdwtask != GNUNET_SCHEDULER_NO_TASK)
+ GNUNET_SCHEDULER_cancel (s5r->fwdwtask);
+ GNUNET_NETWORK_socket_close (s5r->remote_sock);
+ GNUNET_NETWORK_socket_close (s5r->sock);
+ GNUNET_free(s5r);
+ return;
+ }
+
+ if (s5r->state == SOCKS5_INIT)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "SOCKS5 init\n");
+ c_hello = (struct socks5_client_hello*)&s5r->rbuf;
+
+ GNUNET_assert (c_hello->version == SOCKS_VERSION_5);
+
+ s_hello = (struct socks5_server_hello*)&s5r->wbuf;
+ s5r->wbuf_len = sizeof( struct socks5_server_hello );
+
+ s_hello->version = c_hello->version;
+ s_hello->auth_method = SOCKS_AUTH_NONE;
+
+ /* Write response to client */
+ s5r->wtask = GNUNET_SCHEDULER_add_write_net (GNUNET_TIME_UNIT_FOREVER_REL,
+ s5r->sock,
+ &do_write, s5r);
+
+ s5r->rtask = GNUNET_SCHEDULER_add_read_net (GNUNET_TIME_UNIT_FOREVER_REL,
+ s5r->sock,
+ &do_read, s5r);
+
+ s5r->state = SOCKS5_REQUEST;
+ return;
+ }
+
+ if (s5r->state == SOCKS5_REQUEST)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Processing SOCKS5 request\n");
+ c_req = (struct socks5_client_request*)&s5r->rbuf;
+ s_resp = (struct socks5_server_response*)&s5r->wbuf;
+ //Only 10byte for ipv4 response!
+ s5r->wbuf_len = 10;//sizeof (struct socks5_server_response);
+
+ GNUNET_assert (c_req->addr_type == 3);
+
+ dom_len = *((uint8_t*)(&(c_req->addr_type) + 1));
+ memset(domain, 0, sizeof(domain));
+ strncpy(domain, (char*)(&(c_req->addr_type) + 2), dom_len);
+ req_port = *((uint16_t*)(&(c_req->addr_type) + 2 + dom_len));
+
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Requested connection is %s:%d\n",
+ domain,
+ ntohs(req_port));
+
+ if (is_tld (domain, GNUNET_GNS_TLD) ||
+ is_tld (domain, GNUNET_GNS_TLD_ZKEY))
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Requested connection is gnunet tld\n",
+ domain);
+
+ if (NULL == httpd)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ _("Failed to start HTTP server\n"));
+ s_resp->version = 0x05;
+ s_resp->reply = 0x01;
+ s5r->wtask =
+ GNUNET_SCHEDULER_add_write_net (GNUNET_TIME_UNIT_FOREVER_REL,
+ s5r->sock,
+ &do_write, s5r);
+ //ERROR!
+ //TODO! close socket after the write! schedule task
+ //GNUNET_NETWORK_socket_close (s5r->sock);
+ //GNUNET_free(s5r);
+ return;
+ }
+
+ if (MHD_YES == add_handle_to_mhd ( s5r->sock ))
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Sucessfully added client to MHD!\n");
+ s_resp->version = 0x05;
+ s_resp->reply = 0x00;
+ s_resp->reserved = 0x00;
+ s_resp->addr_type = 0x01;
+
+ s5r->wtask =
+ GNUNET_SCHEDULER_add_write_net (GNUNET_TIME_UNIT_FOREVER_REL,
+ s5r->sock,
+ &do_write, s5r);
+ run_httpd ();
+ //GNUNET_free ( s5r );
+ //FIXME complete socks resp!
+ return;
+ }
+ else
+ {
+ phost = (struct hostent*)gethostbyname (domain);
+ if (phost == NULL)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Resolve %s error!\n", domain );
+ s_resp->version = 0x05;
+ s_resp->reply = 0x01;
+ s5r->wtask =
+ GNUNET_SCHEDULER_add_write_net (GNUNET_TIME_UNIT_FOREVER_REL,
+ s5r->sock,
+ &do_write, s5r);
+ //ERROR!
+ //TODO! close socket after the write! schedule task
+ //GNUNET_NETWORK_socket_close (s5r->sock);
+ //GNUNET_free(s5r);
+ return;
+ }
+
+ s5r->remote_sock = GNUNET_NETWORK_socket_create (AF_INET,
+ SOCK_STREAM,
+ 0);
+ r_sin_addr = (struct in_addr*)(phost->h_addr);
+ remote_ip = r_sin_addr->s_addr;
+ memset(&remote_addr, 0, sizeof(remote_addr));
+ remote_addr.sin_family = AF_INET;
+#if HAVE_SOCKADDR_IN_SIN_LEN
+ remote_addr.sin_len = sizeof (remote_addr);
+#endif
+ remote_addr.sin_addr.s_addr = remote_ip;
+ remote_addr.sin_port = req_port;
+
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "target server: %s:%u\n", inet_ntoa(remote_addr.sin_addr),
+ ntohs(req_port));
+
+ if ((GNUNET_OK !=
+ GNUNET_NETWORK_socket_connect ( s5r->remote_sock,
+ (const struct sockaddr*)&remote_addr,
+ sizeof (remote_addr)))
+ && (errno != EINPROGRESS))
+ {
+ GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "connect");
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "socket request error...\n");
+ s_resp->version = 0x05;
+ s_resp->reply = 0x01;
+ s5r->wtask =
+ GNUNET_SCHEDULER_add_write_net (GNUNET_TIME_UNIT_FOREVER_REL,
+ s5r->sock,
+ &do_write, s5r);
+ //TODO see above
+ return;
+ }
+
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "new remote connection\n");
+
+ s_resp->version = 0x05;
+ s_resp->reply = 0x00;
+ s_resp->reserved = 0x00;
+ s_resp->addr_type = 0x01;
+
+ s5r->state = SOCKS5_DATA_TRANSFER;
+
+ s5r->wtask =
+ GNUNET_SCHEDULER_add_write_net (GNUNET_TIME_UNIT_FOREVER_REL,
+ s5r->sock,
+ &do_write, s5r);
+ s5r->rtask =
+ GNUNET_SCHEDULER_add_read_net (GNUNET_TIME_UNIT_FOREVER_REL,
+ s5r->sock,
+ &do_read, s5r);
+
+ }
+ return;
+ }
+
+ if (s5r->state == SOCKS5_DATA_TRANSFER)
+ {
+ if ((s5r->remote_sock == NULL) || (s5r->rbuf_len == 0))
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Closing connection to client\n");
+ if (s5r->rtask != GNUNET_SCHEDULER_NO_TASK)
+ GNUNET_SCHEDULER_cancel (s5r->rtask);
+ if (s5r->fwdwtask != GNUNET_SCHEDULER_NO_TASK)
+ GNUNET_SCHEDULER_cancel (s5r->fwdwtask);
+ if (s5r->fwdrtask != GNUNET_SCHEDULER_NO_TASK)
+ GNUNET_SCHEDULER_cancel (s5r->fwdrtask);
+ if (s5r->fwdrtask != GNUNET_SCHEDULER_NO_TASK)
+ GNUNET_SCHEDULER_cancel (s5r->fwdrtask);
+
+ if (s5r->remote_sock != NULL)
+ GNUNET_NETWORK_socket_close (s5r->remote_sock);
+ GNUNET_NETWORK_socket_close (s5r->sock);
+ GNUNET_free(s5r);
+ return;
+ }
+
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "forwarding %d bytes from client\n", s5r->rbuf_len);
+
+ s5r->fwdwtask =
+ GNUNET_SCHEDULER_add_write_net (GNUNET_TIME_UNIT_FOREVER_REL,
+ s5r->remote_sock,
+ &do_write_remote, s5r);
+
+ if (s5r->fwdrtask == GNUNET_SCHEDULER_NO_TASK)
+ {
+ s5r->fwdrtask =
+ GNUNET_SCHEDULER_add_read_net (GNUNET_TIME_UNIT_FOREVER_REL,
+ s5r->remote_sock,
+ &do_read_remote, s5r);
+ }
+
+
+ }
+
+ //GNUNET_CONTAINER_DLL_remove (s5conns.head, s5conns.tail, s5r);
+
+}
+
+/**
+ * Accept new incoming connections
+ *
+ * @param cls the closure
+ * @param tc the scheduler context
+ */
+static void
+do_accept (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
+{
+ struct GNUNET_NETWORK_Handle *s;
+ struct Socks5Request *s5r;
+
+ ltask = GNUNET_SCHEDULER_NO_TASK;
+ if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN))
+ return;
+
+ ltask = GNUNET_SCHEDULER_add_read_net (GNUNET_TIME_UNIT_FOREVER_REL,
+ lsock,
+ &do_accept, NULL);
+
+ s = GNUNET_NETWORK_socket_accept (lsock, NULL, NULL);
+
+ if (NULL == s)
+ {
+ GNUNET_log_strerror (GNUNET_ERROR_TYPE_INFO, "accept");
+ return;
+ }
+
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Got an inbound connection, waiting for data\n");
+
+ s5r = GNUNET_malloc (sizeof (struct Socks5Request));
+ s5r->sock = s;
+ s5r->state = SOCKS5_INIT;
+ s5r->wtask = GNUNET_SCHEDULER_NO_TASK;
+ s5r->fwdwtask = GNUNET_SCHEDULER_NO_TASK;
+ s5r->fwdrtask = GNUNET_SCHEDULER_NO_TASK;
+ s5r->rtask = GNUNET_SCHEDULER_add_read_net (GNUNET_TIME_UNIT_FOREVER_REL,
+ s5r->sock,
+ &do_read, s5r);
+ //GNUNET_CONTAINER_DLL_insert (s5conns.head, s5conns.tail, s5r);
+}
+
+/**
+ * Main function that will be run
+ *
+ * @param cls closure
+ * @param args remaining command-line arguments
+ * @param cfgfile name of the configuration file used (for saving, can be NULL!)
+ * @param cfg configuration
+ */
+static void
+run (void *cls, char *const *args, const char *cfgfile,
+ const struct GNUNET_CONFIGURATION_Handle *cfg)
+{
+ struct sockaddr_in sa;
+
+ memset (&sa, 0, sizeof (sa));
+ sa.sin_family = AF_INET;
+ sa.sin_port = htons (port);
+#if HAVE_SOCKADDR_IN_SIN_LEN
+ sa.sin_len = sizeof (sa);
+#endif
+
+ lsock = GNUNET_NETWORK_socket_create (AF_INET,
+ SOCK_STREAM,
+ 0);
+
+ if ((NULL == lsock) ||
+ (GNUNET_OK !=
+ GNUNET_NETWORK_socket_bind (lsock, (const struct sockaddr *) &sa,
+ sizeof (sa))))
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "Failed to create listen socket bound to `%s'",
+ GNUNET_a2s ((const struct sockaddr *) &sa, sizeof (sa)));
+ if (NULL != lsock)
+ GNUNET_NETWORK_socket_close (lsock);
+ return;
+ }
+
+ if (GNUNET_OK != GNUNET_NETWORK_socket_listen (lsock, 5))
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "Failed to listen on socket bound to `%s'",
+ GNUNET_a2s ((const struct sockaddr *) &sa, sizeof (sa)));
+ return;
+ }
+
+ ltask = GNUNET_SCHEDULER_add_read_net (GNUNET_TIME_UNIT_FOREVER_REL,
+ lsock, &do_accept, NULL);
+
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Proxy listens on port %u\n",
+ port);
+
+ httpd = MHD_start_daemon (MHD_USE_DEBUG, 4444,
+ NULL, NULL,
+ &create_response, NULL,
+ MHD_OPTION_CONNECTION_LIMIT, (unsigned int) 128,
+ MHD_OPTION_CONNECTION_TIMEOUT, (unsigned int) 16,
+ MHD_OPTION_NOTIFY_COMPLETED,
+ NULL, NULL,
+ MHD_OPTION_END);
+ run_httpd ();
+
+}
+
+/**
+ * The main function for gnunet-gns-proxy.
+ *
+ * @param argc number of arguments from the command line
+ * @param argv command line arguments
+ * @return 0 ok, 1 on error
+ */
+int
+main (int argc, char *const *argv)
+{
+ static const struct GNUNET_GETOPT_CommandLineOption options[] = {
+ {'p', "port", NULL,
+ gettext_noop ("listen on specified port"), 1,
+ &GNUNET_GETOPT_set_string, &port},
+ GNUNET_GETOPT_OPTION_END
+ };
+
+ int ret;
+
+ GNUNET_log_setup ("gnunet-gns-proxy", "WARNING", NULL);
+ ret =
+ (GNUNET_OK ==
+ GNUNET_PROGRAM_run (argc, argv, "gnunet-gns-proxy",
+ _("GNUnet GNS proxy"),
+ options,
+ &run, NULL)) ? 0 : 1;
+ return ret;
+}
diff --git a/src/gns/gnunet-gns.c b/src/gns/gnunet-gns.c
new file mode 100644
index 0000000..ca3a594
--- /dev/null
+++ b/src/gns/gnunet-gns.c
@@ -0,0 +1,262 @@
+/*
+ This file is part of GNUnet.
+ (C) 2012 Christian Grothoff (and other contributing authors)
+
+ GNUnet is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 3, or (at your
+ option) any later version.
+
+ GNUnet is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GNUnet; see the file COPYING. If not, write to the
+ Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+/**
+ * @file gnunet-gns.c
+ * @brief command line tool to access distributed GNS
+ * @author Christian Grothoff
+ *
+ * TODO:
+ * - everything
+ */
+#include "platform.h"
+#include <gnunet_util_lib.h>
+#include <gnunet_dnsparser_lib.h>
+#include <gnunet_namestore_service.h>
+#include <gnunet_gns_service.h>
+
+/**
+ * Handle to GNS service.
+ */
+static struct GNUNET_GNS_Handle *gns;
+
+/**
+ * GNS name to shorten. (-s option)
+ */
+static char *shorten_name;
+
+/**
+ * GNS name to lookup. (-u option)
+ */
+static char *lookup_name;
+
+
+/**
+ * record type to look up (-t option)
+ */
+static char *lookup_type;
+
+/**
+ * name to look up authority for (-a option)
+ */
+static char *auth_name;
+
+/**
+ * raw output
+ */
+static int raw = 0;
+
+static enum GNUNET_GNS_RecordType rtype;
+
+/**
+ * Task run on shutdown. Cleans up everything.
+ *
+ * @param cls unused
+ * @param tc scheduler context
+ */
+static void
+do_shutdown (void *cls,
+ const struct GNUNET_SCHEDULER_TaskContext *tc)
+{
+ if (NULL != gns)
+ {
+ GNUNET_GNS_disconnect (gns);
+ gns = NULL;
+ }
+}
+
+
+static void
+process_shorten_result(void* cls, const char* nshort)
+{
+ if (raw)
+ printf("%s", nshort);
+ else
+ printf("%s shortened to %s\n", (char*) cls, nshort);
+ GNUNET_SCHEDULER_add_now (&do_shutdown, NULL);
+}
+
+static void
+process_lookup_result(void* cls, uint32_t rd_count,
+ const struct GNUNET_NAMESTORE_RecordData *rd)
+{
+ int i;
+ char* name = (char*) cls;
+ const char* typename;
+ char* string_val;
+
+ if (!raw) {
+ if (rd_count == 0)
+ printf("No results.\n");
+ else
+ printf("%s:\n", name);
+ }
+
+
+
+ for (i=0; i<rd_count; i++)
+ {
+ typename = GNUNET_NAMESTORE_number_to_typename (rd[i].record_type);
+ string_val = GNUNET_NAMESTORE_value_to_string(rd[i].record_type,
+ rd[i].data,
+ rd[i].data_size);
+ if (raw)
+ printf("%s\n", string_val);
+ else
+ printf("Got %s record: %s\n", typename, string_val);
+
+ }
+
+ GNUNET_SCHEDULER_add_now (&do_shutdown, NULL);
+}
+
+static void
+process_auth_result(void* cls, const char* auth)
+{
+ printf ("%s\n", auth);
+ GNUNET_SCHEDULER_add_now (&do_shutdown, NULL);
+}
+
+/**
+ * Main function that will be run.
+ *
+ * @param cls closure
+ * @param args remaining command-line arguments
+ * @param cfgfile name of the configuration file used (for saving, can be NULL!)
+ * @param cfg configuration
+ */
+static void
+run (void *cls, char *const *args, const char *cfgfile,
+ const struct GNUNET_CONFIGURATION_Handle *cfg)
+{
+ char* keyfile;
+ struct GNUNET_CRYPTO_RsaPrivateKey *key = NULL;
+ struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded pkey;
+ struct GNUNET_CRYPTO_ShortHashCode *zone = NULL;
+ struct GNUNET_CRYPTO_ShortHashCode user_zone;
+ struct GNUNET_CRYPTO_ShortHashAsciiEncoded zonename;
+
+ if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_filename (cfg, "gns",
+ "ZONEKEY", &keyfile))
+ {
+ if (!raw)
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+ "No private key for root zone found, using default!\n");
+ zone = NULL;
+ }
+ else
+ {
+ if (GNUNET_YES == GNUNET_DISK_file_test (keyfile))
+ {
+ key = GNUNET_CRYPTO_rsa_key_create_from_file (keyfile);
+ GNUNET_CRYPTO_rsa_key_get_public (key, &pkey);
+ GNUNET_CRYPTO_short_hash(&pkey,
+ sizeof(struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded),
+ &user_zone);
+ zone = &user_zone;
+ GNUNET_CRYPTO_short_hash_to_enc (zone, &zonename);
+ if (!raw)
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "Using zone: %s!\n", &zonename);
+ GNUNET_CRYPTO_rsa_key_free(key);
+ }
+ GNUNET_free(keyfile);
+ }
+
+ gns = GNUNET_GNS_connect (cfg);
+ if (lookup_type != NULL)
+ rtype = GNUNET_NAMESTORE_typename_to_number(lookup_type);
+ else
+ rtype = GNUNET_GNS_RECORD_TYPE_A;
+
+ if (NULL == gns)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ _("Failed to connect to GNS\n"));
+ return;
+ }
+
+ if (shorten_name != NULL)
+ {
+ /** shorten name */
+ GNUNET_GNS_shorten_zone (gns, shorten_name, zone, &process_shorten_result,
+ shorten_name);
+ }
+
+ if (lookup_name != NULL)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Lookup\n");
+ GNUNET_GNS_lookup_zone (gns, lookup_name, zone, rtype,
+ &process_lookup_result, lookup_name);
+ }
+
+ if (auth_name != NULL)
+ {
+ GNUNET_GNS_get_authority(gns, auth_name, &process_auth_result, auth_name);
+ }
+
+ // FIXME: do work here...
+ //GNUNET_SCHEDULER_add_now (&do_shutdown, NULL);
+}
+
+
+/**
+ * The main function for gnunet-gns.
+ *
+ * @param argc number of arguments from the command line
+ * @param argv command line arguments
+ * @return 0 ok, 1 on error
+ */
+int
+main (int argc, char *const *argv)
+{
+ static const struct GNUNET_GETOPT_CommandLineOption options[] = {
+ {'s', "shorten", NULL,
+ gettext_noop ("try to shorten a given GNS name"), 1,
+ &GNUNET_GETOPT_set_string, &shorten_name},
+ {'u', "lookup", NULL,
+ gettext_noop ("Lookup a record using GNS (NOT IMPLEMENTED)"), 1,
+ &GNUNET_GETOPT_set_string, &lookup_name},
+ {'a', "authority", NULL,
+ gettext_noop ("Get the authority of a particular name"), 1,
+ &GNUNET_GETOPT_set_string, &auth_name},
+ {'t', "type", NULL,
+ gettext_noop ("Specify the type of the record lookup"), 1,
+ &GNUNET_GETOPT_set_string, &lookup_type},
+ {'r', "raw", NULL,
+ gettext_noop ("No unneeded output"), 0,
+ &GNUNET_GETOPT_set_one, &raw},
+ GNUNET_GETOPT_OPTION_END
+ };
+
+ int ret;
+
+ GNUNET_log_setup ("gnunet-gns", "WARNING", NULL);
+ ret =
+ (GNUNET_OK ==
+ GNUNET_PROGRAM_run (argc, argv, "gnunet-gns",
+ _("GNUnet GNS access tool"),
+ options,
+ &run, NULL)) ? 0 : 1;
+
+ return ret;
+}
+
+/* end of gnunet-gns.c */
diff --git a/src/gns/gnunet-service-gns.c b/src/gns/gnunet-service-gns.c
index b5649f3..5e22801 100644
--- a/src/gns/gnunet-service-gns.c
+++ b/src/gns/gnunet-service-gns.c
@@ -20,10 +20,6 @@
/**
*
- * TODO:
- * - Write xquery and block plugin
- * - The smaller FIXME issues all around
- *
* @file gns/gnunet-service-gns.c
* @brief GNUnet GNS service
* @author Martin Schanzenbach
@@ -38,59 +34,83 @@
#include "gnunet_gns_service.h"
#include "block_gns.h"
#include "gns.h"
+#include "gnunet-service-gns_resolver.h"
+#include "gnunet-service-gns_interceptor.h"
+
+/* FIXME move to proper header in include */
+#define GNUNET_MESSAGE_TYPE_GNS_LOOKUP 23
+#define GNUNET_MESSAGE_TYPE_GNS_LOOKUP_RESULT 24
+#define GNUNET_MESSAGE_TYPE_GNS_SHORTEN 25
+#define GNUNET_MESSAGE_TYPE_GNS_SHORTEN_RESULT 26
+#define GNUNET_MESSAGE_TYPE_GNS_GET_AUTH 27
+#define GNUNET_MESSAGE_TYPE_GNS_GET_AUTH_RESULT 28
-/* Ignore for now not used anyway and probably never will */
-#define GNUNET_MESSAGE_TYPE_GNS_CLIENT_LOOKUP 23
-#define GNUNET_MESSAGE_TYPE_GNS_CLIENT_RESULT 24
/**
- * Handle to a currenty pending resolution
+ * Handle to a shorten operation from api
*/
-struct GNUNET_GNS_ResolverHandle
+struct ClientShortenHandle
{
- /* The name to resolve */
- char *name;
+ /* the requesting client that */
+ struct GNUNET_SERVER_Client *client;
- /* the request handle to reply to */
- struct GNUNET_DNS_RequestHandle *request_handle;
-
- /* the dns parser packet received */
- struct GNUNET_DNSPARSER_Packet *packet;
-
- /* the query parsed from the packet */
+ /* request id */
+ uint64_t unique_id;
+
+ /* request type */
+ enum GNUNET_GNS_RecordType type;
- struct GNUNET_DNSPARSER_Query *query;
+ /* optional zone private key used for lookup */
+ struct GNUNET_CRYPTO_RsaPrivateKey *zone_key;
- /* has this query been answered? how many matches */
- int answered;
+ /* name to shorten */
+ char* name;
- /* the authoritative zone to query */
- GNUNET_HashCode authority;
+};
- /* the name of the authoritative zone to query */
- char *authority_name;
- /**
- * we have an authority in namestore that
- * may be able to resolve
- */
- int authority_found;
+/**
+ * Handle to a get auhtority operation from api
+ */
+struct ClientGetAuthHandle
+{
+ /* the requesting client that */
+ struct GNUNET_SERVER_Client *client;
+
+ /* request id */
+ uint64_t unique_id;
- /* a handle for dht lookups. should be NULL if no lookups are in progress */
- struct GNUNET_DHT_GetHandle *get_handle;
+ /* name to lookup authority */
+ char* name;
};
/**
- * Our handle to the DNS handler library
+ * Handle to a lookup operation from api
*/
-struct GNUNET_DNS_Handle *dns_handle;
+struct ClientLookupHandle
+{
+ /* the requesting client that */
+ struct GNUNET_SERVER_Client *client;
+
+ /* request id */
+ uint64_t unique_id;
+
+ /* request type */
+ enum GNUNET_GNS_RecordType type;
+
+ /* optional zone private key used for lookup */
+ struct GNUNET_CRYPTO_RsaPrivateKey *zone_key;
+
+ /* the name to look up */
+ char* name; //Needed?
+};
/**
* Our handle to the DHT
*/
-struct GNUNET_DHT_Handle *dht_handle;
+static struct GNUNET_DHT_Handle *dht_handle;
/**
* Our zone's private key
@@ -121,1126 +141,765 @@ static struct GNUNET_SERVER_NotificationContext *nc;
/**
* Our zone hash
*/
-GNUNET_HashCode zone_hash;
+struct GNUNET_CRYPTO_ShortHashCode zone_hash;
/**
- * Our tld. Maybe get from config file
+ * Useful for zone update for DHT put
*/
-const char* gnunet_tld = ".gnunet";
+static int num_public_records;
/**
- * Useful for zone update for DHT put
+ * update interval in seconds
*/
-static int num_public_records = 3600;
-struct GNUNET_TIME_Relative dht_update_interval;
+static unsigned long long max_record_put_interval;
+
+static unsigned long long dht_max_update_interval;
+
+/* dht update interval FIXME define? */
+static struct GNUNET_TIME_Relative record_put_interval;
+
+/* zone update task */
GNUNET_SCHEDULER_TaskIdentifier zone_update_taskid = GNUNET_SCHEDULER_NO_TASK;
-/* Prototypes */
-void reply_to_dns(struct GNUNET_GNS_ResolverHandle *answer, uint32_t rd_count,
- const struct GNUNET_NAMESTORE_RecordData *rd);
-void resolve_name(struct GNUNET_GNS_ResolverHandle *rh);
+/* automatic pkey import for name shortening */
+static int auto_import_pkey;
+
+/* lookup timeout */
+static struct GNUNET_TIME_Relative default_lookup_timeout;
/**
- * Task run during shutdown.
- *
- * @param cls unused
- * @param tc unused
+ * Continue shutdown
*/
static void
-shutdown_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
+on_resolver_cleanup(void)
{
- /* Kill zone task for it may make the scheduler hang */
- GNUNET_SCHEDULER_cancel(zone_update_taskid);
-
- GNUNET_DNS_disconnect(dns_handle);
- GNUNET_NAMESTORE_disconnect(namestore_handle, 0);
+ GNUNET_NAMESTORE_disconnect(namestore_handle, 1);
GNUNET_DHT_disconnect(dht_handle);
}
/**
- * Callback when record data is put into namestore
+ * Task run during shutdown.
*
- * @param cls the closure
- * @param success GNUNET_OK on success
- * @param emsg the error message. NULL if SUCCESS==GNUNET_OK
+ * @param cls unused
+ * @param tc unused
*/
-void
-on_namestore_record_put_result(void *cls,
- int32_t success,
- const char *emsg)
+static void
+shutdown_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
{
- if (GNUNET_NO == success)
- {
- GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "records already in namestore\n");
- return;
- }
- else if (GNUNET_YES == success)
- {
- GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
- "records successfully put in namestore\n");
- return;
- }
- GNUNET_log(GNUNET_ERROR_TYPE_ERROR,
- "Error putting records into namestore: %s\n", emsg);
+ GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
+ "Shutting down!");
+ /* Kill zone task for it may make the scheduler hang */
+ if (zone_update_taskid != GNUNET_SCHEDULER_NO_TASK)
+ GNUNET_SCHEDULER_cancel(zone_update_taskid);
+
+ GNUNET_SERVER_notification_context_destroy (nc);
+
+ gns_interceptor_stop();
+ gns_resolver_cleanup(&on_resolver_cleanup);
+
}
+
/**
- * Function called when we get a result from the dht
- * for our query
+ * Method called periodicattluy that triggers
+ * iteration over root zone
*
- * @param cls the request handle
- * @param exp lifetime
- * @param key the key the record was stored under
- * @param get_path get path
- * @param get_path_length get path length
- * @param put_path put path
- * @param put_path_length put path length
- * @param type the block type
- * @param size the size of the record
- * @param data the record data
+ * @param cls closure
+ * @param tc task context
*/
-void
-process_authority_dht_result(void* cls,
- struct GNUNET_TIME_Absolute exp,
- const GNUNET_HashCode * key,
- const struct GNUNET_PeerIdentity *get_path,
- unsigned int get_path_length,
- const struct GNUNET_PeerIdentity *put_path,
- unsigned int put_path_length,
- enum GNUNET_BLOCK_Type type,
- size_t size, const void *data)
+static void
+update_zone_dht_next(void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
{
- struct GNUNET_GNS_ResolverHandle *rh;
- struct GNSNameRecordBlock *nrb;
- struct GNSRecordBlock *rb;
- uint32_t num_records;
- char* name = NULL;
- int i;
- GNUNET_HashCode zone, name_hash;
-
- if (data == NULL)
- return;
-
- //FIXME check expiration?
-
- rh = (struct GNUNET_GNS_ResolverHandle *)cls;
- nrb = (struct GNSNameRecordBlock*)data;
-
- GNUNET_DHT_get_stop (rh->get_handle);
- rh->get_handle = NULL;
- num_records = ntohl(nrb->rd_count);
- struct GNUNET_NAMESTORE_RecordData rd[num_records];
- name = (char*)&nrb[1];
- rb = (struct GNSRecordBlock *)&name[strlen(name) + 1];
-
- for (i=0; i<num_records; i++)
- {
-
- rd[i].record_type = ntohl(rb->type);
- rd[i].data_size = ntohl(rb->data_length);
- rd[i].data = &rb[1];
- rd[i].expiration = GNUNET_TIME_absolute_ntoh(rb->expiration);
- rd[i].flags = ntohl(rb->flags);
-
- GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
- "Got name: %s (wanted %s)\n", name, rh->authority_name);
- GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
- "Got type: %d raw %d (wanted %d)\n",
- rd[i].record_type, rb->type, GNUNET_GNS_RECORD_PKEY);
- GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
- "Got data length: %d\n", rd[i].data_size);
- GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
- "Got flag %d\n", rd[i].flags);
-
- if ((strcmp(name, rh->authority_name) == 0) &&
- (rd[i].record_type == GNUNET_GNS_RECORD_PKEY))
- {
- GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Authority found in DHT\n");
- rh->answered = 1;
- GNUNET_CRYPTO_hash(
- (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *)rd[i].data,
- rd[i].data_size,
- &rh->authority);
- }
- rb = (struct GNSRecordBlock*)((char*)&rb[1] + rd[i].data_size);
-
- }
-
- GNUNET_CRYPTO_hash(name, strlen(name), &name_hash);
- GNUNET_CRYPTO_hash_xor(key, &name_hash, &zone);
-
- /* Save to namestore */
- if (0 == GNUNET_CRYPTO_hash_cmp(&zone_hash, &zone))
- {
- GNUNET_NAMESTORE_record_put (namestore_handle,
- &nrb->public_key,
- name,
- exp,
- num_records,
- rd,
- &nrb->signature,
- &on_namestore_record_put_result, //cont
- NULL); //cls
- }
-
- if (rh->answered)
- {
- rh->answered = 0;
- resolve_name(rh);
- return;
- }
- GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "No authority in records\n");
- reply_to_dns(rh, 0, NULL);
+ zone_update_taskid = GNUNET_SCHEDULER_NO_TASK;
+ GNUNET_NAMESTORE_zone_iterator_next(namestore_iter);
}
/**
- * Start DHT lookup for a name -> PKEY (compare NS) record in
- * query->authority's zone
+ * Continuation for DHT put
*
- * @param rh the pending gns query
- * @param name the name of the PKEY record
+ * @param cls closure
+ * @param success GNUNET_OK if the PUT was transmitted,
+ * GNUNET_NO on timeout,
+ * GNUNET_SYSERR on disconnect from service
+ * after the PUT message was transmitted
+ * (so we don't know if it was received or not)
*/
-void
-resolve_authority_dht(struct GNUNET_GNS_ResolverHandle *rh)
+static void
+record_dht_put(void *cls, int success)
{
- uint32_t xquery;
- struct GNUNET_TIME_Relative timeout;
- GNUNET_HashCode name_hash;
- GNUNET_HashCode lookup_key;
-
- GNUNET_CRYPTO_hash(rh->authority_name,
- strlen(rh->authority_name),
- &name_hash);
- GNUNET_CRYPTO_hash_xor(&name_hash, &rh->authority, &lookup_key);
-
- timeout = GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 5);
-
- xquery = htonl(GNUNET_GNS_RECORD_PKEY);
- //FIXME how long to wait for results?
- rh->get_handle = GNUNET_DHT_get_start(dht_handle, timeout,
- GNUNET_BLOCK_TYPE_GNS_NAMERECORD,
- &lookup_key,
- 5, //Replication level FIXME
- GNUNET_DHT_RO_NONE,
- &xquery,
- sizeof(xquery),
- &process_authority_dht_result,
- rh);
-
+ GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "put request transmitted\n");
}
+/* prototype */
+static void
+update_zone_dht_start(void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc);
+
/**
- * Function called when we get a result from the dht
- * for our query
+ * Function used to put all records successively into the DHT.
*
- * @param cls the request handle
- * @param exp lifetime
- * @param key the key the record was stored under
- * @param get_path get path
- * @param get_path_length get path length
- * @param put_path put path
- * @param put_path_length put path length
- * @param type the block type
- * @param size the size of the record
- * @param data the record data
+ * @param cls the closure (NULL)
+ * @param key the public key of the authority (ours)
+ * @param expiration lifetime of the namestore entry
+ * @param name the name of the records
+ * @param rd_count the number of records in data
+ * @param rd the record data
+ * @param signature the signature for the record data
*/
-void
-process_name_dht_result(void* cls,
- struct GNUNET_TIME_Absolute exp,
- const GNUNET_HashCode * key,
- const struct GNUNET_PeerIdentity *get_path,
- unsigned int get_path_length,
- const struct GNUNET_PeerIdentity *put_path,
- unsigned int put_path_length,
- enum GNUNET_BLOCK_Type type,
- size_t size, const void *data)
+static void
+put_gns_record(void *cls,
+ const struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *key,
+ struct GNUNET_TIME_Absolute expiration,
+ const char *name,
+ unsigned int rd_count,
+ const struct GNUNET_NAMESTORE_RecordData *rd,
+ const struct GNUNET_CRYPTO_RsaSignature *signature)
{
- struct GNUNET_GNS_ResolverHandle *rh;
- struct GNSNameRecordBlock *nrb;
- struct GNSRecordBlock *rb;
- uint32_t num_records;
- char* name = NULL;
- int i;
- GNUNET_HashCode zone, name_hash;
- GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "got dht result (size=%d)\n", size);
-
- if (data == NULL)
- return;
-
- //FIXME maybe check expiration here, check block type
- rh = (struct GNUNET_GNS_ResolverHandle *)cls;
- nrb = (struct GNSNameRecordBlock*)data;
-
- GNUNET_DHT_get_stop (rh->get_handle);
- rh->get_handle = NULL;
- num_records = ntohl(nrb->rd_count);
- struct GNUNET_NAMESTORE_RecordData rd[num_records];
+ struct GNSNameRecordBlock *nrb;
+ struct GNUNET_CRYPTO_ShortHashCode name_hash;
+ struct GNUNET_CRYPTO_ShortHashCode zhash;
+ GNUNET_HashCode xor_hash;
+ GNUNET_HashCode name_hash_double;
+ GNUNET_HashCode zone_hash_double;
+ uint32_t rd_payload_length;
+ char* nrb_data = NULL;
+ size_t namelen;
- name = (char*)&nrb[1];
- rb = (struct GNSRecordBlock*)&name[strlen(name) + 1];
-
- for (i=0; i<num_records; i++)
+ /* we're done */
+ if (NULL == name)
{
- rd[i].record_type = ntohl(rb->type);
- rd[i].data_size = ntohl(rb->data_length);
- rd[i].data = (char*)&rb[1];
- rd[i].expiration = GNUNET_TIME_absolute_ntoh(rb->expiration);
- rd[i].flags = ntohl(rb->flags);
-
GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
- "Got name: %s (wanted %s)\n", name, rh->name);
- GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
- "Got type: %d raw %d (wanted %d)\n",
- rd[i].record_type, rb->type, rh->query->type);
- GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
- "Got data length: %d\n", rd[i].data_size);
- GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
- "Got flag %d\n", rd[i].flags);
-
- /* FIXME class? */
- if ((strcmp(name, rh->name) == 0) &&
- (rd[i].record_type == rh->query->type))
- {
- rh->answered++;
- }
-
- rb = (struct GNSRecordBlock*)((char*)&rb[1] + rd[i].data_size);
-
+ "Zone iteration finished. Rescheduling put in %ds\n",
+ dht_max_update_interval);
+ zone_update_taskid = GNUNET_SCHEDULER_add_delayed (
+ GNUNET_TIME_relative_multiply(
+ GNUNET_TIME_UNIT_SECONDS,
+ dht_max_update_interval
+ ),
+ &update_zone_dht_start,
+ NULL);
+ return;
}
-
- GNUNET_CRYPTO_hash(name, strlen(name), &name_hash);
- GNUNET_CRYPTO_hash_xor(key, &name_hash, &zone);
- /**
- * FIXME check pubkey against existing key in namestore?
- * https://gnunet.org/bugs/view.php?id=2179
- */
-
- /* Save to namestore */
- GNUNET_NAMESTORE_record_put (namestore_handle,
- &nrb->public_key,
- name,
- exp,
- num_records,
- rd,
- &nrb->signature,
- &on_namestore_record_put_result, //cont
- NULL); //cls
+ namelen = strlen(name) + 1;
- if (rh->answered)
- reply_to_dns(rh, num_records, rd);
- else
- reply_to_dns(rh, 0, NULL);
-
-}
+ if (signature == NULL)
+ {
+ GNUNET_log(GNUNET_ERROR_TYPE_ERROR,
+ "No signature for %s record data provided! Skipping...\n",
+ name);
+ zone_update_taskid = GNUNET_SCHEDULER_add_now (&update_zone_dht_next,
+ NULL);
+ return;
-/**
- * Start DHT lookup for a (name -> query->record_type) record in
- * query->authority's zone
- *
- * @param rh the pending gns query context
- * @param name the name to query record
- */
-void
-resolve_name_dht(struct GNUNET_GNS_ResolverHandle *rh, const char* name)
-{
- uint32_t xquery;
- struct GNUNET_TIME_Relative timeout;
- GNUNET_HashCode name_hash;
- GNUNET_HashCode lookup_key;
- struct GNUNET_CRYPTO_HashAsciiEncoded lookup_key_string;
-
- GNUNET_CRYPTO_hash(name, strlen(name), &name_hash);
- GNUNET_CRYPTO_hash_xor(&name_hash, &rh->authority, &lookup_key);
- GNUNET_CRYPTO_hash_to_enc (&lookup_key, &lookup_key_string);
+ }
GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
- "starting dht lookup for %s with key: %s\n",
- name, (char*)&lookup_key_string);
+ "Putting records for %s into the DHT\n", name);
+
+ rd_payload_length = GNUNET_NAMESTORE_records_get_size (rd_count, rd);
+
+ nrb = GNUNET_malloc(rd_payload_length + namelen
+ + sizeof(struct GNSNameRecordBlock));
+
+ nrb->signature = *signature;
+
+ nrb->public_key = *key;
- timeout = GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 5);
+ nrb->rd_count = htonl(rd_count);
- xquery = htonl(rh->query->type);
- //FIXME how long to wait for results?
- rh->get_handle = GNUNET_DHT_get_start(dht_handle, timeout,
- GNUNET_BLOCK_TYPE_GNS_NAMERECORD,
- &lookup_key,
- 5, //Replication level FIXME
- GNUNET_DHT_RO_NONE,
- &xquery, //xquery FIXME is this bad?
- sizeof(xquery),
- &process_name_dht_result,
- rh);
+ memcpy(&nrb[1], name, namelen);
-}
+ nrb_data = (char*)&nrb[1];
+ nrb_data += namelen;
-//Prototype
-void
-resolve_name(struct GNUNET_GNS_ResolverHandle *rh);
+ rd_payload_length += sizeof(struct GNSNameRecordBlock) + namelen;
-/**
- * This is a callback function that should give us only PKEY
- * records. Used to query the namestore for the authority (PKEY)
- * for 'name'
- *
- * @param cls the pending query
- * @param key the key of the zone we did the lookup
- * @param expiration expiration date of the record data set in the namestore
- * @param name the name for which we need an authority
- * @param rd_count the number of records with 'name'
- * @param rd the record data
- * @param signature the signature of the authority for the record data
- */
-void
-process_authority_lookup(void* cls,
- const struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *key,
- struct GNUNET_TIME_Absolute expiration,
- const char *name,
- unsigned int rd_count,
- const struct GNUNET_NAMESTORE_RecordData *rd,
- const struct GNUNET_CRYPTO_RsaSignature *signature)
-{
- struct GNUNET_GNS_ResolverHandle *rh;
- struct GNUNET_TIME_Relative remaining_time;
- GNUNET_HashCode zone;
-
- rh = (struct GNUNET_GNS_ResolverHandle *)cls;
- GNUNET_CRYPTO_hash(key,
- sizeof(struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded),
- &zone);
- remaining_time = GNUNET_TIME_absolute_get_remaining (expiration);
-
- /**
- * No authority found in namestore.
- */
- if (rd_count == 0)
+ if (-1 == GNUNET_NAMESTORE_records_serialize (rd_count,
+ rd,
+ rd_payload_length,
+ nrb_data))
{
- /**
- * We did not find an authority in the namestore
- * _IF_ the current authoritative zone is us we cannot resolve
- * _ELSE_ we can still check the _expired_ dht
- */
- if (0 != GNUNET_CRYPTO_hash_cmp(&zone, &zone_hash) &&
- (remaining_time.rel_value == 0))
- {
- resolve_authority_dht(rh);
- return;
- }
- GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Authority %s unknown\n",
- rh->authority_name);
- reply_to_dns(rh, 0, NULL);
+ GNUNET_log(GNUNET_ERROR_TYPE_ERROR,
+ "Record serialization failed! Skipping...\n");
+ GNUNET_free(nrb);
+ zone_update_taskid = GNUNET_SCHEDULER_add_now (&update_zone_dht_next,
+ NULL);
return;
}
- //Note only 1 pkey should have been returned.. anything else would be strange
- /**
- * We found an authority that may be able to help us
- * move on with query
- */
- int i;
- for (i=0; i<rd_count;i++)
- {
-
- if (rd[i].record_type != GNUNET_GNS_RECORD_PKEY)
- continue;
-
- if ((GNUNET_TIME_absolute_get_remaining (rd[i].expiration)).rel_value
- == 0)
- {
- GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "This pkey is expired.\n");
- if (remaining_time.rel_value == 0)
- {
- GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
- "This dht entry is expired. Refreshing\n");
- resolve_authority_dht(rh);
- }
-
- continue;
- }
-
- /**
- * Resolve rest of query with new authority
- */
- GNUNET_assert(rd[i].record_type == GNUNET_GNS_RECORD_PKEY);
- GNUNET_CRYPTO_hash(rd[i].data,
- sizeof(struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded),
- &rh->authority);
- resolve_name(rh);
- return;
-
- }
-
- /**
- * no answers found
+
+ /*
+ * calculate DHT key: H(name) xor H(pubkey)
*/
- GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
- "Authority lookup successful but no PKEY... never get here\n");
- reply_to_dns(rh, 0, NULL);
-}
+ GNUNET_CRYPTO_short_hash(key,
+ sizeof(struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded),
+ &zhash);
+ GNUNET_CRYPTO_short_hash(name, strlen(name), &name_hash);
+ GNUNET_CRYPTO_short_hash_double (&name_hash, &name_hash_double);
+ GNUNET_CRYPTO_short_hash_double (&zhash, &zone_hash_double);
+ GNUNET_CRYPTO_hash_xor(&zone_hash_double, &name_hash_double, &xor_hash);
+ GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
+ "zone identity: %s\n", GNUNET_h2s (&zone_hash_double));
-/**
- * Reply to client with the result from our lookup.
- *
- * @param rh the request handle of the lookup
- * @param rd_count the number of records to return
- * @param rd the record data
- */
-void
-reply_to_dns(struct GNUNET_GNS_ResolverHandle *rh, uint32_t rd_count,
- const struct GNUNET_NAMESTORE_RecordData *rd)
-{
- int i;
- size_t len;
- int ret;
- char *buf;
- struct GNUNET_DNSPARSER_Packet *packet = rh->packet;
- struct GNUNET_DNSPARSER_Record answer_records[rh->answered];
- struct GNUNET_DNSPARSER_Record additional_records[rd_count-(rh->answered)];
- packet->answers = answer_records;
- packet->additional_records = additional_records;
-
- /**
- * Put records in the DNS packet and modify it
- * to a response
- */
- len = sizeof(struct GNUNET_DNSPARSER_Record*);
- for (i=0; i < rd_count; i++)
- {
-
- GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
- "Adding type %d to DNS response\n", rd[i].record_type);
- GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Name: %s\n", rh->name);
- GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "QName: %s\n", rh->query->name);
- GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Record %d/%d\n", i+1, rd_count);
- GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Record len %d\n", rd[i].data_size);
-
- if (rd[i].record_type == rh->query->type)
- {
- answer_records[i].name = rh->query->name;
- answer_records[i].type = rd[i].record_type;
- answer_records[i].data.raw.data_len = rd[i].data_size;
- answer_records[i].data.raw.data = (char*)rd[i].data;
- answer_records[i].expiration_time = rd[i].expiration;
- answer_records[i].class = GNUNET_DNSPARSER_CLASS_INTERNET;//hmmn
- }
- else
- {
- additional_records[i].name = rh->query->name;
- additional_records[i].type = rd[i].record_type;
- additional_records[i].data.raw.data_len = rd[i].data_size;
- additional_records[i].data.raw.data = (char*)rd[i].data;
- additional_records[i].expiration_time = rd[i].expiration;
- additional_records[i].class = GNUNET_DNSPARSER_CLASS_INTERNET;//hmmn
- }
- }
-
- packet->num_answers = rh->answered;
- packet->num_additional_records = rd_count-(rh->answered);
+ GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
+ "putting records for %s under key: %s with size %d\n",
+ name, GNUNET_h2s (&xor_hash), rd_payload_length);
- if (0 == GNUNET_CRYPTO_hash_cmp(&rh->authority, &zone_hash))
- packet->flags.authoritative_answer = 1;
- else
- packet->flags.authoritative_answer = 0;
-
- if (rd == NULL)
- packet->flags.return_code = GNUNET_DNSPARSER_RETURN_CODE_NAME_ERROR;
- else
- packet->flags.return_code = GNUNET_DNSPARSER_RETURN_CODE_NO_ERROR;
+ GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
+ "DHT req to %d\n", DHT_OPERATION_TIMEOUT.rel_value);
+ /* FIXME: keep return value to possibly cancel? */
+ GNUNET_DHT_put (dht_handle, &xor_hash,
+ DHT_GNS_REPLICATION_LEVEL,
+ GNUNET_DHT_RO_NONE,
+ GNUNET_BLOCK_TYPE_GNS_NAMERECORD,
+ rd_payload_length,
+ (char*)nrb,
+ expiration,
+ DHT_OPERATION_TIMEOUT,
+ &record_dht_put,
+ NULL); //cls for cont
- packet->flags.query_or_response = 1;
+ num_public_records++;
-
/**
- * Reply to DNS
+ * Reschedule periodic put
*/
- GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
- "Building DNS response\n");
- ret = GNUNET_DNSPARSER_pack (packet,
- 1024, /* FIXME magic from dns redirector */
- &buf,
- &len);
- GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
- "Built DNS response! (ret=%d,len=%d)\n", ret, len);
- if (ret == GNUNET_OK)
- {
- GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
- "Answering DNS request\n");
- GNUNET_DNS_request_answer(rh->request_handle,
- len,
- buf);
- //GNUNET_free(answer);
- GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Answered DNS request\n");
- }
- else
- {
- GNUNET_log(GNUNET_ERROR_TYPE_ERROR,
- "Error building DNS response! (ret=%d)", ret);
- }
+ zone_update_taskid = GNUNET_SCHEDULER_add_delayed (record_put_interval,
+ &update_zone_dht_next,
+ NULL);
- GNUNET_free(rh->name);
- GNUNET_free(rh);
-}
+ GNUNET_free(nrb);
+}
/**
- * Namestore calls this function if we have record for this name.
- * (or with rd_count=0 to indicate no matches)
+ * Periodically iterate over our zone and store everything in dht
*
- * @param cls the pending query
- * @param key the key of the zone we did the lookup
- * @param expiration expiration date of the namestore entry
- * @param name the name for which we need an authority
- * @param rd_count the number of records with 'name'
- * @param rd the record data
- * @param signature the signature of the authority for the record data
+ * @param cls NULL
+ * @param tc task context
*/
static void
-process_authoritative_result(void* cls,
- const struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *key,
- struct GNUNET_TIME_Absolute expiration,
- const char *name, unsigned int rd_count,
- const struct GNUNET_NAMESTORE_RecordData *rd,
- const struct GNUNET_CRYPTO_RsaSignature *signature)
+update_zone_dht_start(void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
{
- struct GNUNET_GNS_ResolverHandle *rh;
- struct GNUNET_TIME_Relative remaining_time;
- GNUNET_HashCode zone;
+ unsigned long long interval = 0;
- rh = (struct GNUNET_GNS_ResolverHandle *) cls;
- GNUNET_CRYPTO_hash(key,
- sizeof(struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded),
- &zone);
- remaining_time = GNUNET_TIME_absolute_get_remaining (expiration);
+ zone_update_taskid = GNUNET_SCHEDULER_NO_TASK;
- if (rd_count == 0)
+ GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Scheduling DHT zone update!\n");
+ if (0 == num_public_records)
{
/**
- * Lookup terminated and no results
- * -> DHT Phase unless data is recent
+ * If no records are known (startup) or none present
+ * we can safely set the interval to 1s
*/
+ record_put_interval = GNUNET_TIME_relative_multiply(
+ GNUNET_TIME_UNIT_SECONDS,
+ 1);
GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
- "Namestore lookup for %s terminated without results\n", name);
-
- /**
- * if this is not our zone we cannot rely on the namestore to be
- * complete. -> Query DHT
- */
- if (GNUNET_CRYPTO_hash_cmp(&zone, &zone_hash))
- {
- if (remaining_time.rel_value == 0)
- {
- GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
- "trying dht...\n");
- resolve_name_dht(rh, name);
- return;
- }
- else
- {
- GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
- "Record is still recent. No DHT lookup\n");
- }
- }
-
- /**
- * Our zone and no result? Cannot resolve TT
- */
- GNUNET_assert(rh->answered == 0);
- reply_to_dns(rh, 0, NULL);
- return;
-
+ "No records in db. Adjusted record put interval to 1s\n");
}
else
{
-
+ interval = max_record_put_interval/num_public_records;
+ if (interval == 0)
+ interval = 1;
+ record_put_interval = GNUNET_TIME_relative_multiply(
+ GNUNET_TIME_UNIT_SECONDS,
+ interval);
GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
- "Processing additional result %s from namestore\n", name);
- int i;
- for (i=0; i<rd_count;i++)
- {
-
- if ((strcmp(name, rh->query->name) == 0)
- && (rd[i].record_type != rh->query->type))
- continue;
-
- if ((GNUNET_TIME_absolute_get_remaining (rd[i].expiration)).rel_value
- == 0)
- {
- GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "This record is expired. Skipping\n");
- continue;
- }
-
- rh->answered++;
-
- }
-
- /**
- * no answers found
- * consult dht if expired
- */
- if ((remaining_time.rel_value == 0) && (rh->answered == 0))
- {
- GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
- "This dht entry is old. Refreshing.\n");
- resolve_name_dht(rh, name);
- return;
- }
-
- GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Found %d answer(s) to query!\n",
- rh->answered);
-
- reply_to_dns(rh, rd_count, rd);
+ "Adjusted DHT update interval to %ds!\n",
+ interval);
}
+
+ /* start counting again */
+ num_public_records = 0;
+ namestore_iter = GNUNET_NAMESTORE_zone_iteration_start (namestore_handle,
+ NULL, //All zones
+ GNUNET_NAMESTORE_RF_AUTHORITY,
+ GNUNET_NAMESTORE_RF_PRIVATE,
+ &put_gns_record,
+ NULL);
}
/**
- * Determine if this name is canonical.
- * i.e.
- * a.b.gnunet = not canonical
- * a = canonical
+ * Lookup the private key for the zone
*
- * @param name the name to test
- * @return 1 if canonical
+ * @param zone the zone we want a private key for
+ * @return NULL of not found else the key
*/
-int
-is_canonical(char* name)
+struct GNUNET_CRYPTO_RsaPrivateKey*
+lookup_private_key(struct GNUNET_CRYPTO_ShortHashCode *zone)
{
- uint32_t len = strlen(name);
- int i;
+ char* keydir;
+ struct GNUNET_CRYPTO_ShortHashAsciiEncoded zonename;
+ char* location;
+ struct GNUNET_CRYPTO_RsaPrivateKey *key = NULL;
+
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+ "Looking for private key\n");
- for (i=0; i<len; i++)
+ if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_filename (GNS_cfg,
+ "namestore",
+ "ZONEFILE_DIRECTORY", &keydir))
{
- if (*(name+i) == '.')
- return 0;
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "No zonefile directory!\n");
+ return NULL;
}
- return 1;
-}
-/**
- * Move one level up in the domain hierarchy and return the
- * passed top level domain.
- *
- * @param name the domain
- * @return the tld
- */
-char* pop_tld(char* name)
-{
- uint32_t len;
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+ "Zonefile directory is %s\n", keydir);
- if (is_canonical(name))
- return NULL;
+ GNUNET_CRYPTO_short_hash_to_enc (zone, &zonename);
- for (len = strlen(name); len > 0; len--)
- {
- if (*(name+len) == '.')
- break;
- }
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+ "Zonefile is %s.zkey\n", &zonename);
- if (len == 0)
- return NULL;
+ GNUNET_asprintf(&location, "%s%s%s.zkey", keydir,
+ DIR_SEPARATOR_STR, &zonename);
+
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+ "Checking for %s\n", location);
- name[len] = '\0';
+ if (GNUNET_YES == GNUNET_DISK_file_test (location))
+ key = GNUNET_CRYPTO_rsa_key_create_from_file (location);
+
+ GNUNET_free(location);
+ GNUNET_free(keydir);
+
+ return key;
- return (name+len+1);
}
+/* END DHT ZONE PROPAGATION */
/**
- * The first phase of resolution.
- * First check if the name is canonical.
- * If it is then try to resolve directly.
- * If not then we first have to resolve the authoritative entities.
- *
- * @param rh the pending lookup
+ * Send shorten response back to client
+ *
+ * @param cls the closure containing a client shorten handle
+ * @param name the shortened name result or NULL if cannot be shortened
*/
-void
-resolve_name(struct GNUNET_GNS_ResolverHandle *rh)
+static void
+send_shorten_response(void* cls, const char* name)
{
- if (is_canonical(rh->name))
- {
- /* We only need to check the current zone's ns */
- GNUNET_NAMESTORE_lookup_record(namestore_handle,
- &rh->authority,
- rh->name,
- rh->query->type,
- &process_authoritative_result,
- rh);
- }
- else
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending `%s' message with %s\n",
+ "SHORTEN_RESULT", name);
+ struct GNUNET_GNS_ClientShortenResultMessage *rmsg;
+ struct ClientShortenHandle *csh = (struct ClientShortenHandle *)cls;
+
+ if (name == NULL)
{
- /* We have to resolve the authoritative entity first */
- rh->authority_name = pop_tld(rh->name);
- GNUNET_NAMESTORE_lookup_record(namestore_handle,
- &rh->authority,
- rh->authority_name,
- GNUNET_GNS_RECORD_PKEY,
- &process_authority_lookup,
- rh);
+ name = "";
}
-}
-/**
- * Entry point for name resolution
- * Setup a new query and try to resolve
- *
- * @param request the request handle of the DNS request from a client
- * @param p the DNS query packet we received
- * @param q the DNS query we received parsed from p
- */
-void
-start_resolution(struct GNUNET_DNS_RequestHandle *request,
- struct GNUNET_DNSPARSER_Packet *p,
- struct GNUNET_DNSPARSER_Query *q)
-{
- struct GNUNET_GNS_ResolverHandle *rh;
-
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Starting resolution for (%s)!\n",
- q->name);
+ rmsg = GNUNET_malloc(sizeof(struct GNUNET_GNS_ClientShortenResultMessage)
+ + strlen(name) + 1);
- rh = GNUNET_malloc(sizeof (struct GNUNET_GNS_ResolverHandle));
- rh->packet = p;
- rh->query = q;
- rh->authority = zone_hash;
+ rmsg->id = csh->unique_id;
+ rmsg->header.type = htons(GNUNET_MESSAGE_TYPE_GNS_SHORTEN_RESULT);
+ rmsg->header.size =
+ htons(sizeof(struct GNUNET_GNS_ClientShortenResultMessage) +
+ strlen(name) + 1);
+
+ strcpy((char*)&rmsg[1], name);
+
+ GNUNET_SERVER_notification_context_unicast (nc, csh->client,
+ (const struct GNUNET_MessageHeader *) rmsg,
+ GNUNET_NO);
+ GNUNET_SERVER_receive_done (csh->client, GNUNET_OK);
- rh->name = GNUNET_malloc(strlen(q->name)
- - strlen(gnunet_tld) + 1);
- memset(rh->name, 0,
- strlen(q->name)-strlen(gnunet_tld) + 1);
- memcpy(rh->name, q->name,
- strlen(q->name)-strlen(gnunet_tld));
+ GNUNET_free(rmsg);
+ GNUNET_free_non_null(csh->name);
+ GNUNET_free_non_null(csh->zone_key);
+ GNUNET_free(csh);
- rh->request_handle = request;
-
- /* Start resolution in our zone */
- resolve_name(rh);
}
/**
- * The DNS request handler
- * Called for every incoming DNS request.
+ * Handle a shorten message from the api
*
- * @param cls closure
- * @param rh request handle to user for reply
- * @param request_length number of bytes in request
- * @param request udp payload of the DNS request
+ * @param cls the closure
+ * @param client the client
+ * @param message the message
*/
-void
-handle_dns_request(void *cls,
- struct GNUNET_DNS_RequestHandle *rh,
- size_t request_length,
- const char *request)
+static void handle_shorten(void *cls,
+ struct GNUNET_SERVER_Client * client,
+ const struct GNUNET_MessageHeader * message)
{
- struct GNUNET_DNSPARSER_Packet *p;
- char *tldoffset;
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received `%s' message\n", "SHORTEN");
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Hijacked a DNS request...processing\n");
- p = GNUNET_DNSPARSER_parse (request, request_length);
-
- if (NULL == p)
+ size_t msg_size = 0;
+ struct ClientShortenHandle *csh;
+ char name[MAX_DNS_NAME_LENGTH];
+ char* nameptr = name;
+ struct GNUNET_CRYPTO_ShortHashCode zone;
+ struct GNUNET_CRYPTO_RsaPrivateKey *key;
+
+ if (ntohs (message->size) < sizeof (struct GNUNET_GNS_ClientShortenMessage))
{
- GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
- "Received malformed DNS packet, leaving it untouched\n");
- GNUNET_DNS_request_forward (rh);
+ GNUNET_break_op (0);
+ GNUNET_SERVER_receive_done (client, GNUNET_OK);
return;
}
+
+
+ struct GNUNET_GNS_ClientShortenMessage *sh_msg =
+ (struct GNUNET_GNS_ClientShortenMessage *) message;
- /**
- * Check tld and decide if we or
- * legacy dns is responsible
- *
- * FIXME now in theory there could be more than 1 query in the request
- * but if this is case we get into trouble:
- * either we query the GNS or the DNS. We cannot do both!
- * So I suggest to either only allow a single query per request or
- * only allow GNS or DNS requests.
- * The way it is implemented here now is buggy and will lead to erratic
- * behaviour (if multiple queries are present).
- */
- if (p->num_queries == 0)
- {
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "No Queries in DNS packet... forwarding\n");
- GNUNET_DNS_request_forward (rh);
- }
+ msg_size = ntohs(message->size);
- if (p->num_queries > 1)
+ if (msg_size > GNUNET_SERVER_MAX_MESSAGE_SIZE)
{
- /* Note: We could also look for .gnunet */
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- ">1 queriy in DNS packet... odd. We only process #1\n");
+ GNUNET_break_op (0);
+ GNUNET_SERVER_receive_done (client, GNUNET_OK);
+ return;
}
+ csh = GNUNET_malloc(sizeof(struct ClientShortenHandle));
+ csh->client = client;
+ csh->unique_id = sh_msg->id;
+ csh->zone_key = NULL;
- /**
- * Check for .gnunet
- */
- tldoffset = p->queries[0].name + strlen(p->queries[0].name);
+ GNUNET_STRINGS_utf8_tolower((char*)&sh_msg[1], &nameptr);
+
+ if (strlen (name) < strlen(GNUNET_GNS_TLD)) {
+ GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
+ "SHORTEN: %s is too short", name);
+ csh->name = NULL;
+ send_shorten_response(csh, name);
+ return;
+ }
- while ((*tldoffset) != '.')
- tldoffset--;
+ if (strlen (name) > MAX_DNS_NAME_LENGTH) {
+ GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
+ "SHORTEN: %s is too long", name);
+ csh->name = NULL;
+ send_shorten_response(csh, name);
+ return;
+ }
- if (0 == strcmp(tldoffset, gnunet_tld))
+ if (!is_gnunet_tld(name) && !is_zkey_tld(name))
{
- start_resolution(rh, p, p->queries);
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "%s is not our domain. Returning\n", name);
+ csh->name = NULL;
+ send_shorten_response(csh, name);
+ return;
}
+
+ GNUNET_SERVER_notification_context_add (nc, client);
+
+ if (1 == ntohl(sh_msg->use_default_zone))
+ zone = zone_hash; //Default zone
else
+ zone = sh_msg->zone;
+
+ /* Start shortening */
+ if (GNUNET_YES == auto_import_pkey)
{
- /**
- * This request does not concern us. Forward to real DNS.
- */
- GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
- "Request for %s is forwarded to DNS\n", p->queries[0].name);
- GNUNET_DNS_request_forward (rh);
+ if (1 == ntohl(sh_msg->use_default_zone))
+ key = zone_key;
+ else
+ {
+ key = lookup_private_key(&sh_msg->zone);
+ csh->zone_key = key;
+ }
+ gns_resolver_shorten_name(zone, zone, name, key,
+ &send_shorten_response, csh);
}
-
+ else
+ gns_resolver_shorten_name(zone, zone, name, NULL,
+ &send_shorten_response, csh);
}
+
/**
- * test function that stores some data in the namestore
- * This will also be replaced by a test progrm that
- * directl interfaces with the namestore
+ * Send get authority response back to client
+ *
+ * @param cls the closure containing a client get auth handle
+ * @param name the shortened name result or NULL if cannot be shortened
*/
-void
-put_some_records(void)
+static void
+send_get_auth_response(void *cls, const char* name)
{
- GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Populating namestore\n");
- /* put an A record into namestore FIXME use gnunet.org */
- char* ipB = "5.6.7.8";
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending `%s' message with %s\n",
+ "GET_AUTH_RESULT", name);
+ struct GNUNET_GNS_ClientGetAuthResultMessage *rmsg;
+ struct ClientGetAuthHandle *cah = (struct ClientGetAuthHandle *)cls;
+
+ if (name == NULL)
+ {
+ name = "";
+ }
- struct in_addr *web = GNUNET_malloc(sizeof(struct in_addr));
- struct GNUNET_NAMESTORE_RecordData rdb_web;
+ rmsg = GNUNET_malloc(sizeof(struct GNUNET_GNS_ClientGetAuthResultMessage)
+ + strlen(name) + 1);
+
+ rmsg->id = cah->unique_id;
+ rmsg->header.type = htons(GNUNET_MESSAGE_TYPE_GNS_GET_AUTH_RESULT);
+ rmsg->header.size =
+ htons(sizeof(struct GNUNET_GNS_ClientGetAuthResultMessage) +
+ strlen(name) + 1);
+
+ strcpy((char*)&rmsg[1], name);
+
+ GNUNET_SERVER_notification_context_unicast (nc, cah->client,
+ (const struct GNUNET_MessageHeader *) rmsg,
+ GNUNET_NO);
+ GNUNET_SERVER_receive_done (cah->client, GNUNET_OK);
+
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Cleaning up handles...\n");
- GNUNET_assert(1 == inet_pton (AF_INET, ipB, web));
+ GNUNET_free(rmsg);
+ GNUNET_free_non_null(cah->name);
+ GNUNET_free(cah);
- rdb_web.data_size = sizeof(struct in_addr);
- rdb_web.data = web;
- rdb_web.record_type = GNUNET_DNSPARSER_TYPE_A;
- rdb_web.expiration = GNUNET_TIME_absolute_get_forever ();
-
- GNUNET_NAMESTORE_record_create (namestore_handle,
- zone_key,
- "www",
- &rdb_web,
- NULL,
- NULL);
-}
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "done.\n");
-/**
- * Method called periodicattluy that triggers
- * iteration over root zone
- *
- * @param cls closure
- * @param tc task context
- */
-void
-update_zone_dht_next(void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
-{
- GNUNET_NAMESTORE_zone_iterator_next(namestore_iter);
}
+
/**
- * Continuation for DHT put
+ * Handle a get authority message from the api
*
- * @param cls closure
- * @param tc task context
+ * @param cls the closure
+ * @param client the client
+ * @param message the message
*/
-void
-record_dht_put(void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
+static void handle_get_authority(void *cls,
+ struct GNUNET_SERVER_Client * client,
+ const struct GNUNET_MessageHeader * message)
{
- GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "put request transmitted\n");
-}
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received `%s' message\n", "GET_AUTH");
-/* prototype */
-static void
-update_zone_dht_start(void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc);
+ size_t msg_size = 0;
+ struct ClientGetAuthHandle *cah;
+ char name[MAX_DNS_NAME_LENGTH];
+ char* nameptr = name;
-/**
- * Function used to put all records successively into the DHT.
- * FIXME bug here
- *
- * @param cls the closure (NULL)
- * @param key the public key of the authority (ours)
- * @param expiration lifetime of the namestore entry
- * @param name the name of the records
- * @param rd_count the number of records in data
- * @param rd the record data
- * @param signature the signature for the record data
- */
-void
-put_gns_record(void *cls,
- const struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *key,
- struct GNUNET_TIME_Absolute expiration,
- const char *name,
- unsigned int rd_count,
- const struct GNUNET_NAMESTORE_RecordData *rd,
- const struct GNUNET_CRYPTO_RsaSignature *signature)
-{
- GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
- "Putting records for %s into the DHT\n", name);
- struct GNUNET_TIME_Relative timeout;
- struct GNSNameRecordBlock *nrb;
- struct GNSRecordBlock *rb;
- GNUNET_HashCode name_hash;
- GNUNET_HashCode xor_hash;
- struct GNUNET_CRYPTO_HashAsciiEncoded xor_hash_string;
- int i;
- uint32_t rd_payload_length;
- /* we're done */
- if (NULL == name)
+ if (ntohs (message->size) < sizeof (struct GNUNET_GNS_ClientGetAuthMessage))
{
- GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Zone iteration finished\n");
- GNUNET_NAMESTORE_zone_iteration_stop (namestore_iter);
- zone_update_taskid = GNUNET_SCHEDULER_add_now (&update_zone_dht_start,
- NULL);
+ GNUNET_break_op (0);
+ GNUNET_SERVER_receive_done (client, GNUNET_OK);
return;
}
+
+ GNUNET_SERVER_notification_context_add (nc, client);
+
+ struct GNUNET_GNS_ClientGetAuthMessage *sh_msg =
+ (struct GNUNET_GNS_ClientGetAuthMessage *) message;
- rd_payload_length = rd_count * sizeof(struct GNSRecordBlock);
- rd_payload_length += strlen(name) + 1 + sizeof(struct GNSNameRecordBlock);
-
- /* calculate payload size */
- for (i=0; i<rd_count; i++)
+ msg_size = ntohs(message->size);
+
+ if (msg_size > GNUNET_SERVER_MAX_MESSAGE_SIZE)
{
- rd_payload_length += rd[i].data_size;
+ GNUNET_break_op (0);
+ GNUNET_SERVER_receive_done (client, GNUNET_OK);
+ return;
}
- nrb = GNUNET_malloc(rd_payload_length);
-
- if (signature != NULL)
- memcpy(&nrb->signature, signature,
- sizeof(struct GNUNET_CRYPTO_RsaSignature));
- //FIXME signature purpose
- memcpy(&nrb->public_key, key,
- sizeof(struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded));
+ GNUNET_STRINGS_utf8_tolower((char*)&sh_msg[1], &nameptr);
- nrb->rd_count = htonl(rd_count);
- memcpy(&nrb[1], name, strlen(name) + 1); //FIXME is this 0 terminated??
+ cah = GNUNET_malloc(sizeof(struct ClientGetAuthHandle));
+ cah->client = client;
+ cah->unique_id = sh_msg->id;
- rb = (struct GNSRecordBlock *)((char*)&nrb[1] + strlen(name) + 1);
-
- for (i=0; i<rd_count; i++)
+ if (strlen(name) < strlen(GNUNET_GNS_TLD))
{
- GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Read record with type %d\n",
- rd[i].record_type);
- rb->type = htonl(rd[i].record_type);
- rb->expiration = GNUNET_TIME_absolute_hton(rd[i].expiration);
- rb->data_length = htonl(rd[i].data_size);
- rb->flags = htonl(rd[i].flags);
- memcpy(&rb[1], rd[i].data, rd[i].data_size);
- rb = &rb[1] + rd[i].data_size;
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "GET_AUTH: %s is too short. Returning\n", name);
+ cah->name = NULL;
+ send_get_auth_response(cah, name);
+ return;
}
-
- /**
- * FIXME magic number 20 move to config file
- * DHT_WAIT_TIMEOUT
- */
- timeout = GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 20);
- /*
- * calculate DHT key: H(name) xor H(pubkey)
- */
- GNUNET_CRYPTO_hash(name, strlen(name), &name_hash);
- GNUNET_CRYPTO_hash_xor(&zone_hash, &name_hash, &xor_hash);
- GNUNET_CRYPTO_hash_to_enc (&xor_hash, &xor_hash_string);
- GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
- "putting records for %s under key: %s with size %d\n",
- name, (char*)&xor_hash_string, rd_payload_length);
+ if (strlen (name) > MAX_DNS_NAME_LENGTH) {
+ GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
+ "GET_AUTH: %s is too long", name);
+ cah->name = NULL;
+ send_get_auth_response(cah, name);
+ return;
+ }
+
+ if (strcmp(name+strlen(name)-strlen(GNUNET_GNS_TLD),
+ GNUNET_GNS_TLD) != 0)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "GET_AUTH: %s is not our domain. Returning\n", name);
+ cah->name = NULL;
+ send_get_auth_response(cah, name);
+ return;
+ }
- GNUNET_DHT_put (dht_handle, &xor_hash,
- 5, //replication level
- GNUNET_DHT_RO_NONE,
- GNUNET_BLOCK_TYPE_GNS_NAMERECORD, //FIXME todo block plugin
- rd_payload_length,
- (char*)nrb,
- expiration,
- timeout,
- &record_dht_put, //FIXME continuation needed? success check? yes ofc
- NULL); //cls for cont
+ if (strcmp(name, GNUNET_GNS_TLD) == 0)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "GET_AUTH: %s is us. Returning\n", name);
+ cah->name = NULL;
+ send_get_auth_response(cah, name);
+ return;
+ }
- num_public_records++;
+ cah->name = GNUNET_malloc(strlen(name)
+ - strlen(GNUNET_GNS_TLD) + 1);
+ memset(cah->name, 0,
+ strlen(name)-strlen(GNUNET_GNS_TLD) + 1);
+ memcpy(cah->name, name,
+ strlen(name)-strlen(GNUNET_GNS_TLD));
+
+ /* Start delegation resolution in our namestore */
+ gns_resolver_get_authority(zone_hash, zone_hash, name, &send_get_auth_response, cah);
+}
- /**
- * Reschedule periodic put
- */
- zone_update_taskid = GNUNET_SCHEDULER_add_delayed (dht_update_interval,
- &update_zone_dht_next,
- NULL);
-}
/**
- * Puts a single trusted entity into the
- * namestore. Will be replaced in a testcase
- * that directly interacts with a persistent
- * namestore.
+ * Reply to client with the result from our lookup.
*
- * @param name name of entity
- * @param keyfile keyfile
+ * @param cls the closure (our client lookup handle)
+ * @param rd_count the number of records
+ * @param rd the record data
*/
-void
-put_trusted(char* name, char* keyfile)
+static void
+send_lookup_response(void* cls,
+ uint32_t rd_count,
+ const struct GNUNET_NAMESTORE_RecordData *rd)
{
- struct GNUNET_NAMESTORE_RecordData rd;
- struct GNUNET_CRYPTO_RsaPrivateKey *key;
- struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *pkey;
- pkey = GNUNET_malloc(sizeof(struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded));
-
- key = GNUNET_CRYPTO_rsa_key_create_from_file (keyfile);
- GNUNET_CRYPTO_rsa_key_get_public (key, pkey);
- rd.data = pkey;
- rd.expiration = GNUNET_TIME_absolute_get_forever ();
- rd.data_size = sizeof(struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded);
- rd.record_type = GNUNET_GNS_RECORD_PKEY;
-
- GNUNET_NAMESTORE_record_create (namestore_handle,
- zone_key,
- name,
- &rd,
- NULL,
- NULL);
-}
+ struct ClientLookupHandle* clh = (struct ClientLookupHandle*)cls;
+ struct GNUNET_GNS_ClientLookupResultMessage *rmsg;
+ size_t len;
+
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending `%s' message with %d results\n",
+ "LOOKUP_RESULT", rd_count);
+
+ len = GNUNET_NAMESTORE_records_get_size (rd_count, rd);
+ rmsg = GNUNET_malloc(len+sizeof(struct GNUNET_GNS_ClientLookupResultMessage));
+
+ rmsg->id = clh->unique_id;
+ rmsg->rd_count = htonl(rd_count);
+ rmsg->header.type = htons(GNUNET_MESSAGE_TYPE_GNS_LOOKUP_RESULT);
+ rmsg->header.size =
+ htons(len+sizeof(struct GNUNET_GNS_ClientLookupResultMessage));
+ GNUNET_NAMESTORE_records_serialize (rd_count, rd, len, (char*)&rmsg[1]);
+
+ GNUNET_SERVER_notification_context_unicast (nc, clh->client,
+ (const struct GNUNET_MessageHeader *) rmsg,
+ GNUNET_NO);
+ GNUNET_SERVER_receive_done (clh->client, GNUNET_OK);
+
+ GNUNET_free(rmsg);
+ GNUNET_free(clh->name);
+
+ if (NULL != clh->zone_key)
+ GNUNET_free(clh->zone_key);
+
+ GNUNET_free(clh);
+
+}
/**
- * Periodically iterate over our zone and store everything in dht
+ * Handle lookup requests from client
*
- * @param cls NULL
- * @param tc task context
+ * @param cls the closure
+ * @param client the client
+ * @param message the message
*/
static void
-update_zone_dht_start(void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
+handle_lookup(void *cls,
+ struct GNUNET_SERVER_Client * client,
+ const struct GNUNET_MessageHeader * message)
{
- GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Starting DHT zone update!\n");
- if (0 == num_public_records)
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received `%s' message\n", "LOOKUP");
+
+ size_t msg_size = 0;
+ size_t namelen;
+ char name[MAX_DNS_NAME_LENGTH];
+ struct ClientLookupHandle *clh;
+ char* nameptr = name;
+ struct GNUNET_CRYPTO_RsaPrivateKey *key = NULL;
+ struct GNUNET_CRYPTO_ShortHashCode zone;
+
+ if (ntohs (message->size) < sizeof (struct GNUNET_GNS_ClientLookupMessage))
{
- dht_update_interval = GNUNET_TIME_relative_multiply(
- GNUNET_TIME_UNIT_SECONDS,
- 1);
+ GNUNET_break_op (0);
+ GNUNET_SERVER_receive_done (client, GNUNET_OK);
+ return;
+ }
+
+ GNUNET_SERVER_notification_context_add (nc, client);
+
+ struct GNUNET_GNS_ClientLookupMessage *sh_msg =
+ (struct GNUNET_GNS_ClientLookupMessage *) message;
+
+ msg_size = ntohs(message->size);
+
+ if (msg_size > GNUNET_SERVER_MAX_MESSAGE_SIZE)
+ {
+ GNUNET_break_op (0);
+ GNUNET_SERVER_receive_done (client, GNUNET_OK);
+ return;
}
+
+ GNUNET_STRINGS_utf8_tolower((char*)&sh_msg[1], &nameptr);
+ namelen = strlen(name)+1;
+ clh = GNUNET_malloc(sizeof(struct ClientLookupHandle));
+ clh->client = client;
+ clh->name = GNUNET_malloc(namelen);
+ strcpy(clh->name, name);
+ clh->unique_id = sh_msg->id;
+ clh->type = ntohl(sh_msg->type);
+ clh->zone_key = NULL;
+
+ if (strlen (name) > MAX_DNS_NAME_LENGTH) {
+ GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
+ "LOOKUP: %s is too long", name);
+ clh->name = NULL;
+ send_lookup_response(clh, 0, NULL);
+ return;
+ }
+
+ if (1 == ntohl(sh_msg->use_default_zone))
+ zone = zone_hash; //Default zone
else
+ zone = sh_msg->zone;
+
+ if (GNUNET_YES == auto_import_pkey)
{
- dht_update_interval = GNUNET_TIME_relative_multiply(
- GNUNET_TIME_UNIT_SECONDS,
- (3600/num_public_records));
+ if (1 == ntohl(sh_msg->use_default_zone))
+ key = zone_key;
+ else
+ {
+ key = lookup_private_key(&zone);
+ clh->zone_key = key;
+ }
+
+ gns_resolver_lookup_record(zone, zone, clh->type, name,
+ key,
+ default_lookup_timeout,
+ &send_lookup_response, clh);
+ }
+ else
+ {
+ gns_resolver_lookup_record(zone, zone, clh->type, name,
+ NULL,
+ default_lookup_timeout,
+ &send_lookup_response, clh);
}
- num_public_records = 0; //start counting again
- namestore_iter = GNUNET_NAMESTORE_zone_iteration_start (namestore_handle,
- &zone_hash,
- GNUNET_NAMESTORE_RF_AUTHORITY,
- GNUNET_NAMESTORE_RF_PRIVATE,
- &put_gns_record,
- NULL);
}
+
+
/**
* Process GNS requests.
*
- * @param cls closure
+ * @param cls closure)
* @param server the initialized server
* @param c configuration to use
*/
@@ -1250,53 +909,41 @@ run (void *cls, struct GNUNET_SERVER_Handle *server,
{
GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Initializing GNS\n");
-
+
char* keyfile;
- char* trusted_entities;
struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded pkey;
+ unsigned long long max_parallel_bg_queries = 0;
+ unsigned long long default_lookup_timeout_secs = 0;
+ int ignore_pending = GNUNET_NO;
+
+ static const struct GNUNET_SERVER_MessageHandler handlers[] = {
+ {&handle_shorten, NULL, GNUNET_MESSAGE_TYPE_GNS_SHORTEN, 0},
+ {&handle_lookup, NULL, GNUNET_MESSAGE_TYPE_GNS_LOOKUP, 0},
+ {&handle_get_authority, NULL, GNUNET_MESSAGE_TYPE_GNS_GET_AUTH, 0}
+ };
+
+ GNS_cfg = c;
- if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_string (c, "gns",
+ if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_filename (c, "gns",
"ZONEKEY", &keyfile))
{
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- "No private key for root zone specified%s!\n", keyfile);
- GNUNET_SCHEDULER_shutdown(0);
+ "No private key for root zone specified!\n");
+ GNUNET_SCHEDULER_shutdown ();
return;
}
+ GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
+ "Using keyfile %s for root zone.\n", keyfile);
+
zone_key = GNUNET_CRYPTO_rsa_key_create_from_file (keyfile);
GNUNET_CRYPTO_rsa_key_get_public (zone_key, &pkey);
- GNUNET_CRYPTO_hash(&pkey, sizeof(struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded),
+ GNUNET_CRYPTO_short_hash(&pkey,
+ sizeof(struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded),
&zone_hash);
+ GNUNET_free(keyfile);
- nc = GNUNET_SERVER_notification_context_create (server, 1);
-
- GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL, &shutdown_task,
- NULL);
-
- if (GNUNET_YES ==
- GNUNET_CONFIGURATION_get_value_yesno (c, "gns",
- "HIJACK_DNS"))
- {
- GNUNET_log(GNUNET_ERROR_TYPE_INFO,
- "DNS hijacking enabled... connecting to service.\n");
- /**
- * Do gnunet dns init here
- */
- dns_handle = GNUNET_DNS_connect(c,
- GNUNET_DNS_FLAG_PRE_RESOLUTION,
- &handle_dns_request, /* rh */
- NULL); /* Closure */
- if (NULL == dns_handle)
- {
- GNUNET_log(GNUNET_ERROR_TYPE_ERROR,
- "Failed to connect to the dnsservice!\n");
- }
- }
-
-
-
/**
* handle to our local namestore
*/
@@ -1307,73 +954,135 @@ run (void *cls, struct GNUNET_SERVER_Handle *server,
//FIXME do error handling;
GNUNET_log(GNUNET_ERROR_TYPE_ERROR,
"Failed to connect to the namestore!\n");
- GNUNET_SCHEDULER_shutdown(0);
+ GNUNET_SCHEDULER_shutdown ();
return;
}
- char* trusted_start;
- char* trusted_name;
- char *trusted_key;
- int trusted_len;
- if (GNUNET_OK == GNUNET_CONFIGURATION_get_value_string (c, "gns",
- "TRUSTED",
- &trusted_entities))
+
+
+ auto_import_pkey = GNUNET_NO;
+
+ if (GNUNET_YES ==
+ GNUNET_CONFIGURATION_get_value_yesno (c, "gns",
+ "AUTO_IMPORT_PKEY"))
{
- trusted_start = trusted_entities;
- trusted_len = strlen(trusted_entities);
GNUNET_log(GNUNET_ERROR_TYPE_INFO,
- "Found trusted entities in config file, importing\n");
- while ((trusted_entities-trusted_start) < trusted_len)
- {
- trusted_name = trusted_entities;
- while (*trusted_entities != ':')
- trusted_entities++;
- *trusted_entities = '\0';
- trusted_entities++;
- trusted_key = trusted_entities;
- while (*trusted_entities != ',' && (*trusted_entities != '\0'))
- trusted_entities++;
- *trusted_entities = '\0';
- trusted_entities++;
-
- if (GNUNET_YES == GNUNET_DISK_file_test (trusted_key))
- {
- GNUNET_log(GNUNET_ERROR_TYPE_INFO, "Adding %s:%s to root zone\n",
- trusted_name,
- trusted_key);
- put_trusted(trusted_name, trusted_key);
- }
- else
- {
- GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Keyfile %s does not exist!\n",
- trusted_key);
- //put_trusted(trusted_name, trusted_key); //FIXME for testing
- }
- }
+ "Automatic PKEY import is enabled.\n");
+ auto_import_pkey = GNUNET_YES;
}
+ dht_max_update_interval = GNUNET_GNS_DHT_MAX_UPDATE_INTERVAL;
+
+ if (GNUNET_OK ==
+ GNUNET_CONFIGURATION_get_value_number (c, "gns",
+ "ZONE_PUT_INTERVAL",
+ &dht_max_update_interval))
+ {
+ GNUNET_log(GNUNET_ERROR_TYPE_INFO,
+ "DHT zone update interval: %d\n",
+ dht_max_update_interval);
+ }
+
+ max_record_put_interval = 1;
+
+ if (GNUNET_OK ==
+ GNUNET_CONFIGURATION_get_value_number (c, "gns",
+ "RECORD_PUT_INTERVAL",
+ &max_record_put_interval))
+ {
+ GNUNET_log(GNUNET_ERROR_TYPE_INFO,
+ "Record put interval: %d\n",
+ max_record_put_interval);
+ }
+
+ if (GNUNET_OK ==
+ GNUNET_CONFIGURATION_get_value_number (c, "gns",
+ "MAX_PARALLEL_BACKGROUND_QUERIES",
+ &max_parallel_bg_queries))
+ {
+ GNUNET_log(GNUNET_ERROR_TYPE_INFO,
+ "Number of allowed parallel background queries: %d\n",
+ max_parallel_bg_queries);
+ }
+
+ if (GNUNET_YES ==
+ GNUNET_CONFIGURATION_get_value_yesno (c, "gns",
+ "AUTO_IMPORT_CONFIRMATION_REQ"))
+ {
+ GNUNET_log(GNUNET_ERROR_TYPE_INFO,
+ "Auto import requires user confirmation\n");
+ ignore_pending = GNUNET_YES;
+ }
+
+ if (GNUNET_OK ==
+ GNUNET_CONFIGURATION_get_value_number(c, "gns",
+ "DEFAULT_LOOKUP_TIMEOUT",
+ &default_lookup_timeout_secs))
+ {
+ GNUNET_log(GNUNET_ERROR_TYPE_INFO,
+ "Default lookup timeout: %ds\n", default_lookup_timeout_secs);
+ default_lookup_timeout = GNUNET_TIME_relative_multiply(
+ GNUNET_TIME_UNIT_SECONDS,
+ default_lookup_timeout_secs);
+ }
+
/**
* handle to the dht
*/
- dht_handle = GNUNET_DHT_connect(c, 1); //FIXME get ht_len from cfg
+ dht_handle = GNUNET_DHT_connect(c,
+ //max_parallel_bg_queries); //FIXME get ht_len from cfg
+ 1024);
if (NULL == dht_handle)
{
GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Could not connect to DHT!\n");
}
+
+ if (gns_resolver_init(namestore_handle, dht_handle, zone_hash,
+ max_parallel_bg_queries,
+ ignore_pending)
+ == GNUNET_SYSERR)
+ {
+ GNUNET_log(GNUNET_ERROR_TYPE_ERROR,
+ "Unable to initialize resolver!\n");
+ GNUNET_SCHEDULER_add_now (&shutdown_task, NULL);
+ return;
+ }
- put_some_records(); //FIXME for testing
+ if (GNUNET_YES ==
+ GNUNET_CONFIGURATION_get_value_yesno (c, "gns", "HIJACK_DNS"))
+ {
+ GNUNET_log(GNUNET_ERROR_TYPE_INFO,
+ "DNS hijacking enabled... connecting to service.\n");
+
+ if (gns_interceptor_init(zone_hash, zone_key, c) == GNUNET_SYSERR)
+ {
+ GNUNET_log(GNUNET_ERROR_TYPE_ERROR,
+ "Failed to enable the dns interceptor!\n");
+ }
+ }
/**
* Schedule periodic put
* for our records
* We have roughly an hour for all records;
*/
- dht_update_interval = GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_SECONDS,
+ record_put_interval = GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_SECONDS,
1);
zone_update_taskid = GNUNET_SCHEDULER_add_now (&update_zone_dht_start, NULL);
+ GNUNET_SERVER_add_handlers (server, handlers);
+
+ //FIXME
+ //GNUNET_SERVER_disconnect_notify (server,
+ // &client_disconnect_notification,
+ // NULL);
+
+ nc = GNUNET_SERVER_notification_context_create (server, 1);
+
+ GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL, &shutdown_task,
+ NULL);
}
diff --git a/src/gns/gnunet-service-gns_interceptor.c b/src/gns/gnunet-service-gns_interceptor.c
new file mode 100644
index 0000000..adb09ca
--- /dev/null
+++ b/src/gns/gnunet-service-gns_interceptor.c
@@ -0,0 +1,394 @@
+/*
+ This file is part of GNUnet.
+ (C) 2009, 2010, 2011 Christian Grothoff (and other contributing authors)
+
+ GNUnet is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 3, or (at your
+ option) any later version.
+
+ GNUnet is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GNUnet; see the file COPYING. If not, write to the
+ Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+
+/**
+ *
+ * @file gns/gnunet-service-gns_interceptor.c
+ * @brief GNUnet GNS interceptor logic
+ * @author Martin Schanzenbach
+ */
+#include "platform.h"
+#include "gnunet_util_lib.h"
+#include "gnunet_transport_service.h"
+#include "gnunet_dns_service.h"
+#include "gnunet_dnsparser_lib.h"
+#include "gnunet-service-gns_resolver.h"
+#include "gns.h"
+
+#define MAX_DNS_LABEL_LENGTH 63
+
+/**
+ * Handle to a DNS intercepted
+ * reslution request
+ */
+struct InterceptLookupHandle
+{
+ /* the request handle to reply to */
+ struct GNUNET_DNS_RequestHandle *request_handle;
+
+ /* the dns parser packet received */
+ struct GNUNET_DNSPARSER_Packet *packet;
+
+ /* the query parsed from the packet */
+ struct GNUNET_DNSPARSER_Query *query;
+};
+
+
+/**
+ * Our handle to the DNS handler library
+ */
+static struct GNUNET_DNS_Handle *dns_handle;
+
+/**
+ * The root zone for this interceptor
+ */
+static struct GNUNET_CRYPTO_ShortHashCode our_zone;
+
+/**
+ * Our priv key
+ */
+static struct GNUNET_CRYPTO_RsaPrivateKey *our_key;
+
+/**
+ * Default timeout
+ */
+static struct GNUNET_TIME_Relative default_lookup_timeout;
+
+/**
+ * Reply to dns request with the result from our lookup.
+ *
+ * @param cls the closure to the request (an InterceptLookupHandle)
+ * @param rd_count the number of records to return
+ * @param rd the record data
+ */
+static void
+reply_to_dns(void* cls, uint32_t rd_count,
+ const struct GNUNET_NAMESTORE_RecordData *rd)
+{
+ int i;
+ size_t len;
+ int ret;
+ char *buf;
+ struct InterceptLookupHandle* ilh = (struct InterceptLookupHandle*)cls;
+ struct GNUNET_DNSPARSER_Packet *packet = ilh->packet;
+ unsigned int num_answers = 0;
+
+
+ /**
+ * Put records in the DNS packet and modify it
+ * to a response
+ */
+ for (i=0; i < rd_count; i++)
+ {
+ if (rd[i].record_type == ilh->query->type)
+ num_answers++;
+ }
+
+ struct GNUNET_DNSPARSER_Record answer_records[num_answers];
+ struct GNUNET_DNSPARSER_Record additional_records[rd_count-(num_answers)];
+ packet->answers = answer_records;
+ packet->additional_records = additional_records;
+
+ for (i=0; i < rd_count; i++)
+ {
+ GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
+ "Adding type %d to DNS response\n", rd[i].record_type);
+ GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Name: %s\n", ilh->query->name);
+ GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Record %d/%d\n", i+1, rd_count);
+ GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Record len %d\n", rd[i].data_size);
+
+ if (rd[i].record_type == ilh->query->type)
+ {
+ answer_records[i].name = ilh->query->name;
+ answer_records[i].type = rd[i].record_type;
+ switch(rd[i].record_type)
+ {
+ case GNUNET_GNS_RECORD_TYPE_NS:
+ case GNUNET_GNS_RECORD_TYPE_CNAME:
+ case GNUNET_GNS_RECORD_TYPE_PTR:
+ answer_records[i].data.hostname = (char*)rd[i].data;
+ break;
+ case GNUNET_GNS_RECORD_TYPE_SOA:
+ answer_records[i].data.soa =
+ (struct GNUNET_DNSPARSER_SoaRecord *)rd[i].data;
+ break;
+ case GNUNET_GNS_RECORD_MX:
+ answer_records[i].data.mx =
+ (struct GNUNET_DNSPARSER_MxRecord *)rd[i].data;
+ break;
+ default:
+ answer_records[i].data.raw.data_len = rd[i].data_size;
+ answer_records[i].data.raw.data = (char*)rd[i].data;
+ }
+ answer_records[i].expiration_time = rd[i].expiration;
+ answer_records[i].class = GNUNET_DNSPARSER_CLASS_INTERNET;//hmmn
+ }
+ else
+ {
+ additional_records[i].name = ilh->query->name;
+ additional_records[i].type = rd[i].record_type;
+ switch(rd[i].record_type)
+ {
+ case GNUNET_GNS_RECORD_TYPE_NS:
+ case GNUNET_GNS_RECORD_TYPE_CNAME:
+ case GNUNET_GNS_RECORD_TYPE_PTR:
+ additional_records[i].data.hostname = (char*)rd[i].data;
+ break;
+ case GNUNET_GNS_RECORD_TYPE_SOA:
+ additional_records[i].data.soa =
+ (struct GNUNET_DNSPARSER_SoaRecord *)rd[i].data;
+ break;
+ case GNUNET_GNS_RECORD_MX:
+ additional_records[i].data.mx =
+ (struct GNUNET_DNSPARSER_MxRecord *)rd[i].data;
+ break;
+ default:
+ additional_records[i].data.raw.data_len = rd[i].data_size;
+ additional_records[i].data.raw.data = (char*)rd[i].data;
+ }
+ additional_records[i].expiration_time = rd[i].expiration;
+ additional_records[i].class = GNUNET_DNSPARSER_CLASS_INTERNET;//hmmn
+ }
+ }
+
+ packet->num_answers = num_answers;
+ packet->num_additional_records = rd_count-(num_answers);
+
+ packet->flags.authoritative_answer = 1;
+
+ if (rd == NULL)
+ packet->flags.return_code = GNUNET_DNSPARSER_RETURN_CODE_NAME_ERROR;
+ else
+ packet->flags.return_code = GNUNET_DNSPARSER_RETURN_CODE_NO_ERROR;
+
+ packet->flags.query_or_response = 1;
+
+
+ /**
+ * Reply to DNS
+ */
+ GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
+ "Building DNS response\n");
+ ret = GNUNET_DNSPARSER_pack (packet,
+ 1024, /* FIXME magic from dns redirector */
+ &buf,
+ &len);
+ GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
+ "Built DNS response! (ret=%d,len=%d)\n", ret, len);
+ if (ret == GNUNET_OK)
+ {
+ GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
+ "Answering DNS request\n");
+ GNUNET_DNS_request_answer(ilh->request_handle,
+ len,
+ buf);
+
+ GNUNET_free(buf);
+ GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Answered DNS request\n");
+ }
+ else
+ {
+ GNUNET_log(GNUNET_ERROR_TYPE_ERROR,
+ "Error building DNS response! (ret=%d)", ret);
+ }
+
+ packet->num_answers = 0;
+ packet->answers = NULL;
+ packet->num_additional_records = 0;
+ packet->additional_records = NULL;
+ GNUNET_DNSPARSER_free_packet(packet);
+ GNUNET_free(ilh);
+}
+
+
+/**
+ * Entry point for name resolution
+ * Setup a new query and try to resolve
+ *
+ * @param request the request handle of the DNS request from a client
+ * @param p the DNS query packet we received
+ * @param q the DNS query we received parsed from p
+ */
+static void
+start_resolution_for_dns(struct GNUNET_DNS_RequestHandle *request,
+ struct GNUNET_DNSPARSER_Packet *p,
+ struct GNUNET_DNSPARSER_Query *q)
+{
+ struct InterceptLookupHandle* ilh;
+
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Starting resolution for %s (type=%d)!\n",
+ q->name, q->type);
+
+ ilh = GNUNET_malloc(sizeof(struct InterceptLookupHandle));
+ ilh->packet = p;
+ ilh->query = q;
+ ilh->request_handle = request;
+
+ /* Start resolution in our zone */
+ gns_resolver_lookup_record(our_zone, our_zone, q->type, q->name,
+ our_key,
+ default_lookup_timeout,
+ &reply_to_dns, ilh);
+}
+
+
+
+/**
+ * The DNS request handler
+ * Called for every incoming DNS request.
+ *
+ * @param cls closure
+ * @param rh request handle to user for reply
+ * @param request_length number of bytes in request
+ * @param request udp payload of the DNS request
+ */
+static void
+handle_dns_request(void *cls,
+ struct GNUNET_DNS_RequestHandle *rh,
+ size_t request_length,
+ const char *request)
+{
+ struct GNUNET_DNSPARSER_Packet *p;
+
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Hijacked a DNS request...processing\n");
+ p = GNUNET_DNSPARSER_parse (request, request_length);
+
+ if (NULL == p)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+ "Received malformed DNS packet, leaving it untouched\n");
+ GNUNET_DNS_request_forward (rh);
+ GNUNET_DNSPARSER_free_packet (p);
+ return;
+ }
+
+ /**
+ * Check tld and decide if we or
+ * legacy dns is responsible
+ *
+ * FIXME now in theory there could be more than 1 query in the request
+ * but if this is case we get into trouble:
+ * either we query the GNS or the DNS. We cannot do both!
+ * So I suggest to either only allow a single query per request or
+ * only allow GNS or DNS requests.
+ * The way it is implemented here now is buggy and will lead to erratic
+ * behaviour (if multiple queries are present).
+ */
+ if (p->num_queries == 0)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "No Queries in DNS packet... forwarding\n");
+ GNUNET_DNS_request_forward (rh);
+ GNUNET_DNSPARSER_free_packet(p);
+ return;
+ }
+
+ if (p->num_queries > 1)
+ {
+ /* Note: We could also look for .gnunet */
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ ">1 queriy in DNS packet... odd. We only process #1\n");
+ }
+
+
+ /**
+ * Check for .gnunet/.zkey
+ */
+
+ if ((is_gnunet_tld(p->queries[0].name) == GNUNET_YES) ||
+ (is_zkey_tld(p->queries[0].name) == GNUNET_YES) ||
+ (strcmp(p->queries[0].name, GNUNET_GNS_TLD) == 0))
+ {
+ start_resolution_for_dns(rh, p, p->queries);
+ }
+ else
+ {
+ /**
+ * This request does not concern us. Forward to real DNS.
+ */
+ GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
+ "Request for %s is forwarded to DNS\n", p->queries[0].name);
+ GNUNET_DNS_request_forward (rh);
+ GNUNET_DNSPARSER_free_packet (p);
+ }
+
+}
+
+
+/**
+ * Initialized the interceptor
+ *
+ * @param zone the zone to work in
+ * @param key the prov key of the zone (can be null, needed for caching)
+ * @param c the configuration
+ * @return GNUNET_OK on success
+ */
+int
+gns_interceptor_init(struct GNUNET_CRYPTO_ShortHashCode zone,
+ struct GNUNET_CRYPTO_RsaPrivateKey *key,
+ const struct GNUNET_CONFIGURATION_Handle *c)
+{
+ unsigned long long default_lookup_timeout_secs = 0;
+
+ GNUNET_log(GNUNET_ERROR_TYPE_INFO,
+ "DNS hijacking enabled... connecting to service.\n");
+
+ our_zone = zone;
+ our_key = key;
+ /**
+ * Do gnunet dns init here
+ */
+ dns_handle = GNUNET_DNS_connect(c,
+ GNUNET_DNS_FLAG_PRE_RESOLUTION,
+ &handle_dns_request, /* rh */
+ NULL); /* Closure */
+
+ if (GNUNET_OK ==
+ GNUNET_CONFIGURATION_get_value_number(c, "gns",
+ "DEFAULT_LOOKUP_TIMEOUT",
+ &default_lookup_timeout_secs))
+ {
+ default_lookup_timeout = GNUNET_TIME_relative_multiply(
+ GNUNET_TIME_UNIT_SECONDS,
+ default_lookup_timeout_secs);
+ }
+
+ if (NULL == dns_handle)
+ {
+ GNUNET_log(GNUNET_ERROR_TYPE_ERROR,
+ "Failed to connect to the dnsservice!\n");
+ return GNUNET_SYSERR;
+ }
+
+ return GNUNET_YES;
+}
+
+/**
+ * Disconnect from interceptor
+ */
+void
+gns_interceptor_stop(void)
+{
+ if (dns_handle)
+ GNUNET_DNS_disconnect(dns_handle);
+}
+
+/* end of gns_interceptor.c */
diff --git a/src/gns/gnunet-service-gns_interceptor.h b/src/gns/gnunet-service-gns_interceptor.h
new file mode 100644
index 0000000..dc39aec
--- /dev/null
+++ b/src/gns/gnunet-service-gns_interceptor.h
@@ -0,0 +1,23 @@
+#ifndef GNUNET_GNS_INTERCEPTOR_H
+#define GNUNET_GNS_INTERCEPTOR_H
+
+/**
+ * Initialize dns interceptor
+ *
+ * @param zone the zone
+ * @param key the private key of the local zone
+ * @param c the configuration
+ * @return GNUNET_YES on success GNUNET_SYSERR on error
+ */
+int
+gns_interceptor_init(struct GNUNET_CRYPTO_ShortHashCode zone,
+ struct GNUNET_CRYPTO_RsaPrivateKey *key,
+ const struct GNUNET_CONFIGURATION_Handle *c);
+
+/**
+ * Stops the interceptor
+ */
+void
+gns_interceptor_stop(void);
+
+#endif
diff --git a/src/gns/gnunet-service-gns_resolver.c b/src/gns/gnunet-service-gns_resolver.c
new file mode 100644
index 0000000..cf12e4b
--- /dev/null
+++ b/src/gns/gnunet-service-gns_resolver.c
@@ -0,0 +1,2751 @@
+/*
+ This file is part of GNUnet.
+ (C) 2009, 2010, 2011 Christian Grothoff (and other contributing authors)
+
+ GNUnet is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 3, or (at your
+ option) any later version.
+
+ GNUnet is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GNUnet; see the file COPYING. If not, write to the
+ Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+
+/**
+ *
+ *
+ * @file gns/gnunet-service-gns_resolver.c
+ * @brief GNUnet GNS resolver logic
+ * @author Martin Schanzenbach
+ */
+#include "platform.h"
+#include "gnunet_util_lib.h"
+#include "gnunet_transport_service.h"
+#include "gnunet_dns_service.h"
+#include "gnunet_dht_service.h"
+#include "gnunet_namestore_service.h"
+#include "gnunet_dns_service.h"
+#include "gnunet_dnsparser_lib.h"
+#include "gnunet_gns_service.h"
+#include "block_gns.h"
+#include "gns.h"
+#include "gnunet-service-gns_resolver.h"
+
+#define DHT_LOOKUP_TIMEOUT DHT_OPERATION_TIMEOUT
+#define DHT_GNS_REPLICATION_LEVEL 5
+#define MAX_DNS_LABEL_LENGTH 63
+
+
+/**
+ * Our handle to the namestore service
+ */
+static struct GNUNET_NAMESTORE_Handle *namestore_handle;
+
+/**
+ * Resolver handle to the dht
+ */
+static struct GNUNET_DHT_Handle *dht_handle;
+
+/**
+ * Heap for parallel DHT lookups
+ */
+static struct GNUNET_CONTAINER_Heap *dht_lookup_heap;
+
+/**
+ * Maximum amount of parallel queries in background
+ */
+static unsigned long long max_allowed_background_queries;
+
+/**
+ * Wheather or not to ignore pending records
+ */
+static int ignore_pending_records;
+
+/**
+ * Our local zone
+ */
+static struct GNUNET_CRYPTO_ShortHashCode local_zone;
+
+/**
+ * a resolution identifier pool variable
+ * FIXME overflow?
+ * This is a non critical identifier useful for debugging
+ */
+static unsigned long long rid = 0;
+
+/**
+ * Namestore calls this function if we have record for this name.
+ * (or with rd_count=0 to indicate no matches)
+ *
+ * @param cls the pending query
+ * @param key the key of the zone we did the lookup
+ * @param expiration expiration date of the namestore entry
+ * @param name the name for which we need an authority
+ * @param rd_count the number of records with 'name'
+ * @param rd the record data
+ * @param signature the signature of the authority for the record data
+ */
+static void
+process_pseu_lookup_ns(void* cls,
+ const struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *key,
+ struct GNUNET_TIME_Absolute expiration,
+ const char *name, unsigned int rd_count,
+ const struct GNUNET_NAMESTORE_RecordData *rd,
+ const struct GNUNET_CRYPTO_RsaSignature *signature)
+{
+ struct GetPseuAuthorityHandle* gph = (struct GetPseuAuthorityHandle*)cls;
+ struct GNUNET_NAMESTORE_RecordData new_pkey;
+
+ if (rd_count > 0)
+ {
+ GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
+ "GNS_AUTO_PSEU: Name %s already taken in NS!\n", name);
+ if (0 == strcmp(gph->name, name))
+ {
+ GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
+ "GNS_AUTO_PSEU: Intelligent replacement not implemented\n",
+ name);
+ GNUNET_free(gph);
+ return;
+ }
+
+ GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
+ "GNS_AUTO_PSEU: Trying delegated name %s\n", gph->name);
+ memcpy(gph->new_name, gph->name, strlen(gph->name)+1);
+ GNUNET_NAMESTORE_lookup_record(namestore_handle,
+ &gph->zone,
+ gph->new_name,
+ GNUNET_NAMESTORE_TYPE_ANY,
+ &process_pseu_lookup_ns,
+ gph);
+ return;
+ }
+
+ /** name is free */
+ GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
+ "GNS_AUTO_PSEU: Name %s not taken in NS! Adding\n", gph->new_name);
+
+ new_pkey.expiration = GNUNET_TIME_UNIT_FOREVER_ABS;
+ new_pkey.data_size = sizeof(struct GNUNET_CRYPTO_ShortHashCode);
+ new_pkey.data = &gph->new_zone;
+ new_pkey.record_type = GNUNET_GNS_RECORD_PKEY;
+ new_pkey.flags = GNUNET_NAMESTORE_RF_AUTHORITY
+ | GNUNET_NAMESTORE_RF_PRIVATE
+ | GNUNET_NAMESTORE_RF_PENDING;
+ GNUNET_NAMESTORE_record_create (namestore_handle,
+ gph->key,
+ gph->new_name,
+ &new_pkey,
+ NULL, //cont
+ NULL); //cls
+ GNUNET_free(gph);
+
+}
+
+/**
+ * process result of a dht pseu lookup
+ *
+ * @param gph the handle
+ * @param name the pseu result or NULL
+ */
+static void
+process_pseu_result(struct GetPseuAuthorityHandle* gph, char* name)
+{
+ if (NULL == name)
+ {
+ memcpy(gph->new_name, gph->name, strlen(gph->name)+1);
+ }
+ else
+ {
+ memcpy(gph->new_name, name, strlen(name)+1);
+ }
+
+ GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
+ "GNS_AUTO_PSEU: Checking %s for collision in NS\n", gph->new_name);
+
+ /**
+ * Check for collision
+ */
+ GNUNET_NAMESTORE_lookup_record(namestore_handle,
+ &gph->zone,
+ gph->new_name,
+ GNUNET_NAMESTORE_TYPE_ANY,
+ &process_pseu_lookup_ns,
+ gph);
+}
+
+/**
+ * Handle timeout for dht request
+ *
+ * @param cls the request handle as closure
+ * @param tc the task context
+ */
+static void
+handle_auth_discovery_timeout(void *cls,
+ const struct GNUNET_SCHEDULER_TaskContext *tc)
+{
+ struct GetPseuAuthorityHandle* gph = (struct GetPseuAuthorityHandle*)cls;
+
+ GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
+ "GNS_GET_AUTH: dht lookup for query PSEU timed out.\n");
+ GNUNET_DHT_get_stop (gph->get_handle);
+ gph->get_handle = NULL;
+ process_pseu_result(gph, NULL);
+}
+
+/**
+ * Function called when we find a PSEU entry in the DHT
+ *
+ * @param cls the request handle
+ * @param exp lifetime
+ * @param key the key the record was stored under
+ * @param get_path get path
+ * @param get_path_length get path length
+ * @param put_path put path
+ * @param put_path_length put path length
+ * @param type the block type
+ * @param size the size of the record
+ * @param data the record data
+ */
+static void
+process_auth_discovery_dht_result(void* cls,
+ struct GNUNET_TIME_Absolute exp,
+ const GNUNET_HashCode * key,
+ const struct GNUNET_PeerIdentity *get_path,
+ unsigned int get_path_length,
+ const struct GNUNET_PeerIdentity *put_path,
+ unsigned int put_path_length,
+ enum GNUNET_BLOCK_Type type,
+ size_t size, const void *data)
+{
+ struct GetPseuAuthorityHandle* gph = (struct GetPseuAuthorityHandle*)cls;
+ struct GNSNameRecordBlock *nrb;
+ char* rd_data = (char*)data;
+ char* name;
+ int num_records;
+ size_t rd_size;
+ int i;
+
+ GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
+ "GNS_GET_AUTH: got dht result (size=%d)\n", size);
+
+ if (data == NULL)
+ {
+ GNUNET_log(GNUNET_ERROR_TYPE_ERROR,
+ "GNS_GET_AUTH: got dht result null!\n", size);
+ GNUNET_break(0);
+ GNUNET_free(gph);
+ return;
+ }
+
+ nrb = (struct GNSNameRecordBlock*)data;
+
+ /* stop lookup and timeout task */
+ GNUNET_DHT_get_stop (gph->get_handle);
+ gph->get_handle = NULL;
+ GNUNET_SCHEDULER_cancel(gph->timeout);
+
+ gph->get_handle = NULL;
+
+ nrb = (struct GNSNameRecordBlock*)data;
+
+ name = (char*)&nrb[1];
+ num_records = ntohl(nrb->rd_count);
+ {
+ struct GNUNET_NAMESTORE_RecordData rd[num_records];
+
+ rd_data += strlen(name) + 1 + sizeof(struct GNSNameRecordBlock);
+ rd_size = size - strlen(name) - 1 - sizeof(struct GNSNameRecordBlock);
+
+ if (GNUNET_SYSERR == GNUNET_NAMESTORE_records_deserialize (rd_size,
+ rd_data,
+ num_records,
+ rd))
+ {
+ GNUNET_log(GNUNET_ERROR_TYPE_ERROR,
+ "GNS_GET_AUTH: Error deserializing data!\n");
+ GNUNET_break(0);
+ GNUNET_free(gph);
+ return;
+ }
+
+ for (i=0; i<num_records; i++)
+ {
+ if ((strcmp(name, "+") == 0) &&
+ (rd[i].record_type == GNUNET_GNS_RECORD_PSEU))
+ {
+ /* found pseu */
+ process_pseu_result(gph, (char*)rd[i].data);
+ return;
+ }
+ }
+ }
+
+ GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "GNS_GET_AUTH: no pseu in dht!\n");
+ process_pseu_result(gph, NULL);
+}
+
+static void
+process_auth_discovery_ns_result(void* cls,
+ const struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *key,
+ struct GNUNET_TIME_Absolute expiration,
+ const char *name, unsigned int rd_count,
+ const struct GNUNET_NAMESTORE_RecordData *rd,
+ const struct GNUNET_CRYPTO_RsaSignature *signature)
+{
+ uint32_t xquery;
+ struct GNUNET_CRYPTO_ShortHashCode name_hash;
+ GNUNET_HashCode lookup_key;
+ struct GNUNET_CRYPTO_HashAsciiEncoded lookup_key_string;
+ GNUNET_HashCode name_hash_double;
+ GNUNET_HashCode zone_hash_double;
+ int i;
+ struct GetPseuAuthorityHandle* gph = (struct GetPseuAuthorityHandle*)cls;
+
+ /* no pseu found */
+ if (rd_count == 0)
+ {
+ /**
+ * check dht
+ */
+ GNUNET_CRYPTO_short_hash("+", strlen("+"), &name_hash);
+ GNUNET_CRYPTO_short_hash_double (&name_hash, &name_hash_double);
+ GNUNET_CRYPTO_short_hash_double (&gph->new_zone, &zone_hash_double);
+ GNUNET_CRYPTO_hash_xor(&name_hash_double, &zone_hash_double, &lookup_key);
+ GNUNET_CRYPTO_hash_to_enc (&lookup_key, &lookup_key_string);
+
+ GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
+ "GNS_AUTO_PSEU: starting dht lookup for %s with key: %s\n",
+ "+", (char*)&lookup_key_string);
+
+ gph->timeout = GNUNET_SCHEDULER_add_delayed(DHT_LOOKUP_TIMEOUT,
+ &handle_auth_discovery_timeout, gph);
+
+ xquery = htonl(GNUNET_GNS_RECORD_PSEU);
+
+ GNUNET_assert(gph->get_handle == NULL);
+ gph->get_handle = GNUNET_DHT_get_start(dht_handle,
+ GNUNET_BLOCK_TYPE_GNS_NAMERECORD,
+ &lookup_key,
+ DHT_GNS_REPLICATION_LEVEL,
+ GNUNET_DHT_RO_NONE,
+ &xquery,
+ sizeof(xquery),
+ &process_auth_discovery_dht_result,
+ gph);
+ return;
+ }
+ for (i=0; i<rd_count; i++)
+ {
+ if ((strcmp(name, "+") == 0) &&
+ (rd[i].record_type == GNUNET_GNS_RECORD_PSEU))
+ {
+ /* found pseu */
+ process_pseu_result(gph, (char*)rd[i].data);
+ return;
+ }
+ }
+}
+
+/**
+ * Callback called by namestore for a zone to name
+ * result
+ *
+ * @param cls the closure
+ * @param zone_key the zone we queried
+ * @param expire the expiration time of the name
+ * @param name the name found or NULL
+ * @param rd_len number of records for the name
+ * @param rd the record data (PKEY) for the name
+ * @param signature the signature for the record data
+ */
+static void
+process_zone_to_name_discover(void *cls,
+ const struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *zone_key,
+ struct GNUNET_TIME_Absolute expire,
+ const char *name,
+ unsigned int rd_len,
+ const struct GNUNET_NAMESTORE_RecordData *rd,
+ const struct GNUNET_CRYPTO_RsaSignature *signature)
+{
+ struct GetPseuAuthorityHandle* gph = (struct GetPseuAuthorityHandle*)cls;
+
+ /* we found a match in our own zone */
+ if (rd_len != 0)
+ {
+ GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
+ "GNS_AUTO_PSEU: name for zone in our root %s\n", name);
+ GNUNET_free(gph);
+ }
+ else
+ {
+
+ GNUNET_NAMESTORE_lookup_record(namestore_handle,
+ &gph->new_zone,
+ "+",
+ GNUNET_GNS_RECORD_PSEU,
+ &process_auth_discovery_ns_result,
+ gph);
+ }
+
+
+}
+
+
+/**
+ * Callback for new authories
+ *
+ * @param name the name given by delegation
+ * @param zone the authority
+ * @param our_zone our local zone
+ * @param key the private key of our authority
+ */
+static void process_discovered_authority(char* name,
+ struct GNUNET_CRYPTO_ShortHashCode zone,
+ struct GNUNET_CRYPTO_ShortHashCode our_zone,
+ struct GNUNET_CRYPTO_RsaPrivateKey *key)
+{
+ struct GetPseuAuthorityHandle *gph;
+ size_t namelen;
+
+ GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
+ "GNS_AUTO_PSEU: New authority %s discovered\n",
+ name);
+
+ gph = GNUNET_malloc(sizeof(struct GetPseuAuthorityHandle));
+ namelen = strlen(name) + 1;
+ memcpy(gph->name, name, namelen);
+
+ gph->new_zone = zone;
+ gph->zone = our_zone;
+ gph->key = key;
+
+ GNUNET_NAMESTORE_zone_to_name (namestore_handle,
+ &our_zone,
+ &gph->new_zone,
+ &process_zone_to_name_discover,
+ gph);
+
+}
+
+/**
+ * Initialize the resolver
+ *
+ * @param nh the namestore handle
+ * @param dh the dht handle
+ * @param lz the local zone's hash
+ * @param max_bg_queries maximum number of parallel background queries in dht
+ * @param ignore_pending ignore records that still require user confirmation
+ * on lookup
+ * @return GNUNET_OK on success
+ */
+int
+gns_resolver_init(struct GNUNET_NAMESTORE_Handle *nh,
+ struct GNUNET_DHT_Handle *dh,
+ struct GNUNET_CRYPTO_ShortHashCode lz,
+ unsigned long long max_bg_queries,
+ int ignore_pending)
+{
+ namestore_handle = nh;
+ dht_handle = dh;
+ local_zone = lz;
+ dht_lookup_heap =
+ GNUNET_CONTAINER_heap_create(GNUNET_CONTAINER_HEAP_ORDER_MIN);
+ max_allowed_background_queries = max_bg_queries;
+ ignore_pending_records = ignore_pending;
+
+ if ((namestore_handle != NULL) && (dht_handle != NULL))
+ {
+ return GNUNET_OK;
+ }
+ return GNUNET_SYSERR;
+}
+
+/**
+ * Cleanup background lookups
+ *
+ * @param cls closure to iterator
+ * @param node heap nodes
+ * @param element the resolver handle
+ * @param cost heap cost
+ * @return always GNUNET_YES
+ */
+static int
+cleanup_pending_background_queries(void* cls,
+ struct GNUNET_CONTAINER_HeapNode *node,
+ void *element,
+ GNUNET_CONTAINER_HeapCostType cost)
+{
+ struct ResolverHandle *rh = (struct ResolverHandle *)element;
+ ResolverCleanupContinuation cont = cls;
+
+ GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
+ "GNS_CLEANUP-%llu: Terminating background lookup for %s\n",
+ rh->id, rh->name);
+ GNUNET_DHT_get_stop(rh->get_handle);
+ rh->get_handle = NULL;
+ rh->proc(rh->proc_cls, rh, 0, NULL);
+
+ GNUNET_CONTAINER_heap_remove_node(node);
+
+ if (GNUNET_CONTAINER_heap_get_size(dht_lookup_heap) == 0)
+ cont();
+
+
+ return GNUNET_YES;
+}
+
+
+/**
+ * Shutdown resolver
+ */
+void
+gns_resolver_cleanup(ResolverCleanupContinuation cont)
+{
+ unsigned int s = GNUNET_CONTAINER_heap_get_size(dht_lookup_heap);
+ GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
+ "GNS_CLEANUP: %d pending background queries to terminate\n", s);
+
+ if (0 != s)
+ GNUNET_CONTAINER_heap_iterate (dht_lookup_heap,
+ &cleanup_pending_background_queries,
+ cont);
+ else
+ cont();
+}
+
+
+/**
+ * Helper function to free resolver handle
+ *
+ * @param rh the handle to free
+ */
+static void
+free_resolver_handle(struct ResolverHandle* rh)
+{
+ struct AuthorityChain *ac;
+ struct AuthorityChain *ac_next;
+
+ if (NULL == rh)
+ return;
+
+ ac = rh->authority_chain_head;
+
+ while (NULL != ac)
+ {
+ ac_next = ac->next;
+ GNUNET_free(ac);
+ ac = ac_next;
+ }
+ GNUNET_free(rh);
+}
+
+
+/**
+ * Callback when record data is put into namestore
+ *
+ * @param cls the closure
+ * @param success GNUNET_OK on success
+ * @param emsg the error message. NULL if SUCCESS==GNUNET_OK
+ */
+void
+on_namestore_record_put_result(void *cls,
+ int32_t success,
+ const char *emsg)
+{
+ if (GNUNET_NO == success)
+ {
+ GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
+ "GNS_NS: records already in namestore\n");
+ return;
+ }
+ else if (GNUNET_YES == success)
+ {
+ GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
+ "GNS_NS: records successfully put in namestore\n");
+ return;
+ }
+
+ GNUNET_log(GNUNET_ERROR_TYPE_ERROR,
+ "GNS_NS: Error putting records into namestore: %s\n", emsg);
+}
+
+static void
+handle_lookup_timeout(void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
+{
+ struct ResolverHandle *rh = cls;
+
+ if (rh->timeout_cont)
+ rh->timeout_cont(rh->timeout_cont_cls, tc);
+}
+
+/**
+ * Processor for background lookups in the DHT
+ *
+ * @param cls closure (NULL)
+ * @param rd_count number of records found (not 0)
+ * @param rd record data
+ */
+static void
+background_lookup_result_processor(void *cls,
+ uint32_t rd_count,
+ const struct GNUNET_NAMESTORE_RecordData *rd)
+{
+ //We could do sth verbose/more useful here but it doesn't make any difference
+ GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
+ "GNS_BG: background dht lookup for finished. (%d results)\n",
+ rd_count);
+}
+
+/**
+ * Handle timeout for DHT requests
+ *
+ * @param cls the request handle as closure
+ * @param tc the task context
+ */
+static void
+dht_lookup_timeout(void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
+{
+ struct ResolverHandle *rh = cls;
+ struct RecordLookupHandle *rlh = (struct RecordLookupHandle *)rh->proc_cls;
+ char new_name[MAX_DNS_NAME_LENGTH];
+
+ GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
+ "GNS_PHASE_REC-%d: dht lookup for query %s (%ds)timed out.\n",
+ rh->id, rh->name, rh->timeout.rel_value);
+ /**
+ * Start resolution in bg
+ */
+ //strcpy(new_name, rh->name);
+ //memcpy(new_name+strlen(new_name), GNUNET_GNS_TLD, strlen(GNUNET_GNS_TLD));
+ GNUNET_snprintf(new_name, MAX_DNS_NAME_LENGTH, "%s.%s",
+ rh->name, GNUNET_GNS_TLD);
+
+ GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
+ "GNS_PHASE_REC-%d: Starting background lookup for %s type %d\n",
+ rh->id, new_name, rlh->record_type);
+
+ gns_resolver_lookup_record(rh->authority,
+ rh->private_local_zone,
+ rlh->record_type,
+ new_name,
+ rh->priv_key,
+ GNUNET_TIME_UNIT_FOREVER_REL,
+ &background_lookup_result_processor,
+ NULL);
+ rh->timeout_task = GNUNET_SCHEDULER_NO_TASK;
+
+ GNUNET_DHT_get_stop (rh->get_handle);
+ rh->get_handle = NULL;
+ rh->proc(rh->proc_cls, rh, 0, NULL);
+}
+
+
+/**
+ * Function called when we get a result from the dht
+ * for our record query
+ *
+ * @param cls the request handle
+ * @param exp lifetime
+ * @param key the key the record was stored under
+ * @param get_path get path
+ * @param get_path_length get path length
+ * @param put_path put path
+ * @param put_path_length put path length
+ * @param type the block type
+ * @param size the size of the record
+ * @param data the record data
+ */
+static void
+process_record_result_dht(void* cls,
+ struct GNUNET_TIME_Absolute exp,
+ const GNUNET_HashCode * key,
+ const struct GNUNET_PeerIdentity *get_path,
+ unsigned int get_path_length,
+ const struct GNUNET_PeerIdentity *put_path,
+ unsigned int put_path_length,
+ enum GNUNET_BLOCK_Type type,
+ size_t size, const void *data)
+{
+ struct ResolverHandle *rh;
+ struct RecordLookupHandle *rlh;
+ struct GNSNameRecordBlock *nrb;
+ uint32_t num_records;
+ char* name = NULL;
+ char* rd_data = (char*)data;
+ int i;
+ int rd_size;
+
+ rh = (struct ResolverHandle *)cls;
+ GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
+ "GNS_PHASE_REC-%d: got dht result (size=%d)\n", rh->id, size);
+
+ if (data == NULL)
+ return;
+
+ //FIXME maybe check expiration here, check block type
+
+
+ rlh = (struct RecordLookupHandle *) rh->proc_cls;
+ nrb = (struct GNSNameRecordBlock*)data;
+
+ /* stop lookup and timeout task */
+ GNUNET_DHT_get_stop (rh->get_handle);
+ rh->get_handle = NULL;
+
+ if (rh->dht_heap_node != NULL)
+ {
+ GNUNET_CONTAINER_heap_remove_node(rh->dht_heap_node);
+ rh->dht_heap_node = NULL;
+ }
+
+ if (rh->timeout_task != GNUNET_SCHEDULER_NO_TASK)
+ {
+ GNUNET_SCHEDULER_cancel(rh->timeout_task);
+ rh->timeout_task = GNUNET_SCHEDULER_NO_TASK;
+ }
+
+ rh->get_handle = NULL;
+ name = (char*)&nrb[1];
+ num_records = ntohl(nrb->rd_count);
+ {
+ struct GNUNET_NAMESTORE_RecordData rd[num_records];
+
+ rd_data += strlen(name) + 1 + sizeof(struct GNSNameRecordBlock);
+ rd_size = size - strlen(name) - 1 - sizeof(struct GNSNameRecordBlock);
+
+ if (GNUNET_SYSERR == GNUNET_NAMESTORE_records_deserialize (rd_size,
+ rd_data,
+ num_records,
+ rd))
+ {
+ GNUNET_log(GNUNET_ERROR_TYPE_ERROR,
+ "GNS_PHASE_REC-%d: Error deserializing data!\n", rh->id);
+ return;
+ }
+
+ for (i=0; i<num_records; i++)
+ {
+ GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
+ "GNS_PHASE_REC-%d: Got name: %s (wanted %s)\n",
+ rh->id, name, rh->name);
+ GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
+ "GNS_PHASE_REC-%d: Got type: %d\n",
+ rh->id, rd[i].record_type);
+ GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
+ "GNS_PHASE_REC-%d: Got data length: %d\n",
+ rh->id, rd[i].data_size);
+ GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
+ "GNS_PHASE_REC-%d: Got flag %d\n",
+ rh->id, rd[i].flags);
+
+ if ((strcmp(name, rh->name) == 0) &&
+ (rd[i].record_type == rlh->record_type))
+ {
+ rh->answered++;
+ }
+
+ }
+
+ /**
+ * FIXME check pubkey against existing key in namestore?
+ * https://gnunet.org/bugs/view.php?id=2179
+ */
+
+ /* Save to namestore */
+ GNUNET_NAMESTORE_record_put (namestore_handle,
+ &nrb->public_key,
+ name,
+ exp,
+ num_records,
+ rd,
+ &nrb->signature,
+ &on_namestore_record_put_result, //cont
+ NULL); //cls
+
+
+ if (rh->answered)
+ rh->proc(rh->proc_cls, rh, num_records, rd);
+ else
+ rh->proc(rh->proc_cls, rh, 0, NULL);
+ }
+
+}
+
+
+/**
+ * Start DHT lookup for a (name -> query->record_type) record in
+ * rh->authority's zone
+ *
+ * @param rh the pending gns query context
+ */
+static void
+resolve_record_dht(struct ResolverHandle *rh)
+{
+ uint32_t xquery;
+ struct GNUNET_CRYPTO_ShortHashCode name_hash;
+ GNUNET_HashCode lookup_key;
+ GNUNET_HashCode name_hash_double;
+ GNUNET_HashCode zone_hash_double;
+ struct GNUNET_CRYPTO_HashAsciiEncoded lookup_key_string;
+ struct RecordLookupHandle *rlh = (struct RecordLookupHandle *)rh->proc_cls;
+ struct ResolverHandle *rh_heap_root;
+
+ GNUNET_CRYPTO_short_hash(rh->name, strlen(rh->name), &name_hash);
+ GNUNET_CRYPTO_short_hash_double(&name_hash, &name_hash_double);
+ GNUNET_CRYPTO_short_hash_double(&rh->authority, &zone_hash_double);
+ GNUNET_CRYPTO_hash_xor(&name_hash_double, &zone_hash_double, &lookup_key);
+ GNUNET_CRYPTO_hash_to_enc (&lookup_key, &lookup_key_string);
+
+ GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
+ "GNS_PHASE_REC-%d: starting dht lookup for %s with key: %s\n",
+ rh->id, rh->name, (char*)&lookup_key_string);
+
+ //rh->timeout_task = GNUNET_SCHEDULER_NO_TASK;
+ rh->dht_heap_node = NULL;
+
+ if (rh->timeout.rel_value != GNUNET_TIME_UNIT_FOREVER_REL.rel_value)
+ {
+ /**
+ * Update timeout if necessary
+ */
+ if (rh->timeout_task == GNUNET_SCHEDULER_NO_TASK)
+ {
+
+ GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
+ "GNS_PHASE_REC-%d: Adjusting timeout\n", rh->id);
+ /*
+ * Set timeout for authority lookup phase to 1/2
+ */
+ rh->timeout_task = GNUNET_SCHEDULER_add_delayed(
+ GNUNET_TIME_relative_divide(rh->timeout, 2),
+ &handle_lookup_timeout,
+ rh);
+ }
+ //rh->timeout_task = GNUNET_SCHEDULER_add_delayed (DHT_LOOKUP_TIMEOUT,
+ // &dht_lookup_timeout,
+ // rh);
+ rh->timeout_cont = &dht_lookup_timeout;
+ rh->timeout_cont_cls = rh;
+ }
+ else
+ {
+ if (max_allowed_background_queries <=
+ GNUNET_CONTAINER_heap_get_size (dht_lookup_heap))
+ {
+ rh_heap_root = GNUNET_CONTAINER_heap_remove_root (dht_lookup_heap);
+ GNUNET_DHT_get_stop(rh_heap_root->get_handle);
+ rh_heap_root->get_handle = NULL;
+ rh_heap_root->dht_heap_node = NULL;
+
+ GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
+ "GNS_PHASE_REC-%d: Replacing oldest background query for %s\n",
+ rh->id, rh_heap_root->name);
+ rh_heap_root->proc(rh_heap_root->proc_cls,
+ rh_heap_root,
+ 0,
+ NULL);
+ }
+ rh->dht_heap_node = GNUNET_CONTAINER_heap_insert (dht_lookup_heap,
+ rh,
+ GNUNET_TIME_absolute_get().abs_value);
+ }
+
+ xquery = htonl(rlh->record_type);
+
+ GNUNET_assert(rh->get_handle == NULL);
+ rh->get_handle = GNUNET_DHT_get_start(dht_handle,
+ GNUNET_BLOCK_TYPE_GNS_NAMERECORD,
+ &lookup_key,
+ DHT_GNS_REPLICATION_LEVEL,
+ GNUNET_DHT_RO_NONE,
+ &xquery,
+ sizeof(xquery),
+ &process_record_result_dht,
+ rh);
+
+}
+
+
+/**
+ * Namestore calls this function if we have record for this name.
+ * (or with rd_count=0 to indicate no matches)
+ *
+ * @param cls the pending query
+ * @param key the key of the zone we did the lookup
+ * @param expiration expiration date of the namestore entry
+ * @param name the name for which we need an authority
+ * @param rd_count the number of records with 'name'
+ * @param rd the record data
+ * @param signature the signature of the authority for the record data
+ */
+static void
+process_record_result_ns(void* cls,
+ const struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *key,
+ struct GNUNET_TIME_Absolute expiration,
+ const char *name, unsigned int rd_count,
+ const struct GNUNET_NAMESTORE_RecordData *rd,
+ const struct GNUNET_CRYPTO_RsaSignature *signature)
+{
+ struct ResolverHandle *rh;
+ struct RecordLookupHandle *rlh;
+ struct GNUNET_TIME_Relative remaining_time;
+ struct GNUNET_CRYPTO_ShortHashCode zone;
+
+ rh = (struct ResolverHandle *) cls;
+ rlh = (struct RecordLookupHandle *)rh->proc_cls;
+ GNUNET_CRYPTO_short_hash(key,
+ sizeof(struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded),
+ &zone);
+ remaining_time = GNUNET_TIME_absolute_get_remaining (expiration);
+
+
+
+ rh->status = 0;
+
+ if (name != NULL)
+ {
+ rh->status |= RSL_RECORD_EXISTS;
+ }
+
+ if (remaining_time.rel_value == 0)
+ {
+ rh->status |= RSL_RECORD_EXPIRED;
+ }
+
+ if (rd_count == 0)
+ {
+ /**
+ * Lookup terminated and no results
+ */
+ GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
+ "GNS_PHASE_REC-%d: Namestore lookup for %s terminated without results\n",
+ rh->id, name);
+
+ GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
+ "GNS_PHASE_REC-%d: Record %s unknown in namestore\n",
+ rh->id, rh->name);
+ /**
+ * Our zone and no result? Cannot resolve TT
+ */
+ rh->proc(rh->proc_cls, rh, 0, NULL);
+ return;
+
+ }
+ else
+ {
+
+ GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
+ "GNS_PHASE_REC-%d: Processing additional result %s from namestore\n",
+ rh->id, name);
+ int i;
+ for (i=0; i<rd_count;i++)
+ {
+
+ if (rd[i].record_type != rlh->record_type)
+ continue;
+
+ if (ignore_pending_records &&
+ (rd[i].flags & GNUNET_NAMESTORE_RF_PENDING))
+ {
+ GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
+ "GNS_PHASE_REC-%d: Record %s is awaiting user confirmation. Skipping\n",
+ rh->id, name);
+ continue;
+ }
+
+ if ((GNUNET_TIME_absolute_get_remaining (rd[i].expiration)).rel_value
+ == 0)
+ {
+ GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
+ "GNS_PHASE_REC-%d: This record is expired. Skipping\n",
+ rh->id);
+ continue;
+ }
+
+ rh->answered++;
+
+ }
+
+ /**
+ * no answers found
+ */
+ if (rh->answered == 0)
+ {
+ GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
+ "GNS_PHASE_REC-%d: No answers found. This is odd!\n", rh->id);
+ rh->proc(rh->proc_cls, rh, 0, NULL);
+ return;
+ }
+
+ GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
+ "GNS_PHASE_REC-%d: Found %d answer(s) to query in %d records!\n",
+ rh->id, rh->answered, rd_count);
+
+ rh->proc(rh->proc_cls, rh, rd_count, rd);
+ }
+}
+
+
+/**
+ * The final phase of resolution.
+ * rh->name is a name that is canonical and we do not have a delegation.
+ * Query namestore for this record
+ *
+ * @param rh the pending lookup
+ */
+static void
+resolve_record_ns(struct ResolverHandle *rh)
+{
+ struct RecordLookupHandle *rlh = (struct RecordLookupHandle *)rh->proc_cls;
+
+ /* We cancel here as to not include the ns lookup in the timeout */
+ if (rh->timeout_task != GNUNET_SCHEDULER_NO_TASK)
+ {
+ GNUNET_SCHEDULER_cancel(rh->timeout_task);
+ rh->timeout_task = GNUNET_SCHEDULER_NO_TASK;
+ }
+
+ /**
+ * Try to resolve this record in our namestore.
+ * The name to resolve is now in rh->authority_name
+ * since we tried to resolve it to an authority
+ * and failed.
+ **/
+ GNUNET_NAMESTORE_lookup_record(namestore_handle,
+ &rh->authority,
+ rh->name,
+ rlh->record_type,
+ &process_record_result_ns,
+ rh);
+}
+
+
+
+/**
+ * Handle timeout for DHT requests
+ *
+ * @param cls the request handle as closure
+ * @param tc the task context
+ */
+static void
+dht_authority_lookup_timeout(void *cls,
+ const struct GNUNET_SCHEDULER_TaskContext *tc)
+{
+ struct ResolverHandle *rh = cls;
+ struct RecordLookupHandle *rlh = rh->proc_cls;
+ char new_name[MAX_DNS_NAME_LENGTH];
+
+ GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
+ "GNS_PHASE_DELEGATE_DHT-%llu: dht lookup for query %s (%ds)timed out.\n",
+ rh->id, rh->authority_name, rh->timeout.rel_value);
+
+ rh->status |= RSL_TIMED_OUT;
+
+ rh->timeout_task = GNUNET_SCHEDULER_NO_TASK;
+
+ GNUNET_DHT_get_stop (rh->get_handle);
+ rh->get_handle = NULL;
+
+ if (strcmp(rh->name, "") == 0)
+ {
+ /*
+ * promote authority back to name and try to resolve record
+ */
+ strcpy(rh->name, rh->authority_name);
+ rh->proc(rh->proc_cls, rh, 0, NULL);
+ return;
+ }
+
+ /**
+ * Start resolution in bg
+ */
+ GNUNET_snprintf(new_name, MAX_DNS_NAME_LENGTH,
+ "%s.%s.%s", rh->name, rh->authority_name, GNUNET_GNS_TLD);
+ //strcpy(new_name, rh->name);
+ //strcpy(new_name+strlen(new_name), ".");
+ //memcpy(new_name+strlen(new_name), GNUNET_GNS_TLD, strlen(GNUNET_GNS_TLD));
+
+ strcpy(rh->name, new_name);
+
+ GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
+ "GNS_PHASE_DELEGATE_DHT-%llu: Starting background query for %s type %d\n",
+ rh->id, rh->name, rlh->record_type);
+
+ gns_resolver_lookup_record(rh->authority,
+ rh->private_local_zone,
+ rlh->record_type,
+ new_name,
+ rh->priv_key,
+ GNUNET_TIME_UNIT_FOREVER_REL,
+ &background_lookup_result_processor,
+ NULL);
+
+ rh->proc(rh->proc_cls, rh, 0, NULL);
+}
+
+/* Prototype */
+static void resolve_delegation_dht(struct ResolverHandle *rh);
+
+/* Prototype */
+static void resolve_delegation_ns(struct ResolverHandle *rh);
+
+
+/**
+ * Namestore resolution for delegation finished. Processing result.
+ *
+ * @param cls the closure
+ * @param rh resolver handle
+ * @param rd_count number of results (always 0)
+ * @param rd record data (always NULL)
+ */
+static void
+handle_delegation_ns(void* cls, struct ResolverHandle *rh,
+ unsigned int rd_count,
+ const struct GNUNET_NAMESTORE_RecordData *rd);
+
+
+/**
+ * Function called when we get a result from the dht
+ * for our query. Recursively tries to resolve authorities
+ * for name in DHT.
+ *
+ * @param cls the request handle
+ * @param exp lifetime
+ * @param key the key the record was stored under
+ * @param get_path get path
+ * @param get_path_length get path length
+ * @param put_path put path
+ * @param put_path_length put path length
+ * @param type the block type
+ * @param size the size of the record
+ * @param data the record data
+ */
+static void
+process_delegation_result_dht(void* cls,
+ struct GNUNET_TIME_Absolute exp,
+ const GNUNET_HashCode * key,
+ const struct GNUNET_PeerIdentity *get_path,
+ unsigned int get_path_length,
+ const struct GNUNET_PeerIdentity *put_path,
+ unsigned int put_path_length,
+ enum GNUNET_BLOCK_Type type,
+ size_t size, const void *data)
+{
+ struct ResolverHandle *rh;
+ struct GNSNameRecordBlock *nrb;
+ uint32_t num_records;
+ char* name = NULL;
+ char* rd_data = (char*) data;
+ int i;
+ int rd_size;
+ struct GNUNET_CRYPTO_ShortHashCode zone, name_hash;
+ GNUNET_HashCode zone_hash_double, name_hash_double;
+
+ rh = (struct ResolverHandle *)cls;
+
+ GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
+ "GNS_PHASE_DELEGATE_DHT-%llu: Got DHT result\n", rh->id);
+
+ if (data == NULL)
+ return;
+
+ nrb = (struct GNSNameRecordBlock*)data;
+
+ /* stop dht lookup and timeout task */
+ GNUNET_DHT_get_stop (rh->get_handle);
+
+ rh->get_handle = NULL;
+
+ if (rh->dht_heap_node != NULL)
+ {
+ GNUNET_CONTAINER_heap_remove_node(rh->dht_heap_node);
+ rh->dht_heap_node = NULL;
+ }
+
+ num_records = ntohl(nrb->rd_count);
+ name = (char*)&nrb[1];
+ {
+ struct GNUNET_NAMESTORE_RecordData rd[num_records];
+
+ rd_data += strlen(name) + 1 + sizeof(struct GNSNameRecordBlock);
+ rd_size = size - strlen(name) - 1 - sizeof(struct GNSNameRecordBlock);
+
+ if (GNUNET_SYSERR == GNUNET_NAMESTORE_records_deserialize (rd_size,
+ rd_data,
+ num_records,
+ rd))
+ {
+ GNUNET_log(GNUNET_ERROR_TYPE_ERROR,
+ "GNS_PHASE_DELEGATE_DHT-%llu: Error deserializing data!\n",
+ rh->id);
+ return;
+ }
+
+ GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
+ "GNS_PHASE_DELEGATE_DHT-%llu: Got name: %s (wanted %s)\n",
+ rh->id, name, rh->authority_name);
+ for (i=0; i<num_records; i++)
+ {
+
+ GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
+ "GNS_PHASE_DELEGATE_DHT-%llu: Got name: %s (wanted %s)\n",
+ rh->id, name, rh->authority_name);
+ GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
+ "GNS_PHASE_DELEGATE_DHT-%llu: Got type: %d (wanted %d)\n",
+ rh->id, rd[i].record_type, GNUNET_GNS_RECORD_PKEY);
+ GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
+ "GNS_PHASE_DELEGATE_DHT-%llu: Got data length: %d\n",
+ rh->id, rd[i].data_size);
+ GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
+ "GNS_PHASE_DELEGATE_DHT-%llu: Got flag %d\n",
+ rh->id, rd[i].flags);
+
+ if ((strcmp(name, rh->authority_name) == 0) &&
+ (rd[i].record_type == GNUNET_GNS_RECORD_PKEY))
+ {
+ GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
+ "GNS_PHASE_DELEGATE_DHT-%llu: Authority found in DHT\n",
+ rh->id);
+ rh->answered = 1;
+ memcpy(&rh->authority, rd[i].data, sizeof(struct GNUNET_CRYPTO_ShortHashCode));
+ struct AuthorityChain *auth =
+ GNUNET_malloc(sizeof(struct AuthorityChain));
+ auth->zone = rh->authority;
+ memset(auth->name, 0, strlen(rh->authority_name)+1);
+ strcpy(auth->name, rh->authority_name);
+ GNUNET_CONTAINER_DLL_insert (rh->authority_chain_head,
+ rh->authority_chain_tail,
+ auth);
+
+ /** try to import pkey if private key available */
+ if (rh->priv_key)
+ process_discovered_authority(name, auth->zone,
+ rh->authority_chain_tail->zone,
+ rh->priv_key);
+ }
+
+ }
+
+
+ GNUNET_CRYPTO_short_hash(name, strlen(name), &name_hash);
+ GNUNET_CRYPTO_short_hash_double(&name_hash, &name_hash_double);
+ GNUNET_CRYPTO_hash_xor(key, &name_hash_double, &zone_hash_double);
+ GNUNET_CRYPTO_short_hash_from_truncation (&zone_hash_double, &zone);
+
+ /* Save to namestore */
+ if (0 != GNUNET_CRYPTO_short_hash_cmp(&rh->authority_chain_tail->zone,
+ &zone))
+ {
+ GNUNET_NAMESTORE_record_put (namestore_handle,
+ &nrb->public_key,
+ name,
+ exp,
+ num_records,
+ rd,
+ &nrb->signature,
+ &on_namestore_record_put_result, //cont
+ NULL); //cls
+ }
+ }
+
+ if (rh->answered)
+ {
+ rh->answered = 0;
+ /**
+ * delegate
+ * FIXME in this case. should we ask namestore again?
+ */
+ GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
+ "GNS_PHASE_DELEGATE_DHT-%llu: Answer from DHT for %s. Yet to resolve: %s\n",
+ rh->id, rh->authority_name, rh->name);
+ if (strcmp(rh->name, "") == 0)
+ {
+ rh->proc(rh->proc_cls, rh, 0, NULL);
+ }
+ else
+ {
+ rh->proc = &handle_delegation_ns;
+ resolve_delegation_ns(rh);
+ }
+ return;
+ }
+
+ /**
+ * No pkey but name exists
+ * promote back
+ */
+ GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
+ "GNS_PHASE_DELEGATE_DHT-%llu: Adding %s back to %s\n",
+ rh->id, rh->authority_name, rh->name);
+ if (strcmp(rh->name, "") == 0)
+ strcpy(rh->name, rh->authority_name);
+ else
+ GNUNET_snprintf(rh->name, MAX_DNS_NAME_LENGTH, "%s.%s",
+ rh->name, rh->authority_name); //FIXME ret
+
+ GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
+ "GNS_PHASE_DELEGATE_DHT-%llu: %s restored\n", rh->id, rh->name);
+ GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
+ "GNS_PHASE_DELEGATE_DHT-%llu: DHT authority lookup found no match!\n",
+ rh->id);
+ rh->proc(rh->proc_cls, rh, 0, NULL);
+}
+
+#define MAX_SOA_LENGTH sizeof(uint32_t)+sizeof(uint32_t)+sizeof(uint32_t)+sizeof(uint32_t)\
+ +(MAX_DNS_NAME_LENGTH*2)
+#define MAX_MX_LENGTH sizeof(uint16_t)+MAX_DNS_NAME_LENGTH
+
+
+static void
+expand_plus(char** dest, char* src, char* repl)
+{
+ char* pos;
+ unsigned int s_len = strlen(src)+1;
+
+ GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
+ "GNS_POSTPROCESS: Got %s to expand with %s\n", src, repl);
+
+ if (s_len < 3)
+ {
+ GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
+ "GNS_POSTPROCESS: %s to short\n", src);
+
+ /* no postprocessing */
+ memcpy(*dest, src, s_len+1);
+ return;
+ }
+
+ if (0 == strcmp(src+s_len-3, ".+"))
+ {
+ GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
+ "GNS_POSTPROCESS: Expanding .+ in %s\n", src);
+ memset(*dest, 0, s_len+strlen(repl)+strlen(GNUNET_GNS_TLD));
+ strcpy(*dest, src);
+ pos = *dest+s_len-2;
+ strcpy(pos, repl);
+ pos += strlen(repl);
+ GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
+ "GNS_POSTPROCESS: Expanded to %s\n", *dest);
+ }
+ else
+ {
+ memcpy(*dest, src, s_len+1);
+ }
+}
+
+/**
+ * finish lookup
+ */
+static void
+finish_lookup(struct ResolverHandle *rh,
+ struct RecordLookupHandle* rlh,
+ unsigned int rd_count,
+ const struct GNUNET_NAMESTORE_RecordData *rd)
+{
+ int i;
+ char new_rr_data[MAX_DNS_NAME_LENGTH];
+ char new_mx_data[MAX_MX_LENGTH];
+ char new_soa_data[MAX_SOA_LENGTH];
+ struct GNUNET_NAMESTORE_RecordData p_rd[rd_count];
+ char* repl_string;
+ char* pos;
+ unsigned int offset;
+
+ if (rh->timeout_task != GNUNET_SCHEDULER_NO_TASK)
+ {
+ GNUNET_SCHEDULER_cancel(rh->timeout_task);
+ rh->timeout_task = GNUNET_SCHEDULER_NO_TASK;
+ }
+
+ if (rd_count > 0)
+ memcpy(p_rd, rd, rd_count*sizeof(struct GNUNET_NAMESTORE_RecordData));
+
+ for (i = 0; i < rd_count; i++)
+ {
+
+ if (rd[i].record_type != GNUNET_GNS_RECORD_TYPE_NS &&
+ rd[i].record_type != GNUNET_GNS_RECORD_TYPE_CNAME &&
+ rd[i].record_type != GNUNET_GNS_RECORD_MX &&
+ rd[i].record_type != GNUNET_GNS_RECORD_TYPE_SOA)
+ {
+ p_rd[i].data = rd[i].data;
+ continue;
+ }
+
+ /**
+ * for all those records we 'should'
+ * also try to resolve the A/AAAA records (RFC1035)
+ * This is a feature and not important
+ */
+
+ GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
+ "GNS_POSTPROCESS: Postprocessing\n");
+
+ if (strcmp(rh->name, "+") == 0)
+ repl_string = rlh->name;
+ else
+ repl_string = rlh->name+strlen(rh->name)+1;
+
+ offset = 0;
+ if (rd[i].record_type == GNUNET_GNS_RECORD_MX)
+ {
+ memcpy(new_mx_data, (char*)rd[i].data, sizeof(uint16_t));
+ offset = sizeof(uint16_t);
+ pos = new_mx_data+offset;
+ expand_plus(&pos, (char*)rd[i].data+sizeof(uint16_t),
+ repl_string);
+ offset += strlen(new_mx_data+sizeof(uint16_t))+1;
+ p_rd[i].data = new_mx_data;
+ p_rd[i].data_size = offset;
+ }
+ else if (rd[i].record_type == GNUNET_GNS_RECORD_TYPE_SOA)
+ {
+ /* expand mname and rname */
+ pos = new_soa_data;
+ expand_plus(&pos, (char*)rd[i].data, repl_string);
+ offset = strlen(new_soa_data)+1;
+ pos = new_soa_data+offset;
+ expand_plus(&pos, (char*)rd[i].data+offset, repl_string);
+ offset += strlen(new_soa_data+offset)+1;
+ /* cpy the 4 numbers serial refresh retry and expire */
+ memcpy(new_soa_data+offset, (char*)rd[i].data+offset, sizeof(uint32_t)*5);
+ offset += sizeof(uint32_t)*5;
+ p_rd[i].data_size = offset;
+ p_rd[i].data = new_soa_data;
+ }
+ else
+ {
+ pos = new_rr_data;
+ expand_plus(&pos, (char*)rd[i].data, repl_string);
+ p_rd[i].data_size = strlen(new_rr_data)+1;
+ p_rd[i].data = new_rr_data;
+ }
+
+ }
+
+ rlh->proc(rlh->proc_cls, rd_count, p_rd);
+ GNUNET_free(rlh);
+
+}
+
+/**
+ * Process DHT lookup result for record.
+ *
+ * @param cls the closure
+ * @param rh resolver handle
+ * @param rd_count number of results
+ * @param rd record data
+ */
+static void
+handle_record_dht(void* cls, struct ResolverHandle *rh,
+ unsigned int rd_count,
+ const struct GNUNET_NAMESTORE_RecordData *rd)
+{
+ struct RecordLookupHandle* rlh;
+
+ rlh = (struct RecordLookupHandle*)cls;
+ if (rd_count == 0)
+ {
+ GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
+ "GNS_PHASE_REC-%d: No records for %s found in DHT. Aborting\n",
+ rh->id, rh->name);
+ /* give up, cannot resolve */
+ finish_lookup(rh, rlh, 0, NULL);
+ free_resolver_handle(rh);
+ return;
+ }
+
+ /* results found yay */
+ GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
+ "GNS_PHASE_REC-%d: Record resolved from DHT!", rh->id);
+
+ finish_lookup(rh, rlh, rd_count, rd);
+ free_resolver_handle(rh);
+
+}
+
+
+/**
+ * Process namestore lookup result for record.
+ *
+ * @param cls the closure
+ * @param rh resolver handle
+ * @param rd_count number of results
+ * @param rd record data
+ */
+static void
+handle_record_ns(void* cls, struct ResolverHandle *rh,
+ unsigned int rd_count,
+ const struct GNUNET_NAMESTORE_RecordData *rd)
+{
+ struct RecordLookupHandle* rlh;
+ rlh = (struct RecordLookupHandle*) cls;
+ if (rd_count == 0)
+ {
+ GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
+ "GNS_PHASE_REC-%d: NS returned no records. (status: %d)!\n",
+ rh->id,
+ rh->status);
+
+ /**
+ * There are 4 conditions that have to met for us to consult the DHT:
+ * 1. The entry in the DHT is RSL_RECORD_EXPIRED AND
+ * 2. No entry in the NS existed AND
+ * 3. The zone queried is not the local resolver's zone AND
+ * 4. The name that was looked up is '+'
+ * because if it was any other canonical name we either already queried
+ * the DHT for the authority in the authority lookup phase (and thus
+ * would already have an entry in the NS for the record)
+ */
+ if (rh->status & (RSL_RECORD_EXPIRED | !RSL_RECORD_EXISTS) &&
+ GNUNET_CRYPTO_short_hash_cmp(&rh->authority_chain_head->zone,
+ &rh->private_local_zone) &&
+ (strcmp(rh->name, "+") == 0))
+ {
+ rh->proc = &handle_record_dht;
+ resolve_record_dht(rh);
+ return;
+ }
+ /* give up, cannot resolve */
+ finish_lookup(rh, rlh, 0, NULL);
+ free_resolver_handle(rh);
+ return;
+ }
+
+ /* results found yay */
+ GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
+ "GNS_PHASE_REC-%d: Record resolved from namestore!", rh->id);
+
+ finish_lookup(rh, rlh, rd_count, rd);
+
+ free_resolver_handle(rh);
+
+}
+
+
+/**
+ * Determine if this name is canonical.
+ * i.e.
+ * a.b.gnunet = not canonical
+ * a = canonical
+ *
+ * @param name the name to test
+ * @return 1 if canonical
+ */
+static int
+is_canonical(char* name)
+{
+ uint32_t len = strlen(name);
+ int i;
+
+ for (i=0; i<len; i++)
+ {
+ if (*(name+i) == '.')
+ return 0;
+ }
+ return 1;
+}
+
+/**
+ * Move one level up in the domain hierarchy and return the
+ * passed top level domain.
+ *
+ * @param name the domain
+ * @param dest the destination where the tld will be put
+ */
+void
+pop_tld(char* name, char* dest)
+{
+ uint32_t len;
+
+ if (is_canonical(name))
+ {
+ strcpy(dest, name);
+ strcpy(name, "");
+ return;
+ }
+
+ for (len = strlen(name); len > 0; len--)
+ {
+ if (*(name+len) == '.')
+ break;
+ }
+
+ //Was canonical?
+ if (len == 0)
+ return;
+
+ name[len] = '\0';
+
+ strcpy(dest, (name+len+1));
+}
+
+/**
+ * Checks if name is in tld
+ *
+ * @param name the name to check
+ * @param tld the TLD to check for
+ * @return GNUNET_YES or GNUNET_NO
+ */
+int
+is_tld(const char* name, const char* tld)
+{
+ int offset = 0;
+
+ if (strlen(name) <= strlen(tld))
+ {
+ return GNUNET_NO;
+ }
+
+ offset = strlen(name)-strlen(tld);
+ if (strcmp(name+offset, tld) != 0)
+ {
+ GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
+ "%s is not in .%s TLD\n", name, tld);
+ return GNUNET_NO;
+ }
+ return GNUNET_YES;
+}
+
+/**
+ * DHT resolution for delegation finished. Processing result.
+ *
+ * @param cls the closure
+ * @param rh resolver handle
+ * @param rd_count number of results (always 0)
+ * @param rd record data (always NULL)
+ */
+static void
+handle_delegation_dht(void* cls, struct ResolverHandle *rh,
+ unsigned int rd_count,
+ const struct GNUNET_NAMESTORE_RecordData *rd)
+{
+ struct RecordLookupHandle* rlh;
+ rlh = (struct RecordLookupHandle*) cls;
+
+
+ if (strcmp(rh->name, "") == 0)
+ {
+ if ((rlh->record_type == GNUNET_GNS_RECORD_PKEY))
+ {
+ GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
+ "GNS_PHASE_DELEGATE_DHT-%llu: Resolved queried PKEY via DHT.\n",
+ rh->id);
+ finish_lookup(rh, rlh, rd_count, rd);
+ free_resolver_handle(rh);
+ return;
+ }
+ /* We resolved full name for delegation. resolving record */
+ GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
+ "GNS_PHASE_DELEGATE_DHT-%llu: Resolved full name for delegation via DHT.\n",
+ rh->id);
+ strcpy(rh->name, "+\0");
+ rh->proc = &handle_record_ns;
+ resolve_record_ns(rh);
+ return;
+ }
+
+ /**
+ * we still have some left
+ **/
+ if (is_canonical(rh->name))
+ {
+ GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
+ "GNS_PHASE_DELEGATE_DHT-%llu: Resolving canonical record %s in ns\n",
+ rh->id,
+ rh->name);
+ rh->proc = &handle_record_ns;
+ resolve_record_ns(rh);
+ return;
+ }
+ /* give up, cannot resolve */
+ GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
+ "GNS_PHASE_DELEGATE_DHT-%llu: Cannot fully resolve delegation for %s via DHT!\n",
+ rh->id, rh->name);
+ finish_lookup(rh, rlh, 0, NULL);
+ free_resolver_handle(rh);
+}
+
+
+/**
+ * Start DHT lookup for a name -> PKEY (compare NS) record in
+ * rh->authority's zone
+ *
+ * @param rh the pending gns query
+ */
+static void
+resolve_delegation_dht(struct ResolverHandle *rh)
+{
+ uint32_t xquery;
+ struct GNUNET_CRYPTO_ShortHashCode name_hash;
+ GNUNET_HashCode name_hash_double;
+ GNUNET_HashCode zone_hash_double;
+ GNUNET_HashCode lookup_key;
+ struct ResolverHandle *rh_heap_root;
+
+ pop_tld(rh->name, rh->authority_name);
+ GNUNET_CRYPTO_short_hash(rh->authority_name,
+ strlen(rh->authority_name),
+ &name_hash);
+ GNUNET_CRYPTO_short_hash_double(&name_hash, &name_hash_double);
+ GNUNET_CRYPTO_short_hash_double(&rh->authority, &zone_hash_double);
+ GNUNET_CRYPTO_hash_xor(&name_hash_double, &zone_hash_double, &lookup_key);
+
+ rh->dht_heap_node = NULL;
+
+ if (rh->timeout.rel_value != GNUNET_TIME_UNIT_FOREVER_REL.rel_value)
+ {
+ //rh->timeout_task = GNUNET_SCHEDULER_add_delayed (DHT_LOOKUP_TIMEOUT,
+ // &dht_authority_lookup_timeout,
+ // rh);
+ rh->timeout_cont = &dht_authority_lookup_timeout;
+ rh->timeout_cont_cls = rh;
+ }
+ else
+ {
+ if (max_allowed_background_queries <=
+ GNUNET_CONTAINER_heap_get_size (dht_lookup_heap))
+ {
+ /* terminate oldest lookup */
+ rh_heap_root = GNUNET_CONTAINER_heap_remove_root (dht_lookup_heap);
+ GNUNET_DHT_get_stop(rh_heap_root->get_handle);
+ rh_heap_root->dht_heap_node = NULL;
+
+ GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
+ "GNS_PHASE_DELEGATE_DHT-%llu: Replacing oldest background query for %s\n",
+ rh->id, rh_heap_root->authority_name);
+
+ rh_heap_root->proc(rh_heap_root->proc_cls,
+ rh_heap_root,
+ 0,
+ NULL);
+ }
+ rh->dht_heap_node = GNUNET_CONTAINER_heap_insert (dht_lookup_heap,
+ rh,
+ GNUNET_TIME_absolute_get().abs_value);
+ }
+
+ xquery = htonl(GNUNET_GNS_RECORD_PKEY);
+
+ GNUNET_assert(rh->get_handle == NULL);
+ rh->get_handle = GNUNET_DHT_get_start(dht_handle,
+ GNUNET_BLOCK_TYPE_GNS_NAMERECORD,
+ &lookup_key,
+ DHT_GNS_REPLICATION_LEVEL,
+ GNUNET_DHT_RO_NONE,
+ &xquery,
+ sizeof(xquery),
+ &process_delegation_result_dht,
+ rh);
+
+}
+
+
+/**
+ * Namestore resolution for delegation finished. Processing result.
+ *
+ * @param cls the closure
+ * @param rh resolver handle
+ * @param rd_count number of results (always 0)
+ * @param rd record data (always NULL)
+ */
+static void
+handle_delegation_ns(void* cls, struct ResolverHandle *rh,
+ unsigned int rd_count,
+ const struct GNUNET_NAMESTORE_RecordData *rd)
+{
+ struct RecordLookupHandle* rlh;
+ rlh = (struct RecordLookupHandle*) cls;
+
+ GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
+ "GNS_PHASE_DELEGATE_NS-%llu: Resolution status: %d.\n",
+ rh->id, rh->status);
+
+ if (strcmp(rh->name, "") == 0)
+ {
+ if ((rlh->record_type == GNUNET_GNS_RECORD_PKEY))
+ {
+ GNUNET_assert(rd_count == 1);
+ GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
+ "GNS_PHASE_DELEGATE_NS-%llu: Resolved queried PKEY in NS.\n",
+ rh->id);
+ finish_lookup(rh, rlh, rd_count, rd);
+ free_resolver_handle(rh);
+ return;
+ }
+ /* We resolved full name for delegation. resolving record */
+ GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
+ "GNS_PHASE_DELEGATE_NS-%llu: Resolved full name for delegation.\n",
+ rh->id);
+ strcpy(rh->name, "+\0");
+ rh->proc = &handle_record_ns;
+ resolve_record_ns(rh);
+ return;
+ }
+
+ /**
+ * we still have some left
+ * check if authority in ns is fresh
+ * and exists
+ * or we are authority
+ **/
+ if (((rh->status & RSL_RECORD_EXISTS) && (!(rh->status & RSL_RECORD_EXPIRED)))
+ || !GNUNET_CRYPTO_short_hash_cmp(&rh->authority_chain_head->zone,
+ &rh->private_local_zone))
+ {
+ if (is_canonical(rh->name))
+ {
+ GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
+ "GNS_PHASE_DELEGATE_NS-%llu: Resolving canonical record %s\n",
+ rh->id,
+ rh->name);
+ rh->proc = &handle_record_ns;
+ resolve_record_ns(rh);
+ }
+ else
+ {
+ /* give up, cannot resolve */
+ GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
+ "GNS_PHASE_DELEGATE_NS-%llu: Cannot fully resolve delegation for %s!\n",
+ rh->id,
+ rh->name);
+ finish_lookup(rh, rlh, rd_count, rd);
+ //rlh->proc(rlh->proc_cls, 0, NULL);
+ }
+ return;
+ }
+
+ GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
+ "GNS_PHASE_DELEGATE_NS-%llu: Trying to resolve delegation for %s via DHT\n",
+ rh->id, rh->name);
+ rh->proc = &handle_delegation_dht;
+ resolve_delegation_dht(rh);
+}
+
+
+
+/**
+ * This is a callback function that should give us only PKEY
+ * records. Used to query the namestore for the authority (PKEY)
+ * for 'name'. It will recursively try to resolve the
+ * authority for a given name from the namestore.
+ *
+ * @param cls the pending query
+ * @param key the key of the zone we did the lookup
+ * @param expiration expiration date of the record data set in the namestore
+ * @param name the name for which we need an authority
+ * @param rd_count the number of records with 'name'
+ * @param rd the record data
+ * @param signature the signature of the authority for the record data
+ */
+static void
+process_delegation_result_ns(void* cls,
+ const struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *key,
+ struct GNUNET_TIME_Absolute expiration,
+ const char *name,
+ unsigned int rd_count,
+ const struct GNUNET_NAMESTORE_RecordData *rd,
+ const struct GNUNET_CRYPTO_RsaSignature *signature)
+{
+ struct ResolverHandle *rh;
+ struct GNUNET_TIME_Relative remaining_time;
+ struct GNUNET_CRYPTO_ShortHashCode zone;
+ char new_name[MAX_DNS_NAME_LENGTH];
+
+ rh = (struct ResolverHandle *)cls;
+ GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
+ "GNS_PHASE_DELEGATE_NS-%llu: Got %d records from authority lookup\n",
+ rh->id, rd_count);
+
+ GNUNET_CRYPTO_short_hash(key,
+ sizeof(struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded),
+ &zone);
+ remaining_time = GNUNET_TIME_absolute_get_remaining (expiration);
+
+ rh->status = 0;
+
+ if (name != NULL)
+ {
+ GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
+ "GNS_PHASE_DELEGATE_NS-%llu: Records with name %s exist.\n",
+ rh->id, name);
+ rh->status |= RSL_RECORD_EXISTS;
+ }
+
+ if (remaining_time.rel_value == 0)
+ {
+ GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
+ "GNS_PHASE_DELEGATE_NS-%llu: Record set %s expired.\n",
+ rh->id, name);
+ rh->status |= RSL_RECORD_EXPIRED;
+ }
+
+ /**
+ * No authority found in namestore.
+ */
+ if (rd_count == 0)
+ {
+ /**
+ * We did not find an authority in the namestore
+ */
+
+ /**
+ * No PKEY in zone.
+ * Promote this authority back to a name maybe it is
+ * our record.
+ */
+ if (strcmp(rh->name, "") == 0)
+ {
+ /* simply promote back */
+ GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
+ "GNS_PHASE_DELEGATE_NS-%llu: Promoting %s back to name\n",
+ rh->id, rh->authority_name);
+ strcpy(rh->name, rh->authority_name);
+ }
+ else
+ {
+ /* add back to existing name */
+ GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
+ "GNS_PHASE_DELEGATE_NS-%llu: Adding %s back to %s\n",
+ rh->id, rh->authority_name, rh->name);
+ //memset(new_name, 0, strlen(rh->name) + strlen(rh->authority_name) + 2);
+ GNUNET_snprintf(new_name, MAX_DNS_NAME_LENGTH, "%s.%s",
+ rh->name, rh->authority_name);
+ //strcpy(new_name, rh->name);
+ //strcpy(new_name+strlen(new_name), ".");
+ //strcpy(new_name+strlen(new_name), rh->authority_name);
+ strcpy(rh->name, new_name);
+ GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
+ "GNS_PHASE_DELEGATE_NS-%llu: %s restored\n", rh->id, rh->name);
+ }
+ rh->proc(rh->proc_cls, rh, 0, NULL);
+ return;
+ }
+
+ /**
+ * We found an authority that may be able to help us
+ * move on with query
+ * Note only 1 pkey should have been returned.. anything else would be strange
+ */
+ int i;
+ for (i=0; i<rd_count;i++)
+ {
+
+ if (rd[i].record_type != GNUNET_GNS_RECORD_PKEY)
+ continue;
+
+ if (ignore_pending_records &&
+ (rd[i].flags & GNUNET_NAMESTORE_RF_PENDING))
+ {
+ GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
+ "GNS_PHASE_DELEGATE_NS-%llu: PKEY for %s is pending user confirmation.\n",
+ name,
+ rh->id);
+ continue;
+ }
+
+ if ((GNUNET_TIME_absolute_get_remaining (rd[i].expiration)).rel_value
+ == 0)
+ {
+ GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
+ "GNS_PHASE_DELEGATE_NS-%llu: This pkey is expired.\n",
+ rh->id);
+ if (remaining_time.rel_value == 0)
+ {
+ GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
+ "GNS_PHASE_DELEGATE_NS-%llu: This dht entry is expired.\n",
+ rh->id);
+ rh->authority_chain_head->fresh = 0;
+ rh->proc(rh->proc_cls, rh, 0, NULL);
+ return;
+ }
+
+ continue;
+ }
+
+ /**
+ * Resolve rest of query with new authority
+ */
+ GNUNET_assert(rd[i].record_type == GNUNET_GNS_RECORD_PKEY);
+ memcpy(&rh->authority, rd[i].data,
+ sizeof(struct GNUNET_CRYPTO_ShortHashCode));
+ struct AuthorityChain *auth = GNUNET_malloc(sizeof(struct AuthorityChain));
+ auth->zone = rh->authority;
+ memset(auth->name, 0, strlen(rh->authority_name)+1);
+ strcpy(auth->name, rh->authority_name);
+ GNUNET_CONTAINER_DLL_insert (rh->authority_chain_head,
+ rh->authority_chain_tail,
+ auth);
+
+ /** try to import pkey if private key available
+ * TODO: Only import last one?
+ */
+ if (rh->priv_key && (name != NULL))
+ process_discovered_authority((char*)name, auth->zone,
+ rh->authority_chain_tail->zone,
+ rh->priv_key);
+ /**
+ * We are done with PKEY resolution if name is empty
+ * else resolve again with new authority
+ */
+ if (strcmp(rh->name, "") == 0)
+ rh->proc(rh->proc_cls, rh, rd_count, rd);
+ else
+ resolve_delegation_ns(rh);
+ return;
+ }
+
+ /**
+ * no answers found
+ */
+ GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
+ "GNS_PHASE_DELEGATE_NS-%llu: Authority lookup and no PKEY...\n", rh->id);
+ /**
+ * If we have found some records for the LAST label
+ * we return the results. Else null.
+ */
+ if (strcmp(rh->name, "") == 0)
+ {
+ /* simply promote back */
+ GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
+ "GNS_PHASE_DELEGATE_NS-%llu: Promoting %s back to name\n",
+ rh->id, rh->authority_name);
+ strcpy(rh->name, rh->authority_name);
+ rh->proc(rh->proc_cls, rh, rd_count, rd);
+ }
+ else
+ {
+ rh->proc(rh->proc_cls, rh, 0, NULL);
+ }
+}
+
+
+/**
+ * Resolve the delegation chain for the request in our namestore
+ *
+ * @param rh the resolver handle
+ */
+static void
+resolve_delegation_ns(struct ResolverHandle *rh)
+{
+ GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
+ "GNS_PHASE_DELEGATE_NS-%llu: Resolving delegation for %s\n",
+ rh->id, rh->name);
+ pop_tld(rh->name, rh->authority_name);
+ GNUNET_NAMESTORE_lookup_record(namestore_handle,
+ &rh->authority,
+ rh->authority_name,
+ GNUNET_GNS_RECORD_ANY,
+ &process_delegation_result_ns,
+ rh);
+
+}
+
+
+/**
+ * Lookup of a record in a specific zone
+ * calls lookup result processor on result
+ *
+ * @param zone the root zone
+ * @param pzone the private local zone
+ * @param record_type the record type to look up
+ * @param name the name to look up
+ * @param key a private key for use with PSEU import (can be NULL)
+ * @param timeout timeout for resolution
+ * @param proc the processor to call on result
+ * @param cls the closure to pass to proc
+ */
+void
+gns_resolver_lookup_record(struct GNUNET_CRYPTO_ShortHashCode zone,
+ struct GNUNET_CRYPTO_ShortHashCode pzone,
+ uint32_t record_type,
+ const char* name,
+ struct GNUNET_CRYPTO_RsaPrivateKey *key,
+ struct GNUNET_TIME_Relative timeout,
+ RecordLookupProcessor proc,
+ void* cls)
+{
+ struct ResolverHandle *rh;
+ struct RecordLookupHandle* rlh;
+ char string_hash[MAX_DNS_LABEL_LENGTH];
+ char nzkey[MAX_DNS_LABEL_LENGTH];
+ char* nzkey_ptr = nzkey;
+
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Starting resolution for %s (type=%d)!\n",
+ name, record_type);
+
+
+ if (is_canonical((char*)name) && (strcmp(GNUNET_GNS_TLD, name) != 0))
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "%s is canonical and not gnunet -> cannot resolve!\n", name);
+ proc(cls, 0, NULL);
+ return;
+ }
+
+ rlh = GNUNET_malloc(sizeof(struct RecordLookupHandle));
+ rh = GNUNET_malloc(sizeof (struct ResolverHandle));
+
+ rh->authority = zone;
+ rh->id = rid++;
+ rh->proc_cls = rlh;
+ rh->priv_key = key;
+ rh->timeout = timeout;
+ rh->get_handle = NULL;
+ rh->private_local_zone = pzone;
+
+ if (timeout.rel_value != GNUNET_TIME_UNIT_FOREVER_REL.rel_value)
+ {
+ /*
+ * Set timeout for authority lookup phase to 1/2
+ */
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Timeout for lookup set to %ds\n", rh->timeout.rel_value);
+ rh->timeout_task = GNUNET_SCHEDULER_add_delayed(
+ GNUNET_TIME_relative_divide(timeout, 2),
+ &handle_lookup_timeout,
+ rh);
+ rh->timeout_cont = &dht_authority_lookup_timeout;
+ rh->timeout_cont_cls = rh;
+ }
+ else
+ {
+ GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "No timeout for query!\n");
+ rh->timeout_task = GNUNET_SCHEDULER_NO_TASK;
+ }
+
+ if (strcmp(GNUNET_GNS_TLD, name) == 0)
+ {
+ /**
+ * Only 'gnunet' given
+ */
+ strcpy(rh->name, "\0");
+ }
+ else
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Checking for TLD...\n");
+ if (is_zkey_tld(name) == GNUNET_YES)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "TLD is zkey\n");
+ /**
+ * This is a zkey tld
+ * build hash and use as initial authority
+ */
+ memset(rh->name, 0,
+ strlen(name)-strlen(GNUNET_GNS_TLD_ZKEY));
+ memcpy(rh->name, name,
+ strlen(name)-strlen(GNUNET_GNS_TLD_ZKEY) - 1);
+ pop_tld(rh->name, string_hash);
+
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "ZKEY is %s!\n", string_hash);
+
+ GNUNET_STRINGS_utf8_toupper(string_hash, &nzkey_ptr);
+
+ if (GNUNET_OK != GNUNET_CRYPTO_short_hash_from_string(nzkey,
+ &rh->authority))
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "Cannot convert ZKEY %s to hash!\n", string_hash);
+ GNUNET_free(rh);
+ GNUNET_free(rlh);
+ proc(cls, 0, NULL);
+ return;
+ }
+
+ }
+ else
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "TLD is gnunet\n");
+ /**
+ * Presumably GNUNET tld
+ */
+ memset(rh->name, 0,
+ strlen(name)-strlen(GNUNET_GNS_TLD));
+ memcpy(rh->name, name,
+ strlen(name)-strlen(GNUNET_GNS_TLD) - 1);
+ }
+ }
+
+ /**
+ * Initialize authority chain
+ */
+ rh->authority_chain_head = GNUNET_malloc(sizeof(struct AuthorityChain));
+ rh->authority_chain_head->prev = NULL;
+ rh->authority_chain_head->next = NULL;
+ rh->authority_chain_tail = rh->authority_chain_head;
+ rh->authority_chain_head->zone = rh->authority;
+
+ /**
+ * Copy original query into lookup handle
+ */
+ rlh->record_type = record_type;
+ memset(rlh->name, 0, strlen(name) + 1);
+ strcpy(rlh->name, name);
+ rlh->proc = proc;
+ rlh->proc_cls = cls;
+
+ rh->proc = &handle_delegation_ns;
+ resolve_delegation_ns(rh);
+}
+
+/******** END Record Resolver ***********/
+
+
+/**
+ * Callback calles by namestore for a zone to name
+ * result
+ *
+ * @param cls the closure
+ * @param zone_key the zone we queried
+ * @param expire the expiration time of the name
+ * @param name the name found or NULL
+ * @param rd_len number of records for the name
+ * @param rd the record data (PKEY) for the name
+ * @param signature the signature for the record data
+ */
+static void
+process_zone_to_name_shorten(void *cls,
+ const struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *zone_key,
+ struct GNUNET_TIME_Absolute expire,
+ const char *name,
+ unsigned int rd_len,
+ const struct GNUNET_NAMESTORE_RecordData *rd,
+ const struct GNUNET_CRYPTO_RsaSignature *signature)
+{
+ struct ResolverHandle *rh = (struct ResolverHandle *)cls;
+ struct NameShortenHandle* nsh = (struct NameShortenHandle*)rh->proc_cls;
+ struct AuthorityChain *next_authority;
+
+ char result[MAX_DNS_NAME_LENGTH];
+ char tmp_name[MAX_DNS_NAME_LENGTH];
+ size_t answer_len;
+
+ /* we found a match in our own zone */
+ if (rd_len != 0)
+ {
+ GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
+ "result strlen %d\n", strlen(name));
+ answer_len = strlen(rh->name) + strlen(name) + strlen(GNUNET_GNS_TLD) + 3;
+ memset(result, 0, answer_len);
+ if (strlen(rh->name) > 0)
+ {
+ strcpy(result, rh->name);
+ strcpy(result+strlen(rh->name), ".");
+ }
+
+ strcpy(result+strlen(result), name);
+ strcpy(result+strlen(result), ".");
+ strcpy(result+strlen(result), GNUNET_GNS_TLD);
+
+ GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
+ "Sending shorten result %s\n", result);
+
+ nsh->proc(nsh->proc_cls, result);
+ GNUNET_free(nsh);
+ free_resolver_handle(rh);
+ }
+ else if (GNUNET_CRYPTO_short_hash_cmp(&rh->authority_chain_head->zone,
+ &rh->private_local_zone) == 0)
+ {
+ /* our zone, just append .gnunet */
+ answer_len = strlen(rh->name) + strlen(GNUNET_GNS_TLD) + 2;
+ memset(result, 0, answer_len);
+ strcpy(result, rh->name);
+ strcpy(result+strlen(rh->name), ".");
+ strcpy(result+strlen(rh->name)+1, GNUNET_GNS_TLD);
+
+ GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
+ "Our zone: Sending name as shorten result %s\n", rh->name);
+
+ nsh->proc(nsh->proc_cls, result);
+ GNUNET_free(nsh);
+ free_resolver_handle(rh);
+ }
+ else
+ {
+ /**
+ * No PSEU found.
+ * continue with next authority
+ */
+ next_authority = rh->authority_chain_head;
+
+ GNUNET_snprintf(tmp_name, MAX_DNS_NAME_LENGTH,
+ "%s.%s", rh->name, next_authority->name);
+
+ strcpy(rh->name, tmp_name);
+ GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
+ "No PSEU found for authority %s. Promoting back: %s\n",
+ next_authority->name, rh->name);
+
+ GNUNET_CONTAINER_DLL_remove(rh->authority_chain_head,
+ rh->authority_chain_tail,
+ next_authority);
+
+ GNUNET_NAMESTORE_zone_to_name (namestore_handle,
+ &rh->authority_chain_tail->zone,
+ &rh->authority_chain_head->zone,
+ &process_zone_to_name_shorten,
+ rh);
+ }
+}
+
+/**
+ * DHT resolution for delegation. Processing result.
+ *
+ * @param cls the closure
+ * @param rh resolver handle
+ * @param rd_count number of results
+ * @param rd record data
+ */
+static void
+handle_delegation_dht_bg_shorten(void* cls, struct ResolverHandle *rh,
+ unsigned int rd_count,
+ const struct GNUNET_NAMESTORE_RecordData *rd)
+{
+
+ /* We resolved full name for delegation. resolving record */
+ GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
+ "GNS_SHORTEN: Resolved up to %s for delegation via DHT in background.\n",
+ rh->name);
+ free_resolver_handle(rh);
+}
+
+/**
+ * Process result from namestore delegation lookup
+ * for shorten operation
+ *
+ * @param cls the client shorten handle
+ * @param rh the resolver handle
+ * @param rd_count number of results (0)
+ * @param rd data (NULL)
+ */
+void
+handle_delegation_ns_shorten(void* cls,
+ struct ResolverHandle *rh,
+ uint32_t rd_count,
+ const struct GNUNET_NAMESTORE_RecordData *rd)
+{
+ struct NameShortenHandle *nsh;
+ char result[MAX_DNS_NAME_LENGTH];
+ size_t answer_len;
+ struct ResolverHandle *rh_bg;
+
+ nsh = (struct NameShortenHandle *)cls;
+
+ /**
+ * At this point rh->name contains the part of the name
+ * that we do not have a PKEY in our namestore to resolve.
+ * The authority chain in the resolver handle is now
+ * useful to backtrack if needed
+ */
+
+ GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
+ "PKEY resolved as far as possible in ns up to %s!\n", rh->name);
+
+ if (GNUNET_CRYPTO_short_hash_cmp(&rh->authority_chain_head->zone,
+ &rh->private_local_zone) == 0)
+ {
+ /**
+ * This is our zone append .gnunet unless name is empty
+ * (it shouldn't be, usually FIXME what happens if we
+ * shorten to our zone to a "" record??)
+ */
+
+ answer_len = strlen(rh->name) + strlen(GNUNET_GNS_TLD) + 2;
+ memset(result, 0, answer_len);
+ strcpy(result, rh->name);
+ strcpy(result+strlen(rh->name), ".");
+ strcpy(result+strlen(rh->name)+1, GNUNET_GNS_TLD);
+
+ GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
+ "Our zone: Sending name as shorten result %s\n", rh->name);
+
+ nsh->proc(nsh->proc_cls, result);
+ GNUNET_free(nsh);
+ free_resolver_handle(rh);
+ return;
+ }
+
+ /**
+ * we have to this before zone to name for rh might
+ * be freed by then
+ */
+ rh_bg = NULL;
+ if (!is_canonical(rh->name))
+ {
+ rh_bg = GNUNET_malloc(sizeof(struct ResolverHandle));
+ memcpy(rh_bg, rh, sizeof(struct ResolverHandle));
+ rh_bg->id = rid++;
+ }
+
+ /* backtrack authorities for names */
+ GNUNET_NAMESTORE_zone_to_name (namestore_handle,
+ &rh->authority_chain_tail->zone, //ours
+ &rh->authority_chain_head->zone,
+ &process_zone_to_name_shorten,
+ rh);
+
+ if (rh_bg == NULL)
+ {
+ return;
+ }
+
+ /**
+ * If authority resolution is incomplete we can do a background lookup
+ * of the full name so that next time we can (likely) fully or at least
+ * further shorten the name
+ */
+ rh_bg->authority_chain_head = GNUNET_malloc(sizeof(struct AuthorityChain));
+ rh_bg->authority_chain_tail = rh_bg->authority_chain_head;
+ rh_bg->authority_chain_head->zone = rh_bg->authority;
+
+ rh_bg->proc = &handle_delegation_dht_bg_shorten;
+ rh_bg->proc_cls = NULL;
+
+ GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
+ "GNS_SHORTEN: Starting background lookup for %s\n",
+ rh_bg->name);
+
+ resolve_delegation_dht(rh_bg);
+
+}
+
+
+/**
+ * Callback calles by namestore for a zone to name
+ * result
+ *
+ * @param cls the closure
+ * @param zone_key the zone we queried
+ * @param expire the expiration time of the name
+ * @param name the name found or NULL
+ * @param rd_len number of records for the name
+ * @param rd the record data (PKEY) for the name
+ * @param signature the signature for the record data
+ */
+static void
+process_zone_to_name_zkey(void *cls,
+ const struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *zone_key,
+ struct GNUNET_TIME_Absolute expire,
+ const char *name,
+ unsigned int rd_len,
+ const struct GNUNET_NAMESTORE_RecordData *rd,
+ const struct GNUNET_CRYPTO_RsaSignature *signature)
+{
+ struct ResolverHandle *rh = cls;
+ struct NameShortenHandle *nsh = rh->proc_cls;
+ struct GNUNET_CRYPTO_ShortHashAsciiEncoded enc;
+ char new_name[MAX_DNS_NAME_LENGTH];
+
+ /* zkey not in our zone */
+ if (name == NULL)
+ {
+ /**
+ * In this case we have not given this PKEY a name (yet)
+ * It is either just not in our zone or not even cached
+ * Since we do not know at this point we will not try to shorten
+ * because PKEY import will happen if the user follows the zkey
+ * link.
+ */
+ GNUNET_CRYPTO_short_hash_to_enc ((struct GNUNET_CRYPTO_ShortHashCode*)rd,
+ &enc);
+ GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
+ "No name found for zkey %s returning verbatim!\n", enc);
+ if (strcmp(rh->name, "") != 0)
+ GNUNET_snprintf(new_name, MAX_DNS_NAME_LENGTH, "%s.%s.%s",
+ rh->name, enc, GNUNET_GNS_TLD_ZKEY);
+ else
+ GNUNET_snprintf(new_name, MAX_DNS_NAME_LENGTH, "%s.%s",
+ enc, GNUNET_GNS_TLD_ZKEY);
+ nsh->proc(nsh->proc_cls, new_name);
+ GNUNET_free(nsh);
+ free_resolver_handle(rh);
+ return;
+ }
+
+ if (strcmp(rh->name, "") != 0)
+ GNUNET_snprintf(new_name, MAX_DNS_NAME_LENGTH, "%s.%s",
+ rh->name, name);
+ else
+ strcpy(new_name, name);
+
+ GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
+ "Continue shorten for %s!\n", new_name);
+
+ strcpy(rh->name, new_name);
+
+ rh->authority_chain_head = GNUNET_malloc(sizeof(struct AuthorityChain));
+ rh->authority_chain_tail = rh->authority_chain_head;
+ rh->authority_chain_head->zone = rh->authority;
+
+
+ /* Start delegation resolution in our namestore */
+ resolve_delegation_ns(rh);
+}
+
+
+/**
+ * Shorten api from resolver
+ *
+ * @param zone the zone to use
+ * @param pzone the private local zone
+ * @param name the name to shorten
+ * @param key optional private key for background lookups and PSEU import
+ * @param proc the processor to call with result
+ * @param proc_cls closure to pass to proc
+ */
+void
+gns_resolver_shorten_name(struct GNUNET_CRYPTO_ShortHashCode zone,
+ struct GNUNET_CRYPTO_ShortHashCode pzone,
+ const char* name,
+ struct GNUNET_CRYPTO_RsaPrivateKey *key,
+ ShortenResultProcessor proc,
+ void* proc_cls)
+{
+ struct ResolverHandle *rh;
+ struct NameShortenHandle *nsh;
+ char string_hash[MAX_DNS_LABEL_LENGTH];
+ struct GNUNET_CRYPTO_ShortHashCode zkey;
+ char nzkey[MAX_DNS_LABEL_LENGTH];
+ char* nzkey_ptr = nzkey;
+
+
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Starting shorten for %s!\n", name);
+
+ if (is_canonical((char*)name))
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "%s is canonical. Returning verbatim\n", name);
+ proc(proc_cls, name);
+ return;
+ }
+
+ nsh = GNUNET_malloc(sizeof (struct NameShortenHandle));
+
+ nsh->proc = proc;
+ nsh->proc_cls = proc_cls;
+
+ rh = GNUNET_malloc(sizeof (struct ResolverHandle));
+ rh->authority = zone;
+ rh->id = rid++;
+ rh->priv_key = key;
+ rh->proc = &handle_delegation_ns_shorten;
+ rh->proc_cls = nsh;
+ rh->id = rid++;
+ rh->private_local_zone = pzone;
+
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Checking for TLD...\n");
+ if (is_zkey_tld(name) == GNUNET_YES)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "TLD is zkey\n");
+ /**
+ * This is a zkey tld
+ * build hash and use as initial authority
+ * FIXME sscanf
+ */
+ memset(rh->name, 0,
+ strlen(name)-strlen(GNUNET_GNS_TLD_ZKEY));
+ memcpy(rh->name, name,
+ strlen(name)-strlen(GNUNET_GNS_TLD_ZKEY) - 1);
+ pop_tld(rh->name, string_hash);
+
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "ZKEY is %s!\n", string_hash);
+
+ GNUNET_STRINGS_utf8_toupper(string_hash, &nzkey_ptr);
+
+ if (GNUNET_OK != GNUNET_CRYPTO_short_hash_from_string(nzkey,
+ &zkey))
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "Cannot convert ZKEY %s to hash!\n", nzkey);
+ GNUNET_free(rh);
+ GNUNET_free(nsh);
+ proc(proc_cls, name);
+ return;
+ }
+
+ GNUNET_NAMESTORE_zone_to_name (namestore_handle,
+ &zone, //ours
+ &zkey,
+ &process_zone_to_name_zkey,
+ rh);
+ return;
+
+ }
+ else
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "TLD is gnunet\n");
+ /**
+ * Presumably GNUNET tld
+ */
+ memset(rh->name, 0,
+ strlen(name)-strlen(GNUNET_GNS_TLD));
+ memcpy(rh->name, name,
+ strlen(name)-strlen(GNUNET_GNS_TLD) - 1);
+ }
+
+ rh->authority_chain_head = GNUNET_malloc(sizeof(struct AuthorityChain));
+ rh->authority_chain_tail = rh->authority_chain_head;
+ rh->authority_chain_head->zone = zone;
+
+
+ /* Start delegation resolution in our namestore */
+ resolve_delegation_ns(rh);
+}
+
+/*********** END NAME SHORTEN ********************/
+
+
+/**
+ * Process result from namestore delegation lookup
+ * for get authority operation
+ *
+ * @param cls the client get auth handle
+ * @param rh the resolver handle
+ * @param rd_count number of results (0)
+ * @param rd data (NULL)
+ */
+void
+handle_delegation_result_ns_get_auth(void* cls,
+ struct ResolverHandle *rh,
+ uint32_t rd_count,
+ const struct GNUNET_NAMESTORE_RecordData *rd)
+{
+ struct GetNameAuthorityHandle* nah;
+ char result[MAX_DNS_NAME_LENGTH];
+ size_t answer_len;
+
+ nah = (struct GetNameAuthorityHandle*) rh->proc_cls;
+
+ /**
+ * At this point rh->name contains the part of the name
+ * that we do not have a PKEY in our namestore to resolve.
+ * The authority chain in the resolver handle is now
+ * useful to backtrack if needed
+ */
+
+ GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
+ "PKEY resolved as far as possible in ns up to %s!\n", rh->name);
+
+ GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
+ "Building response!\n");
+ if (is_canonical(rh->name))
+ {
+ /**
+ * We successfully resolved the authority in the ns
+ * FIXME for our purposes this is fine
+ * but maybe we want to have an api that also looks
+ * into the dht (i.e. option in message)
+ **/
+ if (strlen(rh->name) > strlen(nah->name))
+ {
+ GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
+ "Record name longer than original lookup name... odd!\n");
+ //FIXME to sth here
+ }
+
+ answer_len = strlen(nah->name) - strlen(rh->name)
+ + strlen(GNUNET_GNS_TLD) + 1;
+ memset(result, 0, answer_len);
+ strcpy(result, nah->name + strlen(rh->name) + 1);
+
+ GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
+ "Got authority result %s\n", result);
+
+ nah->proc(nah->proc_cls, result);
+ GNUNET_free(nah);
+ free_resolver_handle(rh);
+ }
+ else
+ {
+ GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
+ "Unable to resolve authority for remaining %s!\n", rh->name);
+ nah->proc(nah->proc_cls, "");
+ GNUNET_free(nah);
+ free_resolver_handle(rh);
+ }
+
+
+}
+
+
+/**
+ * Tries to resolve the authority for name
+ * in our namestore
+ *
+ * @param zone the root zone to look up for
+ * @param pzone the private local zone
+ * @param name the name to lookup up
+ * @param proc the processor to call when finished
+ * @param proc_cls the closure to pass to the processor
+ */
+void
+gns_resolver_get_authority(struct GNUNET_CRYPTO_ShortHashCode zone,
+ struct GNUNET_CRYPTO_ShortHashCode pzone,
+ const char* name,
+ GetAuthorityResultProcessor proc,
+ void* proc_cls)
+{
+ struct ResolverHandle *rh;
+ struct GetNameAuthorityHandle *nah;
+
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Starting authority resolution for %s!\n", name);
+
+ nah = GNUNET_malloc(sizeof (struct GetNameAuthorityHandle));
+ rh = GNUNET_malloc(sizeof (struct ResolverHandle));
+ rh->authority = zone;
+ rh->id = rid++;
+ rh->private_local_zone = pzone;
+
+ if (strcmp(GNUNET_GNS_TLD, name) == 0)
+ {
+ strcpy(rh->name, "\0");
+ }
+ else
+ {
+ memset(rh->name, 0,
+ strlen(name)-strlen(GNUNET_GNS_TLD));
+ memcpy(rh->name, name,
+ strlen(name)-strlen(GNUNET_GNS_TLD) - 1);
+ }
+
+ memset(nah->name, 0,
+ strlen(name)+1);
+ strcpy(nah->name, name);
+
+ rh->authority_chain_head = GNUNET_malloc(sizeof(struct AuthorityChain));
+ rh->authority_chain_tail = rh->authority_chain_head;
+ rh->authority_chain_head->zone = zone;
+ rh->proc = &handle_delegation_result_ns_get_auth;
+ rh->proc_cls = (void*)nah;
+
+ nah->proc = proc;
+ nah->proc_cls = proc_cls;
+
+ /* Start delegation resolution in our namestore */
+ resolve_delegation_ns(rh);
+
+}
+
+/******** END GET AUTHORITY *************/
+
+/* end of gnunet-service-gns_resolver.c */
diff --git a/src/gns/gnunet-service-gns_resolver.h b/src/gns/gnunet-service-gns_resolver.h
new file mode 100644
index 0000000..8222397
--- /dev/null
+++ b/src/gns/gnunet-service-gns_resolver.h
@@ -0,0 +1,356 @@
+#ifndef GNS_RESOLVER_H
+#define GNS_RESOLVER_H
+
+#include "gns.h"
+#include "gnunet_dht_service.h"
+
+#define DHT_OPERATION_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 60)
+#define GNUNET_GNS_DEFAULT_LOOKUP_TIMEOUT \
+ GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 10)
+#define DHT_LOOKUP_TIMEOUT DHT_OPERATION_TIMEOUT
+#define DHT_GNS_REPLICATION_LEVEL 5
+
+#define GNUNET_GNS_MAX_PARALLEL_LOOKUPS 500
+
+/*
+ * DLL to hold the authority chain
+ * we had to pass in the resolution process
+ */
+struct AuthorityChain
+{
+ struct AuthorityChain *prev;
+
+ struct AuthorityChain *next;
+
+ /* the zone hash of the authority */
+ struct GNUNET_CRYPTO_ShortHashCode zone;
+
+ /* (local) name of the authority */
+ char name[MAX_DNS_LABEL_LENGTH];
+
+ /* was the ns entry fresh */
+ int fresh;
+};
+
+/* handle to a resolution process */
+struct ResolverHandle;
+
+/**
+ * continuation called when cleanup of resolver finishes
+ */
+typedef void (*ResolverCleanupContinuation) (void);
+
+/**
+ * processor for a record lookup result
+ *
+ * @param cls the closure
+ * @param rd_count number of results
+ * @param rd result data
+ */
+typedef void (*RecordLookupProcessor) (void *cls,
+ uint32_t rd_count,
+ const struct GNUNET_NAMESTORE_RecordData *rd);
+
+
+/**
+ * processor for a shorten result
+ *
+ * @param cls the closure
+ * @param name shortened name
+ */
+typedef void (*ShortenResultProcessor) (void *cls, const char* name);
+
+
+/**
+ * processor for an authority result
+ *
+ * @param cls the closure
+ * @param name name
+ */
+typedef void (*GetAuthorityResultProcessor) (void *cls, const char* name);
+
+/**
+ * processor for a resolution result
+ *
+ * @param cls the closure
+ * @param rh the resolution handle
+ * @param rd_count number of results
+ * @param rd result data
+ */
+typedef void (*ResolutionResultProcessor) (void *cls,
+ struct ResolverHandle *rh,
+ uint32_t rd_count,
+ const struct GNUNET_NAMESTORE_RecordData *rd);
+
+
+/**
+ * Resolution status indicator
+ * RSL_RECORD_EXISTS: the name to lookup exists
+ * RSL_RECORD_EXPIRED: the name in the record expired
+ * RSL_TIMED_OUT: resolution timed out
+ */
+enum ResolutionStatus
+{
+ RSL_RECORD_EXISTS = 1,
+ RSL_RECORD_EXPIRED = 2,
+ RSL_TIMED_OUT = 4
+};
+
+/**
+ * Handle to a currenty pending resolution
+ * a ResolverHandle is passed to, for example
+ * resolve_record_ns to resolve a record in the namestore.
+ * On result (positive or negative) the ResolutionResultProcessor
+ * is called.
+ * If a timeout is set timeout_cont will be called.
+ * If no timeout is set (ie timeout forever) then background resolutions
+ * might be triggered.
+ */
+struct ResolverHandle
+{
+ /* The name to resolve */
+ char name[MAX_DNS_NAME_LENGTH];
+
+ /* has this query been answered? how many matches */
+ int answered;
+
+ /* the authoritative zone to query */
+ struct GNUNET_CRYPTO_ShortHashCode authority;
+
+ /* the name of the authoritative zone to query */
+ char authority_name[MAX_DNS_LABEL_LENGTH];
+
+ /* a handle for dht lookups. should be NULL if no lookups are in progress */
+ struct GNUNET_DHT_GetHandle *get_handle;
+
+ /* timeout set for this lookup task */
+ struct GNUNET_TIME_Relative timeout;
+
+ /* timeout task for the lookup */
+ GNUNET_SCHEDULER_TaskIdentifier timeout_task;
+
+ /* continuation to call on timeout */
+ GNUNET_SCHEDULER_Task timeout_cont;
+
+ /* closure for timeout cont */
+ void* timeout_cont_cls;
+
+ /* called when resolution phase finishes */
+ ResolutionResultProcessor proc;
+
+ /* closure passed to proc */
+ void* proc_cls;
+
+ /* DLL to store the authority chain */
+ struct AuthorityChain *authority_chain_head;
+
+ /* DLL to store the authority chain */
+ struct AuthorityChain *authority_chain_tail;
+
+ /* status of the resolution result */
+ enum ResolutionStatus status;
+
+ /* The provate local zone of this request */
+ struct GNUNET_CRYPTO_ShortHashCode private_local_zone;
+
+ /**
+ * private key of an/our authoritative zone
+ * can be NULL but automatical PKEY import will not work
+ */
+ struct GNUNET_CRYPTO_RsaPrivateKey *priv_key;
+
+ /**
+ * the heap node associated with this lookup, null if timeout is set
+ * used for DHT background lookups.
+ */
+ struct GNUNET_CONTAINER_HeapNode *dht_heap_node;
+
+ /**
+ * Id for resolution process
+ */
+ unsigned long long id;
+
+};
+
+
+/**
+ * Handle to a record lookup
+ */
+struct RecordLookupHandle
+{
+ /* the record type to look up */
+ enum GNUNET_GNS_RecordType record_type;
+
+ /* the name to look up */
+ char name[MAX_DNS_NAME_LENGTH];
+
+ /* Method to call on record resolution result */
+ RecordLookupProcessor proc;
+
+ /* closure to pass to proc */
+ void* proc_cls;
+
+};
+
+
+/**
+ * Handle to a shorten context
+ */
+struct NameShortenHandle
+{
+ /* Method to call on shorten result */
+ ShortenResultProcessor proc;
+
+ /* closure to pass to proc */
+ void* proc_cls;
+};
+
+/**
+ * Handle to a get authority context
+ */
+struct GetNameAuthorityHandle
+{
+ /* the name to look up authority for */
+ char name[MAX_DNS_NAME_LENGTH];
+
+ /* Method to call on result */
+ GetAuthorityResultProcessor proc;
+
+ /* closure to pass to proc */
+ void* proc_cls;
+};
+
+/**
+ * Handle to a pseu lookup
+ */
+struct GetPseuAuthorityHandle
+{
+ /* the name given from delegation */
+ char name[MAX_DNS_LABEL_LENGTH];
+
+ /* name to store the pseu under */
+ char new_name[MAX_DNS_LABEL_LENGTH];
+
+ /* the zone of discovered authority */
+ struct GNUNET_CRYPTO_ShortHashCode new_zone;
+
+ /* the zone of our authority */
+ struct GNUNET_CRYPTO_ShortHashCode zone;
+
+ /* the private key of the zone to store the pseu in */
+ struct GNUNET_CRYPTO_RsaPrivateKey *key;
+
+ /* a handle for dht lookups. should be NULL if no lookups are in progress */
+ struct GNUNET_DHT_GetHandle *get_handle;
+
+ /* timeout task for lookup */
+ GNUNET_SCHEDULER_TaskIdentifier timeout;
+};
+
+/**
+ * Initialize the resolver
+ * MUST be called before other gns_resolver_* methods
+ *
+ * @param nh handle to the namestore
+ * @param dh handle to the dht
+ * @param lz the local zone
+ * @param max_bg_queries maximum amount of background queries
+ * @param ignore_pending ignore records that still require user confirmation
+ * on lookup
+ * @returns GNUNET_OK on success
+ */
+int
+gns_resolver_init(struct GNUNET_NAMESTORE_Handle *nh,
+ struct GNUNET_DHT_Handle *dh,
+ struct GNUNET_CRYPTO_ShortHashCode lz,
+ unsigned long long max_bg_queries,
+ int ignore_pending);
+
+/**
+ * Cleanup resolver: Terminate pending lookups
+ *
+ * @param cont continuation to call when finished
+ */
+void
+gns_resolver_cleanup(ResolverCleanupContinuation cont);
+
+/**
+ * Lookup of a record in a specific zone
+ * calls RecordLookupProcessor on result or timeout
+ *
+ * @param zone the root zone
+ * @param pzone the private local zone
+ * @param record_type the record type to look up
+ * @param name the name to look up
+ * @param key optional private key for authority caching
+ * @param timeout timeout for the resolution
+ * @param proc the processor to call
+ * @param cls the closure to pass to proc
+ */
+void
+gns_resolver_lookup_record(struct GNUNET_CRYPTO_ShortHashCode zone,
+ struct GNUNET_CRYPTO_ShortHashCode pzone,
+ uint32_t record_type,
+ const char* name,
+ struct GNUNET_CRYPTO_RsaPrivateKey *key,
+ struct GNUNET_TIME_Relative timeout,
+ RecordLookupProcessor proc,
+ void* cls);
+
+/**
+ * Shortens a name if possible. If the shortening fails
+ * name will be returned as shortened string. Else
+ * a shorter version of the name will be returned.
+ * There is no guarantee that the shortened name will
+ * actually be canonical/short etc.
+ *
+ * @param zone the zone to perform the operation in
+ * @param pzone the private local zone
+ * @param name name to shorten
+ * @param key optional private key for background lookups and PSEU import
+ * @param proc the processor to call on shorten result
+ * @param proc_cls the closure to pass to proc
+ */
+void
+gns_resolver_shorten_name(struct GNUNET_CRYPTO_ShortHashCode zone,
+ struct GNUNET_CRYPTO_ShortHashCode pzone,
+ const char* name,
+ struct GNUNET_CRYPTO_RsaPrivateKey *key,
+ ShortenResultProcessor proc,
+ void* proc_cls);
+
+/**
+ * Tries to resolve the authority for name
+ * in our namestore
+ *
+ * @param zone the root zone to look up for
+ * @param pzone the private local zone
+ * @param name the name to lookup up
+ * @param proc the processor to call when finished
+ * @param proc_cls the closure to pass to the processor
+ */
+void
+gns_resolver_get_authority(struct GNUNET_CRYPTO_ShortHashCode zone,
+ struct GNUNET_CRYPTO_ShortHashCode pzone,
+ const char* name,
+ GetAuthorityResultProcessor proc,
+ void* proc_cls);
+
+/**
+ * Generic function to check for TLDs
+ *
+ * @param name the name to check
+ * @param tld the tld to check
+ * @return GNUNET_YES or GNUNET_NO
+ */
+int
+is_tld(const char* name, const char* tld);
+
+/**
+ * Checks for gnunet/zkey
+ */
+#define is_gnunet_tld(name) is_tld(name, GNUNET_GNS_TLD)
+#define is_zkey_tld(name) is_tld(name, GNUNET_GNS_TLD_ZKEY)
+
+
+#endif
diff --git a/src/gns/namestore_stub_api.c b/src/gns/namestore_stub_api.c
deleted file mode 100644
index d067bca..0000000
--- a/src/gns/namestore_stub_api.c
+++ /dev/null
@@ -1,438 +0,0 @@
-/*
- This file is part of GNUnet.
- (C) 2009, 2010 Christian Grothoff (and other contributing authors)
-
- GNUnet is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published
- by the Free Software Foundation; either version 3, or (at your
- option) any later version.
-
- GNUnet is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with GNUnet; see the file COPYING. If not, write to the
- Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- Boston, MA 02111-1307, USA.
-*/
-
-/**
- * @file gns/namestore_stub_api.c
- * @brief stub library to access the NAMESTORE service
- * @author Martin Schanzenbach
- */
-
-#include "platform.h"
-#include "gnunet_util_lib.h"
-#include "gnunet_constants.h"
-#include "gnunet_arm_service.h"
-#include "gnunet_namestore_service.h"
-
-#define DEBUG_GNS_API GNUNET_EXTRA_LOGGING
-
-#define LOG(kind,...) GNUNET_log_from (kind, "gns-api",__VA_ARGS__)
-
-/**
- * A QueueEntry.
- */
-struct GNUNET_NAMESTORE_QueueEntry
-{
- char *data; /*stub data pointer*/
-};
-
-/**
- * Connection to the NAMESTORE service.
- */
-struct GNUNET_NAMESTORE_Handle
-{
-
- /**
- * Configuration to use.
- */
- const struct GNUNET_CONFIGURATION_Handle *cfg;
-
- /**
- * Socket (if available).
- */
- struct GNUNET_CLIENT_Connection *client;
-
- /**
- * Currently pending transmission request (or NULL).
- */
- struct GNUNET_CLIENT_TransmitHandle *th;
-
- /* dll to use for records */
- struct GNUNET_NAMESTORE_SimpleRecord * records_head;
- struct GNUNET_NAMESTORE_SimpleRecord * records_tail;
-
- uint32_t locked;
-
-};
-
-struct GNUNET_NAMESTORE_ZoneIterator
-{
- struct GNUNET_NAMESTORE_Handle *handle;
- GNUNET_NAMESTORE_RecordProcessor proc;
- void* proc_cls;
- const GNUNET_HashCode * zone;
- uint32_t no_flags;
- uint32_t flags;
- struct GNUNET_NAMESTORE_Handle *h;
- struct GNUNET_NAMESTORE_SimpleRecord *sr;
-};
-
-struct GNUNET_NAMESTORE_SimpleRecord
-{
- /**
- * DLL
- */
- struct GNUNET_NAMESTORE_SimpleRecord *next;
-
- /**
- * DLL
- */
- struct GNUNET_NAMESTORE_SimpleRecord *prev;
-
- const char *name;
- const GNUNET_HashCode *zone;
- const struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *zone_key;
- uint32_t rd_count;
- struct GNUNET_NAMESTORE_RecordData rd[100];
-};
-
-
-/**
- * Initialize the connection with the NAMESTORE service.
- *
- * @param cfg configuration to use
- * @return handle to the GNS service, or NULL on error
- */
-struct GNUNET_NAMESTORE_Handle *
-GNUNET_NAMESTORE_connect (const struct GNUNET_CONFIGURATION_Handle *cfg)
-{
- struct GNUNET_NAMESTORE_Handle *handle;
-
- handle = GNUNET_malloc (sizeof (struct GNUNET_NAMESTORE_Handle));
- handle->cfg = cfg;
- handle->records_head = NULL;
- handle->records_tail = NULL;
- return handle;
-}
-
-/**
- * Shutdown connection with the NAMESTORE service.
- *
- * @param handle handle of the NAMESTORE connection to stop
- */
-void
-GNUNET_NAMESTORE_disconnect (struct GNUNET_NAMESTORE_Handle *handle, int drop)
-{
- GNUNET_free(handle);
-}
-
-/**
- * Store an item in the namestore. If the item is already present,
- * the expiration time is updated to the max of the existing time and
- * the new time. The operation must fail if there is no matching
- * entry in the signature tree.
- *
- * @param h handle to the namestore
- * @param zone hash of the public key of the zone
- * @param name name that is being mapped (at most 255 characters long)
- * @param record_type type of the record (A, AAAA, PKEY, etc.)
- * @param expiration expiration time for the content
- * @param flags flags for the content
- * @param data_size number of bytes in data
- * @param data value, semantics depend on 'record_type' (see RFCs for DNS and
- * GNS specification for GNS extensions)
- * @param cont continuation to call when done
- * @param cont_cls closure for cont
- * @return handle to abort the request
- */
-struct GNUNET_NAMESTORE_QueueEntry *
-GNUNET_NAMESTORE_record_put (struct GNUNET_NAMESTORE_Handle *h,
- const struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *public_key,
- const char *name,
- struct GNUNET_TIME_Absolute expiration,
- unsigned int rd_count,
- const struct GNUNET_NAMESTORE_RecordData *rd,
- const struct GNUNET_CRYPTO_RsaSignature *signature,
- GNUNET_NAMESTORE_ContinuationWithStatus cont,
- void *cont_cls)
-{
- struct GNUNET_NAMESTORE_QueueEntry *qe;
- qe = GNUNET_malloc(sizeof (struct GNUNET_NAMESTORE_QueueEntry));
- struct GNUNET_NAMESTORE_SimpleRecord* sr;
- GNUNET_HashCode *zone;
- int i;
-
- zone = GNUNET_malloc(sizeof(GNUNET_HashCode));
- GNUNET_CRYPTO_hash(public_key,
- sizeof(struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded),
- zone);
-
- sr = h->records_head;
- for (; sr != NULL; sr = sr->next)
- {
- if (GNUNET_CRYPTO_hash_cmp(zone, sr->zone) == 0)
- {
- sr->rd_count = rd_count;
- for (i=0; i<rd_count; i++)
- {
- sr->rd[i] = rd[i];
- }
- //Expiration, Signature etc
- return qe;
- }
- }
- GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "new records for %s\n", name);
- // Not present
- sr = GNUNET_malloc(sizeof (struct GNUNET_NAMESTORE_SimpleRecord));
- sr->rd_count = rd_count;
- sr->name = GNUNET_malloc(strlen(name));
- sr->zone = zone;
- sr->zone_key = public_key; //pkey FIXME;
- sr->next = NULL;
- sr->prev = NULL;
- strcpy((char*)sr->name, name);
-
- for (i=0; i<rd_count; i++)
- sr->rd[i] = rd[i];
-
- if (h->records_head == NULL && h->records_tail == NULL)
- {
- h->records_head = sr;
- h->records_tail = sr;
- }
- else
- {
- GNUNET_CONTAINER_DLL_insert(h->records_head, h->records_tail, sr);
- }
-
- return qe;
-}
-
-int
-GNUNET_NAMESTORE_verify_signature (const struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *public_key,
- const char *name,
- unsigned int rd_count,
- const struct GNUNET_NAMESTORE_RecordData *rd,
- const struct GNUNET_CRYPTO_RsaSignature *signature)
-{
- return GNUNET_OK;
-}
-
-struct GNUNET_NAMESTORE_QueueEntry *
-GNUNET_NAMESTORE_record_create (struct GNUNET_NAMESTORE_Handle *h,
- const struct GNUNET_CRYPTO_RsaPrivateKey *key,
- const char *name,
- const struct GNUNET_NAMESTORE_RecordData *rd,
- GNUNET_NAMESTORE_ContinuationWithStatus cont,
- void *cont_cls)
-{
- struct GNUNET_NAMESTORE_QueueEntry *qe;
- qe = GNUNET_malloc(sizeof (struct GNUNET_NAMESTORE_QueueEntry));
- struct GNUNET_NAMESTORE_SimpleRecord* sr;
-
- GNUNET_HashCode *zone_hash;
-
- //memleakage.. but only stub so w/e
- struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *pkey;
- pkey = GNUNET_malloc(sizeof(struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded));
- GNUNET_CRYPTO_rsa_key_get_public (key, pkey);
-
- zone_hash = GNUNET_malloc(sizeof(GNUNET_HashCode));
-
- GNUNET_CRYPTO_hash(pkey, sizeof(struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded),
- zone_hash);
-
- sr = h->records_head;
- for (; sr != NULL; sr = sr->next)
- {
- if ((strcmp(sr->name, name) == 0) &&
- (0 == GNUNET_CRYPTO_hash_cmp(sr->zone, zone_hash)))
- {
- //Dangerous
- memcpy (&(sr->rd[sr->rd_count-1]), rd,
- sizeof(struct GNUNET_NAMESTORE_RecordData));
-
- sr->rd_count++;
- return qe;
- }
- }
-
- sr = GNUNET_malloc(sizeof (struct GNUNET_NAMESTORE_SimpleRecord));
-
- sr->rd_count = 1;
- sr->name = GNUNET_malloc(strlen(name));
- sr->zone = zone_hash;
- sr->zone_key = pkey;
- sr->next = NULL;
- sr->prev = NULL;
- strcpy((char*)sr->name, name);
-
- memcpy (&(sr->rd), rd,
- sizeof(struct GNUNET_NAMESTORE_RecordData));
- if (h->records_head == NULL && h->records_tail == NULL)
- {
- h->records_head = sr;
- h->records_tail = sr;
- }
- else
- {
- GNUNET_CONTAINER_DLL_insert(h->records_head, h->records_tail, sr);
- }
-
- return qe;
-}
-
-/**
- * Explicitly remove some content from the database. The
- * "cont"inuation will be called with status "GNUNET_OK" if content
- * was removed, "GNUNET_NO" if no matching entry was found and
- * "GNUNET_SYSERR" on all other types of errors.
- *
- * @param h handle to the namestore
- * @param zone hash of the public key of the zone
- * @param name name that is being mapped (at most 255 characters long)
- * @param record_type type of the record (A, AAAA, PKEY, etc.)
- * @param size number of bytes in data
- * @param data content stored
- * @param cont continuation to call when done
- * @param cont_cls closure for cont
- * @return handle to abort the request
- */
-struct GNUNET_NAMESTORE_QueueEntry *
-GNUNET_NAMESTORE_record_remove (struct GNUNET_NAMESTORE_Handle *h,
- const struct GNUNET_CRYPTO_RsaPrivateKey *pkey,
- const char *name,
- const struct GNUNET_NAMESTORE_RecordData *rd,
- GNUNET_NAMESTORE_ContinuationWithStatus cont,
- void *cont_cls)
-{
- struct GNUNET_NAMESTORE_QueueEntry *qe;
- qe = GNUNET_malloc(sizeof (struct GNUNET_NAMESTORE_QueueEntry));
-
- //FIXME
- return qe;
-}
-
-/**
- * Get a result for a particular key from the namestore. The processor
- * will only be called once.
- *
- * @param h handle to the namestore
- * @param zone zone to look up a record from
- * @param name name to look up
- * @param record_type desired record type
- * @param proc function to call on each matching value;
- * will be called once with a NULL value at the end
- * @param proc_cls closure for proc
- * @return a handle that can be used to
- * cancel
- */
-struct GNUNET_NAMESTORE_QueueEntry *
-GNUNET_NAMESTORE_lookup_record (struct GNUNET_NAMESTORE_Handle *h,
- const GNUNET_HashCode *zone,
- const char *name,
- uint32_t record_type,
- GNUNET_NAMESTORE_RecordProcessor proc, void *proc_cls)
-{
- struct GNUNET_NAMESTORE_QueueEntry *qe;
- qe = GNUNET_malloc(sizeof (struct GNUNET_NAMESTORE_QueueEntry));
- struct GNUNET_NAMESTORE_SimpleRecord *sr;
- struct GNUNET_CRYPTO_HashAsciiEncoded zone_string, zone_string_ex;
-
- GNUNET_CRYPTO_hash_to_enc (zone, &zone_string);
- GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Looking up %s in %s\n", name, (char*)&zone_string);
- sr = h->records_head;
- for (; sr != NULL; sr = sr->next)
- {
- GNUNET_CRYPTO_hash_to_enc (sr->zone, &zone_string_ex);
- if ((strcmp(sr->name, name) == 0) &&
- (0 == (GNUNET_CRYPTO_hash_cmp(sr->zone, zone))))
- {
- GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
- "Found match for %s in %s with %d entries\n",
- sr->name, (char*)&zone_string_ex, sr->rd_count);
- //Simply always return all records
- proc(proc_cls, sr->zone_key, GNUNET_TIME_UNIT_FOREVER_ABS, //FIXME
- name, sr->rd_count, sr->rd, NULL);
- return qe;
- }
- GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "No match\n");
- }
- proc(proc_cls, NULL, GNUNET_TIME_UNIT_ZERO_ABS, name, 0, NULL, NULL);
- //FIXME
- return qe;
-}
-
-struct GNUNET_NAMESTORE_ZoneIterator *
-GNUNET_NAMESTORE_zone_iteration_start(struct GNUNET_NAMESTORE_Handle *h,
- const GNUNET_HashCode *zone,
- enum GNUNET_NAMESTORE_RecordFlags must_have_flags,
- enum GNUNET_NAMESTORE_RecordFlags must_not_have_flags,
- GNUNET_NAMESTORE_RecordProcessor proc,
- void *proc_cls)
-{
- struct GNUNET_NAMESTORE_ZoneIterator *it;
- h->locked = 1;
- it = GNUNET_malloc(sizeof(struct GNUNET_NAMESTORE_ZoneIterator));
- it->h = h;
- it->sr = h->records_head;
- it->proc = proc;
- it->proc_cls = proc_cls;
- it->zone = zone;
- it->no_flags = must_not_have_flags;
- it->flags = must_have_flags;
- GNUNET_NAMESTORE_zone_iterator_next(it);
- return it;
-}
-
-void
-GNUNET_NAMESTORE_zone_iterator_next(struct GNUNET_NAMESTORE_ZoneIterator *it)
-{
-
- if (it->h->locked == 0)
- return;
- if (it->sr == NULL)
- {
- it->proc(it->proc_cls, NULL, GNUNET_TIME_UNIT_ZERO_ABS,
- NULL, 0, NULL, NULL);
- return;
- }
- if (GNUNET_CRYPTO_hash_cmp(it->sr->zone, it->zone) == 0)
- {
- //Simply always return all records
- //check flags
- it->proc(it->proc_cls, it->sr->zone_key, GNUNET_TIME_UNIT_FOREVER_ABS,
- it->sr->name, it->sr->rd_count, it->sr->rd, NULL);
- }
- it->sr = it->sr->next;
-}
-
-void
-GNUNET_NAMESTORE_zone_iteration_stop(struct GNUNET_NAMESTORE_ZoneIterator *it)
-{
- //it->h->locked = 0;
-}
-
-/**
- * Cancel a namestore operation. The final callback from the
- * operation must not have been done yet.
- *
- * @param qe operation to cancel
- */
-void
-GNUNET_NAMESTORE_cancel (struct GNUNET_NAMESTORE_QueueEntry *qe)
-{
- if (qe)
- GNUNET_free(qe);
-}
-
-
-
-
-/* end of namestore_stub_api.c */
diff --git a/src/gns/nss/Makefile.am b/src/gns/nss/Makefile.am
new file mode 100644
index 0000000..5e8ab5a
--- /dev/null
+++ b/src/gns/nss/Makefile.am
@@ -0,0 +1,59 @@
+# $Id$
+#
+# This file taken and modified from nss-gns.
+#
+# nss-gns is free software; you can redistribute it and/or modify it
+# under the terms of the GNU Lesser General Public License as
+# published by the Free Software Foundation; either version 2 of the
+# License, or (at your option) any later version.
+#
+# nss-gns is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with nss-gns; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+# USA.
+
+EXTRA_DIST = map-file
+
+AM_LDFLAGS=-avoid-version -module -export-dynamic
+
+if HAVE_SUDO
+nssdir = /lib/
+else
+nssdir = $(libdir)
+endif
+
+LIBTOOL = $(SUDO_BINARY) $(SHELL) $(top_builddir)/libtool
+
+if !MINGW
+nss_LTLIBRARIES = \
+ libnss_gns.la \
+ libnss_gns4.la \
+ libnss_gns6.la
+endif
+
+sources = nss_gns_query.h nss_gns_query.c
+
+# GNU Libc
+libnss_gns_la_SOURCES= $(sources) nss_gns.c
+libnss_gns_la_CFLAGS=$(AM_CFLAGS) -D_GNU_SOURCE
+libnss_gns_la_LDFLAGS=$(AM_LDFLAGS) -shrext .so.2 -Wl,-version-script=$(srcdir)/map-file
+
+libnss_gns4_la_SOURCES=$(libnss_gns_la_SOURCES)
+libnss_gns4_la_CFLAGS=$(libnss_gns_la_CFLAGS) -DNSS_IPV4_ONLY=1
+libnss_gns4_la_LDFLAGS=$(libnss_gns_la_LDFLAGS)
+
+libnss_gns6_la_SOURCES=$(libnss_gns_la_SOURCES)
+libnss_gns6_la_CFLAGS=$(libnss_gns_la_CFLAGS) -DNSS_IPV6_ONLY=1
+libnss_gns6_la_LDFLAGS=$(libnss_gns_la_LDFLAGS)
+
+install-data-hook:
+ $(SUDO_BINARY) $(SHELL) $(top_builddir)/libtool --finish $(nssdir)
+ $(SUDO_BINARY) rm -f $(nssdir)/libnss_gns.la $(nssdir)/libnss_gns4.la $(nssdir)/libnss_gns6.la
+
+uninstall-hook:
+ $(SUDO_BINARY) rm -f $(nssdir)/libnss_gns.so.2 $(nssdir)/libnss_gns4.so.2 $(nssdir)/libnss_gns6.so.2
diff --git a/src/gns/nss/Makefile.in b/src/gns/nss/Makefile.in
new file mode 100644
index 0000000..6b3b3df
--- /dev/null
+++ b/src/gns/nss/Makefile.in
@@ -0,0 +1,769 @@
+# Makefile.in generated by automake 1.11.1 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+# 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation,
+# Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+
+# $Id$
+#
+# This file taken and modified from nss-gns.
+#
+# nss-gns is free software; you can redistribute it and/or modify it
+# under the terms of the GNU Lesser General Public License as
+# published by the Free Software Foundation; either version 2 of the
+# License, or (at your option) any later version.
+#
+# nss-gns is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with nss-gns; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+# USA.
+
+VPATH = @srcdir@
+pkgdatadir = $(datadir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkglibexecdir = $(libexecdir)/@PACKAGE@
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+target_triplet = @target@
+subdir = src/gns/nss
+DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/m4/absolute-header.m4 \
+ $(top_srcdir)/m4/align.m4 $(top_srcdir)/m4/argz.m4 \
+ $(top_srcdir)/m4/gettext.m4 $(top_srcdir)/m4/iconv.m4 \
+ $(top_srcdir)/m4/lib-ld.m4 $(top_srcdir)/m4/lib-link.m4 \
+ $(top_srcdir)/m4/lib-prefix.m4 $(top_srcdir)/m4/libcurl.m4 \
+ $(top_srcdir)/m4/libgcrypt.m4 $(top_srcdir)/m4/libtool.m4 \
+ $(top_srcdir)/m4/libunistring.m4 $(top_srcdir)/m4/ltdl.m4 \
+ $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \
+ $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \
+ $(top_srcdir)/m4/nls.m4 $(top_srcdir)/m4/po.m4 \
+ $(top_srcdir)/m4/progtest.m4 $(top_srcdir)/acinclude.m4 \
+ $(top_srcdir)/configure.ac
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+ $(ACLOCAL_M4)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/gnunet_config.h
+CONFIG_CLEAN_FILES =
+CONFIG_CLEAN_VPATH_FILES =
+am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`;
+am__vpath_adj = case $$p in \
+ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \
+ *) f=$$p;; \
+ esac;
+am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`;
+am__install_max = 40
+am__nobase_strip_setup = \
+ srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'`
+am__nobase_strip = \
+ for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||"
+am__nobase_list = $(am__nobase_strip_setup); \
+ for p in $$list; do echo "$$p $$p"; done | \
+ sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \
+ $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \
+ if (++n[$$2] == $(am__install_max)) \
+ { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \
+ END { for (dir in files) print dir, files[dir] }'
+am__base_list = \
+ sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \
+ sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g'
+am__installdirs = "$(DESTDIR)$(nssdir)"
+LTLIBRARIES = $(nss_LTLIBRARIES)
+libnss_gns_la_LIBADD =
+am__objects_1 = libnss_gns_la-nss_gns_query.lo
+am_libnss_gns_la_OBJECTS = $(am__objects_1) libnss_gns_la-nss_gns.lo
+libnss_gns_la_OBJECTS = $(am_libnss_gns_la_OBJECTS)
+AM_V_lt = $(am__v_lt_$(V))
+am__v_lt_ = $(am__v_lt_$(AM_DEFAULT_VERBOSITY))
+am__v_lt_0 = --silent
+libnss_gns_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(libnss_gns_la_CFLAGS) \
+ $(CFLAGS) $(libnss_gns_la_LDFLAGS) $(LDFLAGS) -o $@
+@MINGW_FALSE@am_libnss_gns_la_rpath = -rpath $(nssdir)
+libnss_gns4_la_LIBADD =
+am__objects_2 = libnss_gns4_la-nss_gns_query.lo
+am__objects_3 = $(am__objects_2) libnss_gns4_la-nss_gns.lo
+am_libnss_gns4_la_OBJECTS = $(am__objects_3)
+libnss_gns4_la_OBJECTS = $(am_libnss_gns4_la_OBJECTS)
+libnss_gns4_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \
+ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \
+ $(libnss_gns4_la_CFLAGS) $(CFLAGS) $(libnss_gns4_la_LDFLAGS) \
+ $(LDFLAGS) -o $@
+@MINGW_FALSE@am_libnss_gns4_la_rpath = -rpath $(nssdir)
+libnss_gns6_la_LIBADD =
+am__objects_4 = libnss_gns6_la-nss_gns_query.lo
+am__objects_5 = $(am__objects_4) libnss_gns6_la-nss_gns.lo
+am_libnss_gns6_la_OBJECTS = $(am__objects_5)
+libnss_gns6_la_OBJECTS = $(am_libnss_gns6_la_OBJECTS)
+libnss_gns6_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \
+ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \
+ $(libnss_gns6_la_CFLAGS) $(CFLAGS) $(libnss_gns6_la_LDFLAGS) \
+ $(LDFLAGS) -o $@
+@MINGW_FALSE@am_libnss_gns6_la_rpath = -rpath $(nssdir)
+DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
+depcomp = $(SHELL) $(top_srcdir)/depcomp
+am__depfiles_maybe = depfiles
+am__mv = mv -f
+COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
+ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \
+ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \
+ $(AM_CFLAGS) $(CFLAGS)
+AM_V_CC = $(am__v_CC_$(V))
+am__v_CC_ = $(am__v_CC_$(AM_DEFAULT_VERBOSITY))
+am__v_CC_0 = @echo " CC " $@;
+AM_V_at = $(am__v_at_$(V))
+am__v_at_ = $(am__v_at_$(AM_DEFAULT_VERBOSITY))
+am__v_at_0 = @
+CCLD = $(CC)
+LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+ $(AM_LDFLAGS) $(LDFLAGS) -o $@
+AM_V_CCLD = $(am__v_CCLD_$(V))
+am__v_CCLD_ = $(am__v_CCLD_$(AM_DEFAULT_VERBOSITY))
+am__v_CCLD_0 = @echo " CCLD " $@;
+AM_V_GEN = $(am__v_GEN_$(V))
+am__v_GEN_ = $(am__v_GEN_$(AM_DEFAULT_VERBOSITY))
+am__v_GEN_0 = @echo " GEN " $@;
+SOURCES = $(libnss_gns_la_SOURCES) $(libnss_gns4_la_SOURCES) \
+ $(libnss_gns6_la_SOURCES)
+DIST_SOURCES = $(libnss_gns_la_SOURCES) $(libnss_gns4_la_SOURCES) \
+ $(libnss_gns6_la_SOURCES)
+ETAGS = etags
+CTAGS = ctags
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+AMTAR = @AMTAR@
+AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
+AR = @AR@
+ARGZ_H = @ARGZ_H@
+AS = @AS@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CXX = @CXX@
+CXXCPP = @CXXCPP@
+CXXDEPMODE = @CXXDEPMODE@
+CXXFLAGS = @CXXFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFAULT_INTERFACE = @DEFAULT_INTERFACE@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DLLDIR = @DLLDIR@
+DLLTOOL = @DLLTOOL@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+EXT_LIBS = @EXT_LIBS@
+EXT_LIB_PATH = @EXT_LIB_PATH@
+FGREP = @FGREP@
+GMSGFMT = @GMSGFMT@
+GMSGFMT_015 = @GMSGFMT_015@
+GNUNETDNS_GROUP = @GNUNETDNS_GROUP@
+GN_DAEMON_CONFIG_DIR = @GN_DAEMON_CONFIG_DIR@
+GN_DAEMON_HOME_DIR = @GN_DAEMON_HOME_DIR@
+GN_INTLINCL = @GN_INTLINCL@
+GN_LIBINTL = @GN_LIBINTL@
+GN_LIB_LDFLAGS = @GN_LIB_LDFLAGS@
+GN_PLUGIN_LDFLAGS = @GN_PLUGIN_LDFLAGS@
+GN_USER_HOME_DIR = @GN_USER_HOME_DIR@
+GREP = @GREP@
+HAVE_LIBUNISTRING = @HAVE_LIBUNISTRING@
+INCLTDL = @INCLTDL@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+INTLLIBS = @INTLLIBS@
+INTL_MACOSX_LIBS = @INTL_MACOSX_LIBS@
+JAVAPORT = @JAVAPORT@
+LD = @LD@
+LDFLAGS = @LDFLAGS@
+LIBADD_DL = @LIBADD_DL@
+LIBADD_DLD_LINK = @LIBADD_DLD_LINK@
+LIBADD_DLOPEN = @LIBADD_DLOPEN@
+LIBADD_SHL_LOAD = @LIBADD_SHL_LOAD@
+LIBCURL = @LIBCURL@
+LIBCURL_CPPFLAGS = @LIBCURL_CPPFLAGS@
+LIBGCRYPT_CFLAGS = @LIBGCRYPT_CFLAGS@
+LIBGCRYPT_CONFIG = @LIBGCRYPT_CONFIG@
+LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@
+LIBICONV = @LIBICONV@
+LIBINTL = @LIBINTL@
+LIBLTDL = @LIBLTDL@
+LIBOBJS = @LIBOBJS@
+LIBPREFIX = @LIBPREFIX@
+LIBS = @LIBS@
+LIBTOOL = $(SUDO_BINARY) $(SHELL) $(top_builddir)/libtool
+LIBUNISTRING = @LIBUNISTRING@
+LIPO = @LIPO@
+LN_S = @LN_S@
+LTDLDEPS = @LTDLDEPS@
+LTDLINCL = @LTDLINCL@
+LTDLOPEN = @LTDLOPEN@
+LTLIBICONV = @LTLIBICONV@
+LTLIBINTL = @LTLIBINTL@
+LTLIBOBJS = @LTLIBOBJS@
+LTLIBUNISTRING = @LTLIBUNISTRING@
+LT_CONFIG_H = @LT_CONFIG_H@
+LT_DLLOADERS = @LT_DLLOADERS@
+LT_DLPREOPEN = @LT_DLPREOPEN@
+MAKEINFO = @MAKEINFO@
+MKDIR_P = @MKDIR_P@
+MONKEYPREFIX = @MONKEYPREFIX@
+MSGFMT = @MSGFMT@
+MSGFMT_015 = @MSGFMT_015@
+MSGMERGE = @MSGMERGE@
+MYSQL_CPPFLAGS = @MYSQL_CPPFLAGS@
+MYSQL_LDFLAGS = @MYSQL_LDFLAGS@
+NM = @NM@
+NMEDIT = @NMEDIT@
+OBJC = @OBJC@
+OBJCDEPMODE = @OBJCDEPMODE@
+OBJCFLAGS = @OBJCFLAGS@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+OTOOL = @OTOOL@
+OTOOL64 = @OTOOL64@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_URL = @PACKAGE_URL@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+POSTGRES_CPPFLAGS = @POSTGRES_CPPFLAGS@
+POSTGRES_LDFLAGS = @POSTGRES_LDFLAGS@
+POSUB = @POSUB@
+PYTHON = @PYTHON@
+PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
+PYTHON_PLATFORM = @PYTHON_PLATFORM@
+PYTHON_PREFIX = @PYTHON_PREFIX@
+PYTHON_VERSION = @PYTHON_VERSION@
+RANLIB = @RANLIB@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+SQLITE_CPPFLAGS = @SQLITE_CPPFLAGS@
+SQLITE_LDFLAGS = @SQLITE_LDFLAGS@
+STRIP = @STRIP@
+SUDO_BINARY = @SUDO_BINARY@
+UNIXONLY = @UNIXONLY@
+USE_NLS = @USE_NLS@
+VERSION = @VERSION@
+XGETTEXT = @XGETTEXT@
+XGETTEXT_015 = @XGETTEXT_015@
+XMKMF = @XMKMF@
+X_CFLAGS = @X_CFLAGS@
+X_EXTRA_LIBS = @X_EXTRA_LIBS@
+X_LIBS = @X_LIBS@
+X_PRE_LIBS = @X_PRE_LIBS@
+_libcurl_config = @_libcurl_config@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_CXX = @ac_ct_CXX@
+ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
+ac_ct_OBJC = @ac_ct_OBJC@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_target = @build_target@
+build_vendor = @build_vendor@
+builddir = @builddir@
+datadir = @datadir@
+datarootdir = @datarootdir@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localedir = @localedir@
+localstatedir = @localstatedir@
+lt_ECHO = @lt_ECHO@
+ltdl_LIBOBJS = @ltdl_LIBOBJS@
+ltdl_LTLIBOBJS = @ltdl_LTLIBOBJS@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+pkgpyexecdir = @pkgpyexecdir@
+pkgpythondir = @pkgpythondir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+pyexecdir = @pyexecdir@
+pythondir = @pythondir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+subdirs = @subdirs@
+sys_symbol_underscore = @sys_symbol_underscore@
+sysconfdir = @sysconfdir@
+target = @target@
+target_alias = @target_alias@
+target_cpu = @target_cpu@
+target_os = @target_os@
+target_vendor = @target_vendor@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+EXTRA_DIST = map-file
+AM_LDFLAGS = -avoid-version -module -export-dynamic
+@HAVE_SUDO_FALSE@nssdir = $(libdir)
+@HAVE_SUDO_TRUE@nssdir = /lib/
+@MINGW_FALSE@nss_LTLIBRARIES = \
+@MINGW_FALSE@ libnss_gns.la \
+@MINGW_FALSE@ libnss_gns4.la \
+@MINGW_FALSE@ libnss_gns6.la
+
+sources = nss_gns_query.h nss_gns_query.c
+
+# GNU Libc
+libnss_gns_la_SOURCES = $(sources) nss_gns.c
+libnss_gns_la_CFLAGS = $(AM_CFLAGS) -D_GNU_SOURCE
+libnss_gns_la_LDFLAGS = $(AM_LDFLAGS) -shrext .so.2 -Wl,-version-script=$(srcdir)/map-file
+libnss_gns4_la_SOURCES = $(libnss_gns_la_SOURCES)
+libnss_gns4_la_CFLAGS = $(libnss_gns_la_CFLAGS) -DNSS_IPV4_ONLY=1
+libnss_gns4_la_LDFLAGS = $(libnss_gns_la_LDFLAGS)
+libnss_gns6_la_SOURCES = $(libnss_gns_la_SOURCES)
+libnss_gns6_la_CFLAGS = $(libnss_gns_la_CFLAGS) -DNSS_IPV6_ONLY=1
+libnss_gns6_la_LDFLAGS = $(libnss_gns_la_LDFLAGS)
+all: all-am
+
+.SUFFIXES:
+.SUFFIXES: .c .lo .o .obj
+$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps)
+ @for dep in $?; do \
+ case '$(am__configure_deps)' in \
+ *$$dep*) \
+ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
+ && { if test -f $@; then exit 0; else break; fi; }; \
+ exit 1;; \
+ esac; \
+ done; \
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/gns/nss/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --gnu src/gns/nss/Makefile
+.PRECIOUS: Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+ @case '$?' in \
+ *config.status*) \
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+ *) \
+ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
+ esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure: $(am__configure_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4): $(am__aclocal_m4_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(am__aclocal_m4_deps):
+install-nssLTLIBRARIES: $(nss_LTLIBRARIES)
+ @$(NORMAL_INSTALL)
+ test -z "$(nssdir)" || $(MKDIR_P) "$(DESTDIR)$(nssdir)"
+ @list='$(nss_LTLIBRARIES)'; test -n "$(nssdir)" || list=; \
+ list2=; for p in $$list; do \
+ if test -f $$p; then \
+ list2="$$list2 $$p"; \
+ else :; fi; \
+ done; \
+ test -z "$$list2" || { \
+ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(nssdir)'"; \
+ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(nssdir)"; \
+ }
+
+uninstall-nssLTLIBRARIES:
+ @$(NORMAL_UNINSTALL)
+ @list='$(nss_LTLIBRARIES)'; test -n "$(nssdir)" || list=; \
+ for p in $$list; do \
+ $(am__strip_dir) \
+ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(nssdir)/$$f'"; \
+ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(nssdir)/$$f"; \
+ done
+
+clean-nssLTLIBRARIES:
+ -test -z "$(nss_LTLIBRARIES)" || rm -f $(nss_LTLIBRARIES)
+ @list='$(nss_LTLIBRARIES)'; for p in $$list; do \
+ dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \
+ test "$$dir" != "$$p" || dir=.; \
+ echo "rm -f \"$${dir}/so_locations\""; \
+ rm -f "$${dir}/so_locations"; \
+ done
+libnss_gns.la: $(libnss_gns_la_OBJECTS) $(libnss_gns_la_DEPENDENCIES)
+ $(AM_V_CCLD)$(libnss_gns_la_LINK) $(am_libnss_gns_la_rpath) $(libnss_gns_la_OBJECTS) $(libnss_gns_la_LIBADD) $(LIBS)
+libnss_gns4.la: $(libnss_gns4_la_OBJECTS) $(libnss_gns4_la_DEPENDENCIES)
+ $(AM_V_CCLD)$(libnss_gns4_la_LINK) $(am_libnss_gns4_la_rpath) $(libnss_gns4_la_OBJECTS) $(libnss_gns4_la_LIBADD) $(LIBS)
+libnss_gns6.la: $(libnss_gns6_la_OBJECTS) $(libnss_gns6_la_DEPENDENCIES)
+ $(AM_V_CCLD)$(libnss_gns6_la_LINK) $(am_libnss_gns6_la_rpath) $(libnss_gns6_la_OBJECTS) $(libnss_gns6_la_LIBADD) $(LIBS)
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libnss_gns4_la-nss_gns.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libnss_gns4_la-nss_gns_query.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libnss_gns6_la-nss_gns.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libnss_gns6_la-nss_gns_query.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libnss_gns_la-nss_gns.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libnss_gns_la-nss_gns_query.Plo@am__quote@
+
+.c.o:
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(COMPILE) -c $<
+
+.c.obj:
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'`
+
+.c.lo:
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo
+@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $<
+
+libnss_gns_la-nss_gns_query.lo: nss_gns_query.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libnss_gns_la_CFLAGS) $(CFLAGS) -MT libnss_gns_la-nss_gns_query.lo -MD -MP -MF $(DEPDIR)/libnss_gns_la-nss_gns_query.Tpo -c -o libnss_gns_la-nss_gns_query.lo `test -f 'nss_gns_query.c' || echo '$(srcdir)/'`nss_gns_query.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libnss_gns_la-nss_gns_query.Tpo $(DEPDIR)/libnss_gns_la-nss_gns_query.Plo
+@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='nss_gns_query.c' object='libnss_gns_la-nss_gns_query.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libnss_gns_la_CFLAGS) $(CFLAGS) -c -o libnss_gns_la-nss_gns_query.lo `test -f 'nss_gns_query.c' || echo '$(srcdir)/'`nss_gns_query.c
+
+libnss_gns_la-nss_gns.lo: nss_gns.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libnss_gns_la_CFLAGS) $(CFLAGS) -MT libnss_gns_la-nss_gns.lo -MD -MP -MF $(DEPDIR)/libnss_gns_la-nss_gns.Tpo -c -o libnss_gns_la-nss_gns.lo `test -f 'nss_gns.c' || echo '$(srcdir)/'`nss_gns.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libnss_gns_la-nss_gns.Tpo $(DEPDIR)/libnss_gns_la-nss_gns.Plo
+@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='nss_gns.c' object='libnss_gns_la-nss_gns.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libnss_gns_la_CFLAGS) $(CFLAGS) -c -o libnss_gns_la-nss_gns.lo `test -f 'nss_gns.c' || echo '$(srcdir)/'`nss_gns.c
+
+libnss_gns4_la-nss_gns_query.lo: nss_gns_query.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libnss_gns4_la_CFLAGS) $(CFLAGS) -MT libnss_gns4_la-nss_gns_query.lo -MD -MP -MF $(DEPDIR)/libnss_gns4_la-nss_gns_query.Tpo -c -o libnss_gns4_la-nss_gns_query.lo `test -f 'nss_gns_query.c' || echo '$(srcdir)/'`nss_gns_query.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libnss_gns4_la-nss_gns_query.Tpo $(DEPDIR)/libnss_gns4_la-nss_gns_query.Plo
+@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='nss_gns_query.c' object='libnss_gns4_la-nss_gns_query.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libnss_gns4_la_CFLAGS) $(CFLAGS) -c -o libnss_gns4_la-nss_gns_query.lo `test -f 'nss_gns_query.c' || echo '$(srcdir)/'`nss_gns_query.c
+
+libnss_gns4_la-nss_gns.lo: nss_gns.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libnss_gns4_la_CFLAGS) $(CFLAGS) -MT libnss_gns4_la-nss_gns.lo -MD -MP -MF $(DEPDIR)/libnss_gns4_la-nss_gns.Tpo -c -o libnss_gns4_la-nss_gns.lo `test -f 'nss_gns.c' || echo '$(srcdir)/'`nss_gns.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libnss_gns4_la-nss_gns.Tpo $(DEPDIR)/libnss_gns4_la-nss_gns.Plo
+@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='nss_gns.c' object='libnss_gns4_la-nss_gns.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libnss_gns4_la_CFLAGS) $(CFLAGS) -c -o libnss_gns4_la-nss_gns.lo `test -f 'nss_gns.c' || echo '$(srcdir)/'`nss_gns.c
+
+libnss_gns6_la-nss_gns_query.lo: nss_gns_query.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libnss_gns6_la_CFLAGS) $(CFLAGS) -MT libnss_gns6_la-nss_gns_query.lo -MD -MP -MF $(DEPDIR)/libnss_gns6_la-nss_gns_query.Tpo -c -o libnss_gns6_la-nss_gns_query.lo `test -f 'nss_gns_query.c' || echo '$(srcdir)/'`nss_gns_query.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libnss_gns6_la-nss_gns_query.Tpo $(DEPDIR)/libnss_gns6_la-nss_gns_query.Plo
+@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='nss_gns_query.c' object='libnss_gns6_la-nss_gns_query.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libnss_gns6_la_CFLAGS) $(CFLAGS) -c -o libnss_gns6_la-nss_gns_query.lo `test -f 'nss_gns_query.c' || echo '$(srcdir)/'`nss_gns_query.c
+
+libnss_gns6_la-nss_gns.lo: nss_gns.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libnss_gns6_la_CFLAGS) $(CFLAGS) -MT libnss_gns6_la-nss_gns.lo -MD -MP -MF $(DEPDIR)/libnss_gns6_la-nss_gns.Tpo -c -o libnss_gns6_la-nss_gns.lo `test -f 'nss_gns.c' || echo '$(srcdir)/'`nss_gns.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libnss_gns6_la-nss_gns.Tpo $(DEPDIR)/libnss_gns6_la-nss_gns.Plo
+@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='nss_gns.c' object='libnss_gns6_la-nss_gns.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libnss_gns6_la_CFLAGS) $(CFLAGS) -c -o libnss_gns6_la-nss_gns.lo `test -f 'nss_gns.c' || echo '$(srcdir)/'`nss_gns.c
+
+mostlyclean-libtool:
+ -rm -f *.lo
+
+clean-libtool:
+ -rm -rf .libs _libs
+
+ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ mkid -fID $$unique
+tags: TAGS
+
+TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ set x; \
+ here=`pwd`; \
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ shift; \
+ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
+ test -n "$$unique" || unique=$$empty_fix; \
+ if test $$# -gt 0; then \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ "$$@" $$unique; \
+ else \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ $$unique; \
+ fi; \
+ fi
+ctags: CTAGS
+CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ test -z "$(CTAGS_ARGS)$$unique" \
+ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+ $$unique
+
+GTAGS:
+ here=`$(am__cd) $(top_builddir) && pwd` \
+ && $(am__cd) $(top_srcdir) \
+ && gtags -i $(GTAGS_ARGS) "$$here"
+
+distclean-tags:
+ -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+distdir: $(DISTFILES)
+ @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ list='$(DISTFILES)'; \
+ dist_files=`for file in $$list; do echo $$file; done | \
+ sed -e "s|^$$srcdirstrip/||;t" \
+ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+ case $$dist_files in \
+ */*) $(MKDIR_P) `echo "$$dist_files" | \
+ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+ sort -u` ;; \
+ esac; \
+ for file in $$dist_files; do \
+ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+ if test -d $$d/$$file; then \
+ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+ if test -d "$(distdir)/$$file"; then \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
+ else \
+ test -f "$(distdir)/$$file" \
+ || cp -p $$d/$$file "$(distdir)/$$file" \
+ || exit 1; \
+ fi; \
+ done
+check-am: all-am
+check: check-am
+all-am: Makefile $(LTLIBRARIES)
+installdirs:
+ for dir in "$(DESTDIR)$(nssdir)"; do \
+ test -z "$$dir" || $(MKDIR_P) "$$dir"; \
+ done
+install: install-am
+install-exec: install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
+
+install-am: all-am
+ @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-am
+install-strip:
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ `test -z '$(STRIP)' || \
+ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+ -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+ -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
+
+maintainer-clean-generic:
+ @echo "This command is intended for maintainers to use"
+ @echo "it deletes files that may require special tools to rebuild."
+clean: clean-am
+
+clean-am: clean-generic clean-libtool clean-nssLTLIBRARIES \
+ mostlyclean-am
+
+distclean: distclean-am
+ -rm -rf ./$(DEPDIR)
+ -rm -f Makefile
+distclean-am: clean-am distclean-compile distclean-generic \
+ distclean-tags
+
+dvi: dvi-am
+
+dvi-am:
+
+html: html-am
+
+html-am:
+
+info: info-am
+
+info-am:
+
+install-data-am: install-nssLTLIBRARIES
+ @$(NORMAL_INSTALL)
+ $(MAKE) $(AM_MAKEFLAGS) install-data-hook
+install-dvi: install-dvi-am
+
+install-dvi-am:
+
+install-exec-am:
+
+install-html: install-html-am
+
+install-html-am:
+
+install-info: install-info-am
+
+install-info-am:
+
+install-man:
+
+install-pdf: install-pdf-am
+
+install-pdf-am:
+
+install-ps: install-ps-am
+
+install-ps-am:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+ -rm -rf ./$(DEPDIR)
+ -rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-compile mostlyclean-generic \
+ mostlyclean-libtool
+
+pdf: pdf-am
+
+pdf-am:
+
+ps: ps-am
+
+ps-am:
+
+uninstall-am: uninstall-nssLTLIBRARIES
+ @$(NORMAL_INSTALL)
+ $(MAKE) $(AM_MAKEFLAGS) uninstall-hook
+.MAKE: install-am install-data-am install-strip uninstall-am
+
+.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \
+ clean-libtool clean-nssLTLIBRARIES ctags distclean \
+ distclean-compile distclean-generic distclean-libtool \
+ distclean-tags distdir dvi dvi-am html html-am info info-am \
+ install install-am install-data install-data-am \
+ install-data-hook install-dvi install-dvi-am install-exec \
+ install-exec-am install-html install-html-am install-info \
+ install-info-am install-man install-nssLTLIBRARIES install-pdf \
+ install-pdf-am install-ps install-ps-am install-strip \
+ installcheck installcheck-am installdirs maintainer-clean \
+ maintainer-clean-generic mostlyclean mostlyclean-compile \
+ mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \
+ tags uninstall uninstall-am uninstall-hook \
+ uninstall-nssLTLIBRARIES
+
+
+install-data-hook:
+ $(SUDO_BINARY) $(SHELL) $(top_builddir)/libtool --finish $(nssdir)
+ $(SUDO_BINARY) rm -f $(nssdir)/libnss_gns.la $(nssdir)/libnss_gns4.la $(nssdir)/libnss_gns6.la
+
+uninstall-hook:
+ $(SUDO_BINARY) rm -f $(nssdir)/libnss_gns.so.2 $(nssdir)/libnss_gns4.so.2 $(nssdir)/libnss_gns6.so.2
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/src/gns/nss/map-file b/src/gns/nss/map-file
new file mode 100644
index 0000000..476d0ac
--- /dev/null
+++ b/src/gns/nss/map-file
@@ -0,0 +1,14 @@
+NSSGNS_0 {
+global:
+_nss_gns_gethostbyaddr_r;
+_nss_gns4_gethostbyaddr_r;
+_nss_gns6_gethostbyaddr_r;
+_nss_gns_gethostbyname_r;
+_nss_gns4_gethostbyname_r;
+_nss_gns6_gethostbyname_r;
+_nss_gns_gethostbyname2_r;
+_nss_gns4_gethostbyname2_r;
+_nss_gns6_gethostbyname2_r;
+local:
+*;
+};
diff --git a/src/gns/nss/nss_gns.c b/src/gns/nss/nss_gns.c
new file mode 100644
index 0000000..3bb45a1
--- /dev/null
+++ b/src/gns/nss/nss_gns.c
@@ -0,0 +1,264 @@
+/***
+ This file is part of nss-gns.
+
+ Parts taken from: nss.c in nss-mdns
+
+ nss-mdns is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published
+ by the Free Software Foundation; either version 2 of the License,
+ or (at your option) any later version.
+
+ nss-mdns is distributed in the hope that it will be useful, but1
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with nss-mdns; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ USA.
+***/
+
+#include <gnunet_config.h>
+#include <unistd.h>
+#include <errno.h>
+#include <string.h>
+#include <assert.h>
+#include <netdb.h>
+#include <sys/socket.h>
+#include <nss.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "nss_gns_query.h"
+
+#include <arpa/inet.h>
+
+/** macro to align idx to 32bit boundary */
+#define ALIGN(idx) do { \
+ if (idx % sizeof(void*)) \
+ idx += (sizeof(void*) - idx % sizeof(void*)); /* Align on 32 bit boundary */ \
+} while(0)
+
+
+/**
+ * function to check if name ends with a specific suffix
+ *
+ * @param name the name to check
+ * @param suffix the suffix to check for
+ * @return 1 if true
+ */
+static int ends_with(const char *name, const char* suffix) {
+ size_t ln, ls;
+ assert(name);
+ assert(suffix);
+
+ if ((ls = strlen(suffix)) > (ln = strlen(name)))
+ return 0;
+
+ return strcasecmp(name+ln-ls, suffix) == 0;
+}
+
+
+/**
+ * Check if name is inside .gnunet or .zkey TLD
+ *
+ * @param name name to check
+ * @return 1 if true
+ */
+static int verify_name_allowed(const char *name) {
+ return ends_with(name, ".gnunet") || ends_with(name, ".zkey");
+}
+
+/**
+ * The gethostbyname hook executed by nsswitch
+ *
+ * @param name the name to resolve
+ * @param af the address family to resolve
+ * @param result the result hostent
+ * @param buffer the result buffer
+ * @param buflen length of the buffer
+ * @param errnop idk
+ * @param h_errnop idk
+ * @return a nss_status code
+ */
+enum nss_status _nss_gns_gethostbyname2_r(
+ const char *name,
+ int af,
+ struct hostent * result,
+ char *buffer,
+ size_t buflen,
+ int *errnop,
+ int *h_errnop) {
+
+ struct userdata u;
+ enum nss_status status = NSS_STATUS_UNAVAIL;
+ int i;
+ size_t address_length, l, idx, astart;
+ int name_allowed;
+
+ if (af == AF_UNSPEC)
+#ifdef NSS_IPV6_ONLY
+ af = AF_INET6;
+#else
+ af = AF_INET;
+#endif
+
+#ifdef NSS_IPV4_ONLY
+ if (af != AF_INET)
+#elif NSS_IPV6_ONLY
+ if (af != AF_INET6)
+#else
+ if (af != AF_INET && af != AF_INET6)
+#endif
+ {
+ *errnop = EINVAL;
+ *h_errnop = NO_RECOVERY;
+
+ goto finish;
+ }
+
+ address_length = af == AF_INET ? sizeof(ipv4_address_t) : sizeof(ipv6_address_t);
+ if (buflen <
+ sizeof(char*)+ /* alias names */
+ strlen(name)+1) { /* official name */
+
+ *errnop = ERANGE;
+ *h_errnop = NO_RECOVERY;
+ status = NSS_STATUS_TRYAGAIN;
+
+ goto finish;
+ }
+
+ u.count = 0;
+ u.data_len = 0;
+
+ name_allowed = verify_name_allowed(name);
+
+ if (name_allowed) {
+
+ if (!gns_resolve_name(af, name, &u) == 0)
+ {
+ status = NSS_STATUS_NOTFOUND;
+ }
+ }
+
+ if (u.count == 0) {
+ *errnop = ETIMEDOUT;
+ *h_errnop = HOST_NOT_FOUND;
+ printf("not found\n");
+ goto finish;
+ }
+
+
+ /* Alias names */
+ *((char**) buffer) = NULL;
+ result->h_aliases = (char**) buffer;
+ idx = sizeof(char*);
+
+ /* Official name */
+ strcpy(buffer+idx, name);
+ result->h_name = buffer+idx;
+ idx += strlen(name)+1;
+
+ ALIGN(idx);
+
+ result->h_addrtype = af;
+ result->h_length = address_length;
+
+ /* Check if there's enough space for the addresses */
+ if (buflen < idx+u.data_len+sizeof(char*)*(u.count+1)) {
+ *errnop = ERANGE;
+ *h_errnop = NO_RECOVERY;
+ status = NSS_STATUS_TRYAGAIN;
+ goto finish;
+ }
+
+ /* Addresses */
+ astart = idx;
+ l = u.count*address_length;
+ memcpy(buffer+astart, &u.data, l);
+ /* address_length is a multiple of 32bits, so idx is still aligned
+ * correctly */
+ idx += l;
+
+ /* Address array address_lenght is always a multiple of 32bits */
+ for (i = 0; i < u.count; i++)
+ ((char**) (buffer+idx))[i] = buffer+astart+address_length*i;
+ ((char**) (buffer+idx))[i] = NULL;
+ result->h_addr_list = (char**) (buffer+idx);
+
+ status = NSS_STATUS_SUCCESS;
+
+finish:
+ return status;
+}
+
+/**
+ * The gethostbyname hook executed by nsswitch
+ *
+ * @param name the name to resolve
+ * @param result the result hostent
+ * @param buffer the result buffer
+ * @param buflen length of the buffer
+ * @param errnop idk
+ * @param h_errnop idk
+ * @return a nss_status code
+ */
+enum nss_status _nss_gns_gethostbyname_r (
+ const char *name,
+ struct hostent *result,
+ char *buffer,
+ size_t buflen,
+ int *errnop,
+ int *h_errnop) {
+
+ return _nss_gns_gethostbyname2_r(
+ name,
+ AF_UNSPEC,
+ result,
+ buffer,
+ buflen,
+ errnop,
+ h_errnop);
+}
+
+/**
+ * The gethostbyaddr hook executed by nsswitch
+ * We can't do this so we always return NSS_STATUS_UNAVAIL
+ *
+ * @param addr the address to resolve
+ * @param len the length of the address
+ * @param af the address family of the address
+ * @param result the result hostent
+ * @param buffer the result buffer
+ * @param buflen length of the buffer
+ * @param errnop idk
+ * @param h_errnop idk
+ * @return NSS_STATUS_UNAVAIL
+ */
+enum nss_status _nss_gns_gethostbyaddr_r(
+ const void* addr,
+ int len,
+ int af,
+ struct hostent *result,
+ char *buffer,
+ size_t buflen,
+ int *errnop,
+ int *h_errnop) {
+
+ /* we dont do this */
+
+ enum nss_status status = NSS_STATUS_UNAVAIL;
+
+ *errnop = EINVAL;
+ *h_errnop = NO_RECOVERY;
+
+ /* Check for address types */
+
+ *h_errnop = NO_RECOVERY;
+
+ status = NSS_STATUS_NOTFOUND;
+ return status;
+}
+
diff --git a/src/gns/nss/nss_gns_query.c b/src/gns/nss/nss_gns_query.c
new file mode 100644
index 0000000..ab88d22
--- /dev/null
+++ b/src/gns/nss/nss_gns_query.c
@@ -0,0 +1,65 @@
+#include <string.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include "nss_gns_query.h"
+#include <arpa/inet.h>
+
+
+/**
+ * Wrapper function that uses gnunet-gns cli tool to resolve
+ * an IPv4/6 address.
+ *
+ * @param af address family
+ * @param name the name to resolve
+ * @param u the userdata (result struct)
+ * @return -1 on error else 0
+ */
+int gns_resolve_name(int af, const char *name, struct userdata *u)
+{
+ FILE *p;
+ char *cmd;
+ char line[128];
+
+ if (af == AF_INET6)
+ {
+ if (-1 == asprintf(&cmd, "%s -t AAAA -u %s\n", "gnunet-gns -r", name))
+ return -1;
+ }
+ else
+ {
+ if (-1 == asprintf(&cmd, "%s %s\n", "gnunet-gns -r -u", name))
+ return -1;
+ }
+
+ p = popen(cmd,"r");
+
+ if (p != NULL )
+ {
+ while (fgets( line, sizeof(line), p ) != NULL)
+ {
+
+ if (u->count >= MAX_ENTRIES)
+ break;
+
+ if (line[strlen(line)-1] == '\n')
+ {
+ line[strlen(line)-1] = '\0';
+ if (af == AF_INET)
+ {
+ inet_pton(af, line, &(u->data.ipv4[u->count++]));
+ u->data_len += sizeof(ipv4_address_t);
+ }
+ else if ((af == AF_INET6))
+ {
+ inet_pton(af, line, &(u->data.ipv6[u->count++]));
+ u->data_len += sizeof(ipv6_address_t);
+ }
+ }
+ }
+ }
+ fclose(p);
+ free(cmd);
+
+ return 0;
+
+}
diff --git a/src/gns/nss/nss_gns_query.h b/src/gns/nss/nss_gns_query.h
new file mode 100644
index 0000000..0b4dae5
--- /dev/null
+++ b/src/gns/nss/nss_gns_query.h
@@ -0,0 +1,66 @@
+#ifndef NSS_GNS_QUERY_H
+#define NSS_GNS_QUERY_H
+
+/**
+ * Parts taken from nss-mdns. Original license statement follows
+ */
+
+/* $Id$ */
+
+/***
+ This file is part of nss-mdns.
+
+ nss-mdns is free software; you can redistribute it and/or modify it
+ under the terms of the GNU Lesser General Public License as
+ published by the Free Software Foundation; either version 2 of the
+ License, or (at your option) any later version.
+
+ nss-mdns is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with nss-mdns; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ USA.
+***/
+
+#include <inttypes.h>
+
+/* Maximum number of entries to return */
+#define MAX_ENTRIES 16
+
+typedef struct {
+ uint32_t address;
+} ipv4_address_t;
+
+typedef struct {
+ uint8_t address[16];
+} ipv6_address_t;
+
+
+struct userdata {
+ int count;
+ int data_len; /* only valid when doing reverse lookup */
+ union {
+ ipv4_address_t ipv4[MAX_ENTRIES];
+ ipv6_address_t ipv6[MAX_ENTRIES];
+ char *name[MAX_ENTRIES];
+ } data;
+};
+
+/**
+ * Wrapper function that uses gnunet-gns cli tool to resolve
+ * an IPv4/6 address.
+ *
+ * @param af address family
+ * @param name the name to resolve
+ * @param u the userdata (result struct)
+ * @return -1 on error else 0
+ */
+int gns_resolve_name(int af,
+ const char *name,
+ struct userdata *userdata);
+
+#endif
diff --git a/src/gns/plugin_block_gns.c b/src/gns/plugin_block_gns.c
index a4d6ad9..5d986ce 100644
--- a/src/gns/plugin_block_gns.c
+++ b/src/gns/plugin_block_gns.c
@@ -62,86 +62,135 @@ block_plugin_gns_evaluate (void *cls, enum GNUNET_BLOCK_Type type,
size_t xquery_size, const void *reply_block,
size_t reply_block_size)
{
- if (type != GNUNET_BLOCK_TYPE_GNS_NAMERECORD)
- return GNUNET_BLOCK_EVALUATION_TYPE_NOT_SUPPORTED;
- if (reply_block_size == 0)
- return GNUNET_BLOCK_EVALUATION_REQUEST_VALID;
-
char* name;
- GNUNET_HashCode pkey_hash;
+ GNUNET_HashCode pkey_hash_double;
GNUNET_HashCode query_key;
- GNUNET_HashCode name_hash;
+ GNUNET_HashCode name_hash_double;
GNUNET_HashCode mhash;
GNUNET_HashCode chash;
+ struct GNUNET_CRYPTO_ShortHashCode pkey_hash;
+ struct GNUNET_CRYPTO_ShortHashCode name_hash;
struct GNSNameRecordBlock *nrb;
- struct GNSRecordBlock *rb;
uint32_t rd_count;
+ char* rd_data = NULL;
+ int rd_len;
+ uint32_t record_xquery;
+ unsigned int record_match;
+ //GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "RB SIZE %d\n", reply_block_size);
+
+ if (type != GNUNET_BLOCK_TYPE_GNS_NAMERECORD)
+ return GNUNET_BLOCK_EVALUATION_TYPE_NOT_SUPPORTED;
+ if (reply_block == NULL)
+ {
+ /**
+ * check if request is valid
+ * FIXME we could check for the record types here
+ **/
+ if (xquery_size < sizeof(uint32_t))
+ {
+ GNUNET_break_op (0);
+ return GNUNET_BLOCK_EVALUATION_REQUEST_INVALID;
+ }
+ return GNUNET_BLOCK_EVALUATION_REQUEST_VALID;
+ }
+
+ /* this is a reply */
+
nrb = (struct GNSNameRecordBlock *)reply_block;
name = (char*)&nrb[1];
- GNUNET_CRYPTO_hash(&nrb->public_key,
+ GNUNET_CRYPTO_short_hash(&nrb->public_key,
sizeof(nrb->public_key),
&pkey_hash);
- GNUNET_CRYPTO_hash(name, strlen(name), &name_hash);
+ GNUNET_CRYPTO_short_hash(name, strlen(name), &name_hash);
+
+ GNUNET_CRYPTO_short_hash_double(&name_hash, &name_hash_double);
+ GNUNET_CRYPTO_short_hash_double(&pkey_hash, &pkey_hash_double);
- GNUNET_CRYPTO_hash_xor(&pkey_hash, &name_hash, &query_key);
+ GNUNET_CRYPTO_hash_xor(&pkey_hash_double, &name_hash_double, &query_key);
+ struct GNUNET_CRYPTO_HashAsciiEncoded xor_exp;
+ struct GNUNET_CRYPTO_HashAsciiEncoded xor_got;
+ GNUNET_CRYPTO_hash_to_enc (&query_key, &xor_exp);
+ GNUNET_CRYPTO_hash_to_enc (query, &xor_got);
+
+ //GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
+ // "BLOCK_TEST for %s got %s expected %s\n",
+ // name, (char*) &xor_got, (char*) &xor_exp);
+
/* Check query key against public key */
if (0 != GNUNET_CRYPTO_hash_cmp(query, &query_key))
- return GNUNET_BLOCK_EVALUATION_REQUEST_VALID;
+ {
+ GNUNET_break_op (0);
+ return GNUNET_BLOCK_EVALUATION_RESULT_INVALID;
+ }
+ record_match = 0;
rd_count = ntohl(nrb->rd_count);
-
- struct GNUNET_NAMESTORE_RecordData rd[rd_count];
- int i = 0;
- int record_match = 0;
- uint32_t record_xquery = ntohl(*((uint32_t*)xquery));
- rb = (struct GNSRecordBlock*)(&name[strlen(name) + 1]);
-
- for (i=0; i<rd_count; i++)
+ rd_data = (char*)&nrb[1];
+ rd_data += strlen(name) + 1;
+ rd_len = reply_block_size - (strlen(name) + 1
+ + sizeof(struct GNSNameRecordBlock));
{
- rd[i].record_type = ntohl(rb->type);
- rd[i].expiration =
- GNUNET_TIME_absolute_ntoh(rb->expiration);
- rd[i].data_size = ntohl(rb->data_length);
- rd[i].flags = ntohl(rb->flags);
- rd[i].data = (char*)&rb[1];
- rb = (struct GNSRecordBlock *)((char*)&rb[1] + rd[i].data_size);
+ struct GNUNET_NAMESTORE_RecordData rd[rd_count];
+ unsigned int i;
+ struct GNUNET_TIME_Absolute exp = GNUNET_TIME_UNIT_FOREVER_ABS;
- if (xquery_size == 0)
- continue;
+ if (GNUNET_SYSERR == GNUNET_NAMESTORE_records_deserialize (rd_len,
+ rd_data,
+ rd_count,
+ rd))
+ {
+ GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
+ "Data invalid (%d bytes, %d records)\n", rd_len, rd_count);
+ GNUNET_break_op (0);
+ return GNUNET_BLOCK_EVALUATION_RESULT_INVALID;
+ }
+
+ if (xquery_size < sizeof(uint32_t))
+ record_xquery = 0;
+ else
+ record_xquery = ntohl(*((uint32_t*)xquery));
- if (rd[i].record_type == record_xquery)
+ for (i=0; i<rd_count; i++)
{
- record_match++;
+
+ exp = GNUNET_TIME_absolute_min (exp, rd[i].expiration);
+
+ GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
+ "Got record of size %d\n", rd[i].data_size);
+
+ if ((record_xquery != 0)
+ && (rd[i].record_type == record_xquery))
+ {
+ record_match++;
+ }
}
- }
-
+
+ GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
+ "Verifying signature of %d records for name %s\n",
+ rd_count, name);
- /*if (GNUNET_OK != GNUNET_NAMESTORE_verify_signature (&nrb->public_key,
- name,
- rd_count,
- rd,
- NULL))
- {
- GNUNET_log(GNUNET_ERROR_TYPE_INFO, "Signature invalid\n");
- return GNUNET_BLOCK_EVALUATION_REQUEST_INVALID;
- }*/
+ if (GNUNET_OK != GNUNET_NAMESTORE_verify_signature (&nrb->public_key,
+ exp,
+ name,
+ rd_count,
+ rd,
+ &nrb->signature))
+ {
+ GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Signature invalid for name %s\n");
+ GNUNET_break_op (0);
+ return GNUNET_BLOCK_EVALUATION_RESULT_INVALID;
+ }
+ }
- //No record matches query
- if ((xquery_size > 0) && (record_match == 0))
- return GNUNET_BLOCK_EVALUATION_REQUEST_VALID;
-
- GNUNET_log(GNUNET_ERROR_TYPE_INFO, "Records match\n");
- //FIXME do bf check before or after crypto??
if (NULL != bf)
{
GNUNET_CRYPTO_hash(reply_block, reply_block_size, &chash);
GNUNET_BLOCK_mingle_hash(&chash, bf_mutator, &mhash);
if (NULL != *bf)
{
- GNUNET_log(GNUNET_ERROR_TYPE_INFO, "Check BF\n");
if (GNUNET_YES == GNUNET_CONTAINER_bloomfilter_test(*bf, &mhash))
return GNUNET_BLOCK_EVALUATION_OK_DUPLICATE;
}
@@ -151,7 +200,6 @@ block_plugin_gns_evaluate (void *cls, enum GNUNET_BLOCK_Type type,
}
GNUNET_CONTAINER_bloomfilter_add(*bf, &mhash);
}
- GNUNET_log(GNUNET_ERROR_TYPE_INFO, "No dup\n");
return GNUNET_BLOCK_EVALUATION_OK_MORE;
}
@@ -174,18 +222,23 @@ block_plugin_gns_get_key (void *cls, enum GNUNET_BLOCK_Type type,
{
if (type != GNUNET_BLOCK_TYPE_GNS_NAMERECORD)
return GNUNET_SYSERR;
- GNUNET_HashCode name_hash;
- GNUNET_HashCode pkey_hash;
+ struct GNUNET_CRYPTO_ShortHashCode name_hash;
+ struct GNUNET_CRYPTO_ShortHashCode pkey_hash;
+ GNUNET_HashCode name_hash_double;
+ GNUNET_HashCode pkey_hash_double;
+
struct GNSNameRecordBlock *nrb = (struct GNSNameRecordBlock *)block;
- GNUNET_CRYPTO_hash(&nrb[1], strlen((char*)&nrb[1]), &name_hash);
- GNUNET_CRYPTO_hash(&nrb->public_key,
+ GNUNET_CRYPTO_short_hash(&nrb[1], strlen((char*)&nrb[1]), &name_hash);
+ GNUNET_CRYPTO_short_hash(&nrb->public_key,
sizeof(struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded),
&pkey_hash);
+
+ GNUNET_CRYPTO_short_hash_double(&name_hash, &name_hash_double);
+ GNUNET_CRYPTO_short_hash_double(&pkey_hash, &pkey_hash_double);
- GNUNET_CRYPTO_hash_xor(&name_hash, &pkey_hash, key);
+ GNUNET_CRYPTO_hash_xor(&name_hash_double, &pkey_hash_double, key);
- //FIXME calculate key from name and hash(pkey) here
return GNUNET_OK;
}
diff --git a/src/gns/test_gns_defaults.conf b/src/gns/test_gns_defaults.conf
new file mode 100644
index 0000000..b7e68ff
--- /dev/null
+++ b/src/gns/test_gns_defaults.conf
@@ -0,0 +1,69 @@
+[PATHS]
+SERVICEHOME = /tmp/test-gnunet-testing/
+DEFAULTCONFIG = test_testing_defaults.conf
+
+[resolver]
+PORT = 2564
+
+[transport]
+PORT = 2565
+PLUGINS = tcp
+
+[arm]
+PORT = 2566
+DEFAULTSERVICES =
+
+[statistics]
+PORT = 2567
+
+[transport-tcp]
+PORT = 2568
+BINDTO = 127.0.0.1
+
+[peerinfo]
+PORT = 2569
+
+[core]
+PORT = 2570
+
+[testing]
+NUM_PEERS = 5
+WEAKRANDOM = YES
+F2F = YES
+HOSTKEYSFILE = ../../contrib/testing_hostkeys.dat
+
+[dht]
+AUTOSTART = NO
+
+[nat]
+DISABLEV6 = YES
+ENABLE_UPNP = NO
+BEHIND_NAT = NO
+ALLOW_NAT = NO
+INTERNAL_ADDRESS = 127.0.0.1
+EXTERNAL_ADDRESS = 127.0.0.1
+USE_LOCALADDR = NO
+
+[dns]
+AUTOSTART = NO
+
+[nse]
+AUTOSTART = NO
+
+[mesh]
+AUTOSTART = NO
+
+[datastore]
+AUTOSTART = NO
+
+[fs]
+AUTOSTART = NO
+
+[dv]
+AUTOSTART = NO
+
+[chat]
+AUTOSTART = NO
+
+[vpn]
+AUTOSTART = NO
diff --git a/src/gns/test_gns_dht_default.conf b/src/gns/test_gns_dht_default.conf
new file mode 100644
index 0000000..1b37373
--- /dev/null
+++ b/src/gns/test_gns_dht_default.conf
@@ -0,0 +1,94 @@
+@INLINE@ test_gns_defaults.conf
+[PATHS]
+SERVICEHOME = /tmp/test-gnunet-gns-dht/
+DEFAULTCONFIG = test_gns_dht_default.conf
+
+[transport-tcp]
+PORT = 22568
+
+[dht]
+UNIXPATH = /tmp/gnunet-service-dht.sock
+DEBUG = NO
+AUTOSTART = YES
+ACCEPT_FROM6 = ::1;
+ACCEPT_FROM = 127.0.0.1;
+HOSTNAME = localhost
+PORT = 2102
+BINARY = gnunet-service-dht
+
+[block]
+plugins = dht test gns
+
+[dhtcache]
+QUOTA = 1 MB
+DATABASE = sqlite
+
+[arm]
+PORT = 22566
+DEFAULTSERVICES = core namestore dht gns
+UNIXPATH = /tmp/gnunet-default-service-arm.sock
+
+[statistics]
+PORT = 22567
+UNIXPATH = /tmp/gnunet-default-service-statistics.sock
+
+[resolver]
+PORT = 22564
+UNIXPATH = /tmp/gnunet-default-service-resolver.sock
+
+[peerinfo]
+PORT = 22569
+UNIXPATH = /tmp/gnunet-default-service-peerinfo.sock
+
+[transport]
+PORT = 22565
+UNIXPATH = /tmp/gnunet-default-service-transport.sock
+
+[core]
+PORT = 22570
+UNIXPATH = /tmp/gnunet-default-service-core.sock
+
+[ats]
+PORT = 22571
+UNIXPATH = /tmp/gnunet-default-service-ats.sock
+
+[dns]
+UNIXPATH = /tmp/gnunet-default-service-dns.sock
+PORT = 22369
+AUTOSTART = YES
+DNS_EXIT = 8.8.8.8
+
+[gns]
+PORT = 22370
+#PREFIX = valgrind -v --leak-check=full --track-origins=yes.
+AUTOSTART = YES
+BINARY = gnunet-service-gns
+ZONEKEY = $SERVICEHOME/zonekey.zkey
+HIJACK_DNS = NO
+UNIXPATH = /tmp/gnunet-service-gns-default.sock
+HOME = $SERVICEHOME
+CONFIG = $DEFAULTCONFIG
+AUTO_IMPORT_PKEY = NO
+MAX_PARALLEL_BACKGROUND_QUERIES = 10
+DEFAULT_LOOKUP_TIMEOUT = 60
+RECORD_PUT_INTERVAL = 1
+ZONE_PUT_INTERVAL = 5
+
+[namestore]
+PORT = 22371
+AUTOSTART = YES
+UNIXPATH = /tmp/gnunet-service-namestore-default.sock
+UNIX_MATCH_UID = YES
+UNIX_MATCH_GID = YES
+HOSTNAME = localhost
+HOME = $SERVICEHOME
+CONFIG = $DEFAULTCONFIG
+BINARY = gnunet-service-namestore
+ACCEPT_FROM = 127.0.0.1;
+ACCEPT_FROM6 = ::1;
+DATABASE = sqlite
+ZONEFILE_DIRECTORY = $SERVICEHOME
+
+[namestore-sqlite]
+FILENAME = $SERVICEHOME/sqlite-default.db
+
diff --git a/src/gns/test_gns_dht_delegated_lookup.c b/src/gns/test_gns_dht_delegated_lookup.c
new file mode 100644
index 0000000..882bb7e
--- /dev/null
+++ b/src/gns/test_gns_dht_delegated_lookup.c
@@ -0,0 +1,411 @@
+/*
+ This file is part of GNUnet.
+ (C) 2009 Christian Grothoff (and other contributing authors)
+
+ GNUnet is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 3, or (at your
+ option) any later version.
+
+ GNUnet is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GNUnet; see the file COPYING. If not, write to the
+ Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+/**
+ * @file gns/test_gns_dht_delegated_lookup.c
+ * @brief test for record lookup via DHT
+ *
+ */
+#include "platform.h"
+#include "gnunet_testing_lib.h"
+#include "gnunet_core_service.h"
+#include "block_gns.h"
+#include "gnunet_signatures.h"
+#include "gnunet_namestore_service.h"
+#include "../namestore/namestore.h"
+#include "gnunet_dnsparser_lib.h"
+#include "gnunet_dht_service.h"
+#include "gnunet_gns_service.h"
+
+/* DEFINES */
+#define VERBOSE GNUNET_YES
+
+/* Timeout for entire testcase */
+#define TIMEOUT GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_SECONDS, 20)
+
+/* If number of peers not in config file, use this number */
+#define DEFAULT_NUM_PEERS 2
+
+/* test records to resolve */
+#define TEST_DOMAIN "www.bob.gnunet"
+#define TEST_IP "127.0.0.1"
+#define TEST_RECORD_NAME "www"
+
+#define TEST_AUTHORITY_NAME "bob"
+
+#define DHT_OPERATION_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 1)
+
+#define KEYFILE_BOB "../namestore/zonefiles/HGU0A0VCU334DN7F2I9UIUMVQMM7JMSD142LIMNUGTTV9R0CF4EG.zkey"
+
+/* Globals */
+
+/**
+ * Directory to store temp data in, defined in config file
+ */
+static char *test_directory;
+
+static struct GNUNET_TESTING_PeerGroup *pg;
+
+/* Task handle to use to schedule test failure */
+GNUNET_SCHEDULER_TaskIdentifier die_task;
+
+/* Global return value (0 for success, anything else for failure) */
+static int ok;
+
+static struct GNUNET_NAMESTORE_Handle *namestore_handle;
+
+static struct GNUNET_GNS_Handle *gns_handle;
+
+static struct GNUNET_DHT_Handle *dht_handle;
+
+const struct GNUNET_CONFIGURATION_Handle *cfg;
+
+struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded alice_pkey;
+struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded bob_pkey;
+struct GNUNET_CRYPTO_RsaPrivateKey *alice_key;
+struct GNUNET_CRYPTO_RsaPrivateKey *bob_key;
+
+/**
+ * Check whether peers successfully shut down.
+ */
+void
+shutdown_callback (void *cls, const char *emsg)
+{
+ if (emsg != NULL)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Error on shutdown! ret=%d\n", ok);
+ if (ok == 0)
+ ok = 2;
+ }
+
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO, "done(ret=%d)!\n", ok);
+}
+
+
+static void
+on_lookup_result(void *cls, uint32_t rd_count,
+ const struct GNUNET_NAMESTORE_RecordData *rd)
+{
+ struct in_addr a;
+ int i;
+ char* addr;
+
+ if (rd_count == 0)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "Lookup failed, rp_filtering?\n");
+ ok = 2;
+ }
+ else
+ {
+ ok = 1;
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO, "name: %s\n", (char*)cls);
+ for (i=0; i<rd_count; i++)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO, "type: %d\n", rd[i].record_type);
+ if (rd[i].record_type == GNUNET_GNS_RECORD_TYPE_A)
+ {
+ memcpy(&a, rd[i].data, sizeof(a));
+ addr = inet_ntoa(a);
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO, "address: %s\n", addr);
+ if (0 == strcmp(addr, TEST_IP))
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+ "%s correctly resolved to %s!\n", TEST_DOMAIN, addr);
+ ok = 0;
+ }
+ }
+ else
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "No resolution!\n");
+ }
+ }
+ }
+ GNUNET_GNS_disconnect(gns_handle);
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Shutting down peer1!\n");
+ //GNUNET_TESTING_daemon_stop (d1, TIMEOUT, &shutdown_callback, NULL,
+ // GNUNET_YES, GNUNET_NO);
+ GNUNET_TESTING_daemons_stop (pg, TIMEOUT, &shutdown_callback, NULL);
+}
+
+
+/**
+ * Function scheduled to be run on the successful start of services
+ * tries to look up the dns record for TEST_DOMAIN
+ */
+static void
+commence_testing (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
+{
+ GNUNET_NAMESTORE_disconnect(namestore_handle, GNUNET_YES);
+
+ gns_handle = GNUNET_GNS_connect(cfg);
+
+ if (NULL == gns_handle)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "Failed to connect to GNS!\n");
+ }
+
+ GNUNET_GNS_lookup(gns_handle, TEST_DOMAIN, GNUNET_GNS_RECORD_TYPE_A,
+ &on_lookup_result, TEST_DOMAIN);
+}
+
+/**
+ * Continuation for the GNUNET_DHT_get_stop call, so that we don't shut
+ * down the peers without freeing memory associated with GET request.
+ */
+static void
+end_badly_cont (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
+{
+
+ if (pg != NULL) {
+ GNUNET_TESTING_daemons_stop (pg, TIMEOUT, &shutdown_callback, NULL);
+ }
+ GNUNET_SCHEDULER_cancel (die_task);
+}
+
+/**
+ * Check if the get_handle is being used, if so stop the request. Either
+ * way, schedule the end_badly_cont function which actually shuts down the
+ * test.
+ */
+static void
+end_badly (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
+{
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Failing test with error: `%s'!\n",
+ (char *) cls);
+ GNUNET_SCHEDULER_add_now (&end_badly_cont, NULL);
+ ok = 1;
+}
+
+
+static void
+put_dht(void *cls, int32_t success, const char *emsg)
+{
+ struct GNSNameRecordBlock *nrb;
+ struct GNUNET_CRYPTO_ShortHashCode name_hash;
+ struct GNUNET_CRYPTO_ShortHashCode zone_hash;
+ GNUNET_HashCode xor_hash;
+ GNUNET_HashCode name_hash_double;
+ GNUNET_HashCode zone_hash_double;
+ uint32_t rd_payload_length;
+ char* nrb_data = NULL;
+ struct GNUNET_CRYPTO_RsaSignature *sig;
+ struct GNUNET_NAMESTORE_RecordData rd;
+ char* ip = TEST_IP;
+ struct in_addr *web = GNUNET_malloc(sizeof(struct in_addr));
+
+ rd.expiration = GNUNET_TIME_UNIT_FOREVER_ABS;
+ GNUNET_assert(1 == inet_pton (AF_INET, ip, web));
+ rd.data_size = sizeof(struct in_addr);
+ rd.data = web;
+ rd.record_type = GNUNET_DNSPARSER_TYPE_A;
+
+ sig = GNUNET_NAMESTORE_create_signature(bob_key, GNUNET_TIME_UNIT_FOREVER_ABS, TEST_RECORD_NAME,
+ &rd, 1);
+ rd_payload_length = GNUNET_NAMESTORE_records_get_size (1, &rd);
+ nrb = GNUNET_malloc(rd_payload_length + strlen(TEST_RECORD_NAME) + 1
+ + sizeof(struct GNSNameRecordBlock));
+ nrb->signature = *sig;
+ nrb->public_key = bob_pkey;
+ nrb->rd_count = htonl(1);
+ memset(&nrb[1], 0, strlen(TEST_RECORD_NAME) + 1);
+ strcpy((char*)&nrb[1], TEST_RECORD_NAME);
+ nrb_data = (char*)&nrb[1];
+ nrb_data += strlen(TEST_RECORD_NAME) + 1;
+
+ if (-1 == GNUNET_NAMESTORE_records_serialize (1,
+ &rd,
+ rd_payload_length,
+ nrb_data))
+ {
+ GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Record serialization failed!\n");
+ ok = 3;
+ GNUNET_free (nrb);
+ return;
+ }
+ GNUNET_CRYPTO_short_hash(TEST_RECORD_NAME, strlen(TEST_RECORD_NAME), &name_hash);
+ GNUNET_CRYPTO_short_hash(&bob_pkey,
+ sizeof(struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded),
+ &zone_hash);
+ GNUNET_CRYPTO_short_hash_double(&zone_hash, &zone_hash_double);
+ GNUNET_CRYPTO_short_hash_double(&name_hash, &name_hash_double);
+ GNUNET_CRYPTO_hash_xor(&zone_hash_double, &name_hash_double, &xor_hash);
+
+ rd_payload_length += sizeof(struct GNSNameRecordBlock) +
+ strlen(TEST_RECORD_NAME) + 1;
+ GNUNET_DHT_put (dht_handle, &xor_hash,
+ 0,
+ GNUNET_DHT_RO_NONE,
+ GNUNET_BLOCK_TYPE_GNS_NAMERECORD,
+ rd_payload_length,
+ (char*)nrb,
+ rd.expiration,
+ DHT_OPERATION_TIMEOUT,
+ NULL,
+ NULL);
+ GNUNET_free (nrb);
+ GNUNET_SCHEDULER_add_delayed(TIMEOUT, &commence_testing, NULL);
+}
+
+static void
+do_lookup(void *cls, const struct GNUNET_PeerIdentity *id,
+ const struct GNUNET_CONFIGURATION_Handle *_cfg,
+ struct GNUNET_TESTING_Daemon *d, const char *emsg)
+{
+
+
+ char* alice_keyfile;
+ struct GNUNET_CRYPTO_ShortHashCode bob_hash;
+
+ cfg = _cfg;
+
+ GNUNET_SCHEDULER_cancel (die_task);
+
+ /* put records into namestore */
+ namestore_handle = GNUNET_NAMESTORE_connect(cfg);
+ if (NULL == namestore_handle)
+ {
+ GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Failed to connect to namestore\n");
+ ok = -1;
+ return;
+ }
+
+ /* dht */
+ dht_handle = GNUNET_DHT_connect(cfg, 1);
+ if (NULL == dht_handle)
+ {
+ GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Failed to connect to dht\n");
+ ok = -1;
+ return;
+ }
+
+ if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_filename (cfg, "gns",
+ "ZONEKEY",
+ &alice_keyfile))
+ {
+ GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Failed to get key from cfg\n");
+ ok = -1;
+ return;
+ }
+
+ alice_key = GNUNET_CRYPTO_rsa_key_create_from_file (alice_keyfile);
+ bob_key = GNUNET_CRYPTO_rsa_key_create_from_file (KEYFILE_BOB);
+
+ GNUNET_free(alice_keyfile);
+
+ GNUNET_CRYPTO_rsa_key_get_public (alice_key, &alice_pkey);
+ GNUNET_CRYPTO_rsa_key_get_public (bob_key, &bob_pkey);
+ GNUNET_CRYPTO_short_hash(&bob_pkey, sizeof(bob_pkey), &bob_hash);
+
+ struct GNUNET_NAMESTORE_RecordData rd;
+ rd.expiration = GNUNET_TIME_UNIT_FOREVER_ABS;
+ rd.data_size = sizeof(struct GNUNET_CRYPTO_ShortHashCode);
+ rd.data = &bob_hash;
+ rd.record_type = GNUNET_GNS_RECORD_PKEY;
+
+ GNUNET_NAMESTORE_record_create (namestore_handle,
+ alice_key,
+ TEST_AUTHORITY_NAME,
+ &rd,
+ &put_dht,
+ NULL);
+
+
+
+}
+
+static void
+run (void *cls, char *const *args, const char *cfgfile,
+ const struct GNUNET_CONFIGURATION_Handle *c)
+{
+ cfg = c;
+ /* Get path from configuration file */
+ if (GNUNET_YES !=
+ GNUNET_CONFIGURATION_get_value_string (cfg, "paths", "servicehome",
+ &test_directory))
+ {
+ ok = 404;
+ return;
+ }
+
+
+ /* Set up a task to end testing if peer start fails */
+ die_task =
+ GNUNET_SCHEDULER_add_delayed (TIMEOUT, &end_badly,
+ "didn't start all daemons in reasonable amount of time!!!");
+
+ /* Start alice */
+ //d1 = GNUNET_TESTING_daemon_start(cfg, TIMEOUT, GNUNET_NO, NULL, NULL, 0,
+ // NULL, NULL, NULL, &do_lookup, NULL);
+ pg = GNUNET_TESTING_daemons_start(cfg, 1, 1, 1, TIMEOUT,
+ NULL, NULL, &do_lookup, NULL, NULL, NULL, NULL);
+}
+
+static int
+check ()
+{
+ int ret;
+
+ /* Arguments for GNUNET_PROGRAM_run */
+ char *const argv[] = { "test-gns-dht-delegated-lookup", /* Name to give running binary */
+ "-c",
+ "test_gns_simple_lookup.conf", /* Config file to use */
+#if VERBOSE
+ "-L", "DEBUG",
+#endif
+ NULL
+ };
+ struct GNUNET_GETOPT_CommandLineOption options[] = {
+ GNUNET_GETOPT_OPTION_END
+ };
+ /* Run the run function as a new program */
+ ret =
+ GNUNET_PROGRAM_run ((sizeof (argv) / sizeof (char *)) - 1, argv,
+ "test-gns-dht-delegated-lookup", "nohelp", options, &run,
+ &ok);
+ if (ret != GNUNET_OK)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+ "`test-gns-dht-delegated-lookup': Failed with error code %d\n", ret);
+ }
+ return ok;
+}
+
+int
+main (int argc, char *argv[])
+{
+ int ret;
+
+ GNUNET_log_setup ("test-gns-simple-lookup",
+#if VERBOSE
+ "DEBUG",
+#else
+ "WARNING",
+#endif
+ NULL);
+ ret = check ();
+ /**
+ * Need to remove base directory, subdirectories taken care
+ * of by the testing framework.
+ */
+ return ret;
+}
+
+/* end of test_gns_twopeer.c */
diff --git a/src/gns/test_gns_dht_threepeer.c b/src/gns/test_gns_dht_threepeer.c
new file mode 100644
index 0000000..ed9600f
--- /dev/null
+++ b/src/gns/test_gns_dht_threepeer.c
@@ -0,0 +1,524 @@
+/*
+ This file is part of GNUnet.
+ (C) 2009 Christian Grothoff (and other contributing authors)
+
+ GNUnet is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 3, or (at your
+ option) any later version.
+
+ GNUnet is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GNUnet; see the file COPYING. If not, write to the
+ Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+/**
+ * @file gns/test_gns_dht_threepeer.c
+ * @brief tests dht lookup over 3 peers
+ *
+ * topology:
+ * alice <----> bob <-----> dave
+ *
+ * alice queries for www.buddy.bob.gnunet
+ *
+ */
+#include "platform.h"
+#include "gnunet_disk_lib.h"
+#include "gnunet_testing_lib.h"
+#include "gnunet_core_service.h"
+#include "gnunet_dht_service.h"
+#include "block_dns.h"
+#include "gnunet_signatures.h"
+#include "gnunet_namestore_service.h"
+#include "gnunet_dnsparser_lib.h"
+#include "gnunet_gns_service.h"
+
+/* DEFINES */
+#define VERBOSE GNUNET_YES
+
+/* Timeout for entire testcase */
+#define TIMEOUT GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_SECONDS, 180)
+#define ZONE_PUT_WAIT_TIME GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_SECONDS, 30)
+
+/* If number of peers not in config file, use this number */
+#define DEFAULT_NUM_PEERS 2
+
+#define TEST_DOMAIN "www.buddy.bob.gnunet"
+#define TEST_IP "1.1.1.1"
+#define TEST_DAVE_PSEU "hagbard"
+#define TEST_NUM_PEERS 3
+#define TEST_NUM_CON 3
+
+/* Globals */
+
+/**
+ * Directory to store temp data in, defined in config file
+ */
+static char *test_directory;
+
+/**
+ * Variable used to store the number of connections we should wait for.
+ */
+static unsigned int expected_connections;
+
+/**
+ * Variable used to keep track of how many peers aren't yet started.
+ */
+static unsigned long long peers_left;
+
+struct GNUNET_TESTING_Daemon *d1;
+struct GNUNET_TESTING_Daemon *d2;
+struct GNUNET_TESTING_Daemon *d3;
+
+
+/**
+ * Total number of peers to run, set based on config file.
+ */
+static unsigned long long num_peers;
+
+/**
+ * Global used to count how many connections we have currently
+ * been notified about (how many times has topology_callback been called
+ * with success?)
+ */
+static unsigned int total_connections;
+
+/**
+ * Global used to count how many failed connections we have
+ * been notified about (how many times has topology_callback
+ * been called with failure?)
+ */
+static unsigned int failed_connections;
+
+/* Task handle to use to schedule test failure */
+GNUNET_SCHEDULER_TaskIdentifier die_task;
+
+GNUNET_SCHEDULER_TaskIdentifier bob_task;
+
+/* Global return value (0 for success, anything else for failure) */
+static int ok;
+
+int bob_online, alice_online, dave_online;
+
+const struct GNUNET_CONFIGURATION_Handle *alice_cfg;
+struct GNUNET_CONFIGURATION_Handle *cfg_bob;
+struct GNUNET_CONFIGURATION_Handle *cfg_dave;
+
+struct GNUNET_CRYPTO_ShortHashCode bob_hash;
+struct GNUNET_CRYPTO_ShortHashCode dave_hash;
+struct GNUNET_TESTING_Daemon *alice_daemon;
+struct GNUNET_TESTING_Daemon *bob_daemon;
+struct GNUNET_TESTING_Daemon *dave_daemon;
+
+struct GNUNET_TESTING_PeerGroup *pg;
+struct GNUNET_GNS_Handle *gh;
+
+/**
+ * Function scheduled to be run on the successful completion of this
+ * testcase. Specifically, called when our get request completes.
+ */
+static void
+finish_testing (void *cls, const char *emsg)
+{
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Test finished! (ret=%d)\n", ok);
+}
+
+/**
+ * Continuation for the GNUNET_DHT_get_stop call, so that we don't shut
+ * down the peers without freeing memory associated with GET request.
+ */
+static void
+end_badly_cont (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
+{
+ die_task = GNUNET_SCHEDULER_NO_TASK;
+ GNUNET_TESTING_daemons_stop (pg, TIMEOUT, &finish_testing, NULL);
+}
+
+/**
+ * Check if the get_handle is being used, if so stop the request. Either
+ * way, schedule the end_badly_cont function which actually shuts down the
+ * test.
+ */
+static void
+end_badly (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
+{
+ die_task = GNUNET_SCHEDULER_NO_TASK;
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Failing test with error: `%s'!\n",
+ (char *) cls);
+ die_task = GNUNET_SCHEDULER_add_now (&end_badly_cont, NULL);
+ ok = 1;
+}
+
+
+static void
+on_lookup_result(void *cls, uint32_t rd_count,
+ const struct GNUNET_NAMESTORE_RecordData *rd)
+{
+ int i;
+ char* string_val;
+ const char* typename;
+
+ if (rd_count == 0)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "Lookup failed!\n");
+ ok = 2;
+ }
+ else
+ {
+ ok = 1;
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO, "name: %s\n", (char*)cls);
+ for (i=0; i<rd_count; i++)
+ {
+ typename = GNUNET_NAMESTORE_number_to_typename (rd[i].record_type);
+ string_val = GNUNET_NAMESTORE_value_to_string(rd[i].record_type,
+ rd[i].data,
+ rd[i].data_size);
+ printf("Got %s record: %s\n", typename, string_val);
+ if (0 == strcmp(string_val, TEST_IP))
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+ "%s correctly resolved to %s!\n", TEST_DOMAIN, string_val);
+ ok = 0;
+ }
+ }
+ }
+ GNUNET_GNS_disconnect(gh);
+ GNUNET_SCHEDULER_cancel(die_task);
+ die_task = GNUNET_SCHEDULER_NO_TASK;
+ GNUNET_TESTING_daemons_stop (pg, TIMEOUT, &finish_testing, NULL);
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Shutting down!\n");
+
+}
+
+static void
+commence_testing(void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
+{
+
+
+ gh = GNUNET_GNS_connect(alice_cfg);
+
+ GNUNET_GNS_lookup(gh, TEST_DOMAIN, GNUNET_GNS_RECORD_TYPE_A,
+ &on_lookup_result, TEST_DOMAIN);
+ die_task =
+ GNUNET_SCHEDULER_add_delayed (TIMEOUT, &end_badly, "from lookup");
+}
+
+
+/**
+ * This function is called whenever a connection attempt is finished between two of
+ * the started peers (started with GNUNET_TESTING_daemons_start). The total
+ * number of times this function is called should equal the number returned
+ * from the GNUNET_TESTING_connect_topology call.
+ *
+ * The emsg variable is NULL on success (peers connected), and non-NULL on
+ * failure (peers failed to connect).
+ */
+void
+daemon_connected (void *cls, const struct GNUNET_PeerIdentity *first,
+ const struct GNUNET_PeerIdentity *second, uint32_t distance,
+ const struct GNUNET_CONFIGURATION_Handle *first_cfg,
+ const struct GNUNET_CONFIGURATION_Handle *second_cfg,
+ struct GNUNET_TESTING_Daemon *first_daemon,
+ struct GNUNET_TESTING_Daemon *second_daemon,
+ const char *emsg)
+{
+ if (emsg == NULL)
+ {
+ total_connections++;
+#if VERBOSE
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+ "connected peer %s to peer %s, distance %u\n",
+ first_daemon->shortname, second_daemon->shortname, distance);
+#endif
+ }
+#if VERBOSE
+ else
+ {
+ failed_connections++;
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+ "Failed to connect peer %s to peer %s with error :\n%s\n",
+ first_daemon->shortname, second_daemon->shortname, emsg);
+ }
+#endif
+
+ if (total_connections == expected_connections)
+ {
+#if VERBOSE
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+ "Created %d total connections, which is our target number! Starting next phase of testing.\n",
+ total_connections);
+#endif
+ GNUNET_SCHEDULER_cancel (die_task);
+ die_task = GNUNET_SCHEDULER_NO_TASK;
+ //die_task =
+ // GNUNET_SCHEDULER_add_delayed (TIMEOUT, &end_badly, "from connect");
+
+ //commence_testing();
+
+ }
+ else if (total_connections + failed_connections == expected_connections)
+ {
+ GNUNET_SCHEDULER_cancel (die_task);
+ die_task =
+ GNUNET_SCHEDULER_add_now (&end_badly,
+ "from topology_callback (too many failed connections)");
+ }
+}
+
+void
+all_connected(void *cls, const char *emsg)
+{
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+ "Created all connections! Starting next phase of testing.\n");
+ GNUNET_SCHEDULER_add_delayed (ZONE_PUT_WAIT_TIME, &commence_testing, NULL);
+}
+
+void
+ns_create_cont(void *cls, int32_t s, const char *emsg)
+{
+ GNUNET_NAMESTORE_disconnect((struct GNUNET_NAMESTORE_Handle *)cls, 0);
+}
+
+static void
+daemon_started (void *cls, const struct GNUNET_PeerIdentity *id,
+ const struct GNUNET_CONFIGURATION_Handle *cfg,
+ struct GNUNET_TESTING_Daemon *d, const char *emsg)
+{
+ struct GNUNET_NAMESTORE_Handle *ns;
+ char* keyfile;
+ struct GNUNET_CRYPTO_RsaPrivateKey *key;
+ struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded pkey;
+ struct in_addr *web;
+ struct GNUNET_NAMESTORE_RecordData rd;
+
+ rd.flags = GNUNET_NAMESTORE_RF_AUTHORITY | GNUNET_NAMESTORE_RF_NONE;
+ rd.expiration = GNUNET_TIME_UNIT_FOREVER_ABS;
+
+ if (NULL == dave_daemon)
+ {
+ if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_filename (cfg, "gns",
+ "ZONEKEY",
+ &keyfile))
+ {
+ GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Failed to get key from cfg\n");
+ ok = -1;
+ return;
+ }
+ dave_daemon = d;
+
+ key = GNUNET_CRYPTO_rsa_key_create_from_file (keyfile);
+
+ GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "This is now dave\n");
+ ns = GNUNET_NAMESTORE_connect(cfg);
+
+ GNUNET_CRYPTO_rsa_key_get_public (key, &pkey);
+ GNUNET_CRYPTO_short_hash(&pkey, sizeof(pkey), &dave_hash);
+
+ web = GNUNET_malloc(sizeof(struct in_addr));
+ GNUNET_assert(1 == inet_pton (AF_INET, TEST_IP, web));
+ rd.data_size = sizeof(struct in_addr);
+ rd.data = web;
+ rd.record_type = GNUNET_GNS_RECORD_TYPE_A;
+
+ GNUNET_NAMESTORE_record_create (ns, key, "www", &rd, NULL, NULL);
+
+ rd.data_size = strlen(TEST_DAVE_PSEU);
+ rd.data = TEST_DAVE_PSEU;
+ rd.record_type = GNUNET_GNS_RECORD_PSEU;
+
+ GNUNET_NAMESTORE_record_create (ns, key, "+", &rd, ns_create_cont, ns);
+
+ GNUNET_CRYPTO_rsa_key_free(key);
+ GNUNET_free(keyfile);
+ GNUNET_free(web);
+
+ return;
+ }
+
+
+ if (NULL == bob_daemon)
+ {
+ if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_filename (cfg, "gns",
+ "ZONEKEY",
+ &keyfile))
+ {
+ GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Failed to get key from cfg\n");
+ ok = -1;
+ return;
+ }
+ bob_daemon = d;
+
+ key = GNUNET_CRYPTO_rsa_key_create_from_file (keyfile);
+
+ GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "This is now bob\n");
+ ns = GNUNET_NAMESTORE_connect(cfg);
+
+ GNUNET_CRYPTO_rsa_key_get_public (key, &pkey);
+ GNUNET_CRYPTO_short_hash(&pkey, sizeof(pkey), &bob_hash);
+
+ rd.data_size = sizeof(struct GNUNET_CRYPTO_ShortHashCode);
+ rd.data = &dave_hash;
+ rd.record_type = GNUNET_GNS_RECORD_PKEY;
+
+ GNUNET_NAMESTORE_record_create (ns, key, "buddy", &rd, ns_create_cont, ns);
+
+ GNUNET_CRYPTO_rsa_key_free(key);
+ GNUNET_free(keyfile);
+
+ return;
+ }
+
+
+
+ if (NULL == alice_daemon)
+ {
+
+ if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_filename (cfg, "gns",
+ "ZONEKEY",
+ &keyfile))
+ {
+ GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Failed to get key from cfg\n");
+ ok = -1;
+ return;
+ }
+ alice_daemon = d;
+ alice_cfg = cfg;
+
+ key = GNUNET_CRYPTO_rsa_key_create_from_file (keyfile);
+
+ GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "This is now alice\n");
+ ns = GNUNET_NAMESTORE_connect(cfg);
+
+ rd.data_size = sizeof(struct GNUNET_CRYPTO_ShortHashCode);
+ rd.data = &bob_hash;
+ rd.record_type = GNUNET_GNS_RECORD_PKEY;
+
+ GNUNET_NAMESTORE_record_create (ns, key, "bob", &rd, ns_create_cont, ns);
+
+ GNUNET_CRYPTO_rsa_key_free(key);
+ GNUNET_free(keyfile);
+
+ GNUNET_TESTING_connect_topology (pg, GNUNET_TESTING_TOPOLOGY_CLIQUE,
+ GNUNET_TESTING_TOPOLOGY_OPTION_ALL,
+ 0,
+ TIMEOUT,
+ 3,
+ &all_connected, NULL);
+ return;
+
+ }
+
+
+
+ GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "This is a random guy\n");
+}
+
+static void
+run (void *cls, char *const *args, const char *cfgfile,
+ const struct GNUNET_CONFIGURATION_Handle *cfg)
+{
+
+ /* Get path from configuration file */
+ if (GNUNET_YES !=
+ GNUNET_CONFIGURATION_get_value_string (cfg, "paths", "servicehome",
+ &test_directory))
+ {
+ ok = 404;
+ return;
+ }
+
+ GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "starting\n");
+
+ /* Get number of peers to start from configuration (should be two) */
+ if (GNUNET_SYSERR ==
+ GNUNET_CONFIGURATION_get_value_number (cfg, "testing", "num_peers",
+ &num_peers))
+ num_peers = DEFAULT_NUM_PEERS;
+
+ /* Set peers_left so we know when all peers started */
+ peers_left = num_peers;
+
+ bob_daemon = NULL;
+ dave_daemon = NULL;
+ alice_daemon = NULL;
+
+ pg = GNUNET_TESTING_daemons_start (cfg, TEST_NUM_PEERS, TEST_NUM_CON,
+ TEST_NUM_CON, TIMEOUT, NULL, NULL, &daemon_started, NULL,
+ &daemon_connected, NULL, NULL);
+
+ /* Set up a task to end testing if peer start fails */
+ die_task =
+ GNUNET_SCHEDULER_add_delayed (TIMEOUT, &end_badly,
+ "didn't start all daemons in reasonable amount of time!!!");
+
+ alice_online = 0;
+ bob_online = 0;
+ dave_online = 0;
+ expected_connections = 2;
+
+ /* Start alice */
+ //d1 = GNUNET_TESTING_daemon_start(cfg_alice, TIMEOUT, GNUNET_NO, NULL, NULL, 0,
+ // NULL, NULL, NULL, &alice_started, NULL);
+
+
+
+
+}
+
+static int
+check ()
+{
+ int ret;
+
+ /* Arguments for GNUNET_PROGRAM_run */
+ char *const argv[] = { "test-gns-twopeer", /* Name to give running binary */
+ "-c",
+ "test_gns_dht_default.conf", /* Config file to use */
+#if VERBOSE
+ "-L", "DEBUG",
+#endif
+ NULL
+ };
+ struct GNUNET_GETOPT_CommandLineOption options[] = {
+ GNUNET_GETOPT_OPTION_END
+ };
+ /* Run the run function as a new program */
+ ret =
+ GNUNET_PROGRAM_run ((sizeof (argv) / sizeof (char *)) - 1, argv,
+ "test-gns-threepeer", "nohelp", options, &run,
+ &ok);
+ if (ret != GNUNET_OK)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+ "`test-gns-threepeer': Failed with error code %d\n", ret);
+ }
+ return ok;
+}
+
+int
+main (int argc, char *argv[])
+{
+ int ret;
+
+ GNUNET_log_setup ("test-gns-threepeer",
+#if VERBOSE
+ "DEBUG",
+#else
+ "WARNING",
+#endif
+ NULL);
+ ret = check ();
+ /**
+ * Need to remove base directory, subdirectories taken care
+ * of by the testing framework.
+ */
+ return ret;
+}
+
+/* end of test_gns_threepeer.c */
diff --git a/src/gns/test_gns_max_queries.c b/src/gns/test_gns_max_queries.c
new file mode 100644
index 0000000..ad1743c
--- /dev/null
+++ b/src/gns/test_gns_max_queries.c
@@ -0,0 +1,381 @@
+/*
+ This file is part of GNUnet.
+ (C) 2009 Christian Grothoff (and other contributing authors)
+
+ GNUnet is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 3, or (at your
+ option) any later version.
+
+ GNUnet is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GNUnet; see the file COPYING. If not, write to the
+ Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+/**
+ * @file gns/test_gns_max_queries.c
+ * @brief base testcase for testing GNS background queries
+ * in particular query replacement and clean shutdown
+ */
+#include "platform.h"
+#include "gnunet_testing_lib.h"
+#include "gnunet_core_service.h"
+#include "block_dns.h"
+#include "gns.h"
+#include "gnunet_signatures.h"
+#include "gnunet_namestore_service.h"
+#include "gnunet_dnsparser_lib.h"
+#include "gnunet_gns_service.h"
+
+/* DEFINES */
+#define VERBOSE GNUNET_YES
+
+/* Timeout for entire testcase */
+#define TIMEOUT GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_SECONDS, 20)
+
+/* If number of peers not in config file, use this number */
+#define DEFAULT_NUM_PEERS 2
+
+/* test records to resolve */
+#define TEST_DOMAIN "www.gnunet"
+#define TEST_DOMAIN_NACK "doesnotexist.bob.gnunet"
+#define TEST_IP "127.0.0.1"
+#define TEST_RECORD_NAME "www"
+#define TEST_ADDITIONAL_LOOKUPS 5
+#define TEST_AUTHORITY_NAME "bob"
+
+#define KEYFILE_BOB "../namestore/zonefiles/HGU0A0VCU334DN7F2I9UIUMVQMM7JMSD142LIMNUGTTV9R0CF4EG.zkey"
+
+/* Globals */
+
+/**
+ * Directory to store temp data in, defined in config file
+ */
+static char *test_directory;
+
+static struct GNUNET_TESTING_PeerGroup *pg;
+
+/* Task handle to use to schedule test failure */
+GNUNET_SCHEDULER_TaskIdentifier die_task;
+
+/* Global return value (0 for success, anything else for failure) */
+static int ok;
+
+static struct GNUNET_NAMESTORE_Handle *namestore_handle;
+
+static struct GNUNET_GNS_Handle *gns_handle;
+
+const struct GNUNET_CONFIGURATION_Handle *cfg;
+
+static unsigned long long max_parallel_lookups;
+
+/**
+ * Check whether peers successfully shut down.
+ */
+void
+shutdown_callback (void *cls, const char *emsg)
+{
+ if (emsg != NULL)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Error on shutdown! ret=%d\n", ok);
+ if (ok == 0)
+ ok = 2;
+ }
+
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO, "done(ret=%d)!\n", ok);
+}
+
+static void
+on_lookup_result_dummy(void *cls, uint32_t rd_count,
+ const struct GNUNET_NAMESTORE_RecordData *rd)
+{
+ if (rd_count != 0)
+ {
+ GNUNET_log(GNUNET_ERROR_TYPE_ERROR,
+ "Got %d results from dummy lookup! Wanted: 0\n",
+ rd_count);
+ ok = -1;
+ }
+}
+
+static void
+on_lookup_result(void *cls, uint32_t rd_count,
+ const struct GNUNET_NAMESTORE_RecordData *rd)
+{
+ struct in_addr a;
+ int i;
+ char* addr;
+
+ if (rd_count == 0)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "Lookup failed, rp_filtering?\n");
+ ok = 2;
+ }
+ else
+ {
+ ok = 1;
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO, "name: %s\n", (char*)cls);
+ for (i=0; i<rd_count; i++)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO, "type: %d\n", rd[i].record_type);
+ if (rd[i].record_type == GNUNET_GNS_RECORD_TYPE_A)
+ {
+ memcpy(&a, rd[i].data, sizeof(a));
+ addr = inet_ntoa(a);
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO, "address: %s\n", addr);
+ if (0 == strcmp(addr, TEST_IP))
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+ "%s correctly resolved to %s!\n", TEST_DOMAIN, addr);
+ ok = 0;
+ }
+ }
+ else
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "No resolution!\n");
+ }
+ }
+ }
+ GNUNET_GNS_disconnect(gns_handle);
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Shutting down peer1!\n");
+ //GNUNET_TESTING_daemon_stop (d1, TIMEOUT, &shutdown_callback, NULL,
+ // GNUNET_YES, GNUNET_NO);
+ GNUNET_TESTING_daemons_stop (pg, TIMEOUT, &shutdown_callback, NULL);
+}
+
+
+/**
+ * Function scheduled to be run on the successful start of services
+ * tries to look up the dns record for TEST_DOMAIN
+ */
+static void
+commence_testing (void *cls, int32_t success, const char *emsg)
+{
+ int i;
+ char lookup_name[MAX_DNS_NAME_LENGTH];
+
+ GNUNET_NAMESTORE_disconnect(namestore_handle, GNUNET_YES);
+
+ gns_handle = GNUNET_GNS_connect(cfg);
+
+ if (NULL == gns_handle)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "Failed to connect to GNS!\n");
+ ok = 2;
+ }
+
+
+ /* Now lookup some non existing records */
+ for (i=0; i<max_parallel_lookups+TEST_ADDITIONAL_LOOKUPS; i++)
+ {
+ GNUNET_snprintf(lookup_name,
+ MAX_DNS_NAME_LENGTH,
+ "www.doesnotexist-%d.bob.gnunet", i);
+ GNUNET_GNS_lookup(gns_handle, lookup_name, GNUNET_GNS_RECORD_TYPE_A,
+ &on_lookup_result_dummy, NULL);
+ }
+
+ GNUNET_GNS_lookup(gns_handle, TEST_DOMAIN, GNUNET_GNS_RECORD_TYPE_A,
+ &on_lookup_result, TEST_DOMAIN);
+}
+
+
+/**
+ * Continuation for the GNUNET_DHT_get_stop call, so that we don't shut
+ * down the peers without freeing memory associated with GET request.
+ */
+static void
+end_badly_cont (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
+{
+
+ if (pg != NULL)
+ GNUNET_TESTING_daemons_stop (pg, TIMEOUT, &shutdown_callback, NULL);
+ GNUNET_SCHEDULER_cancel (die_task);
+}
+
+/**
+ * Check if the get_handle is being used, if so stop the request. Either
+ * way, schedule the end_badly_cont function which actually shuts down the
+ * test.
+ */
+static void
+end_badly (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
+{
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Failing test with error: `%s'!\n",
+ (char *) cls);
+ GNUNET_SCHEDULER_add_now (&end_badly_cont, NULL);
+ ok = 1;
+}
+
+static void
+do_lookup(void *cls, const struct GNUNET_PeerIdentity *id,
+ const struct GNUNET_CONFIGURATION_Handle *_cfg,
+ struct GNUNET_TESTING_Daemon *d, const char *emsg)
+{
+ struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded alice_pkey;
+ struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded bob_pkey;
+ struct GNUNET_CRYPTO_RsaPrivateKey *alice_key;
+ struct GNUNET_CRYPTO_RsaPrivateKey *bob_key;
+ char* alice_keyfile;
+ struct GNUNET_CRYPTO_ShortHashCode bob_hash;
+
+ cfg = _cfg;
+
+ GNUNET_SCHEDULER_cancel (die_task);
+
+ /* put records into namestore */
+ namestore_handle = GNUNET_NAMESTORE_connect(cfg);
+ if (NULL == namestore_handle)
+ {
+ GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Failed to connect to namestore\n");
+ ok = -1;
+ return;
+ }
+
+ if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_filename (cfg, "gns",
+ "ZONEKEY",
+ &alice_keyfile))
+ {
+ GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Failed to get key from cfg\n");
+ ok = -1;
+ return;
+ }
+
+ if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_number (cfg, "gns",
+ "MAX_PARALLEL_BACKGROUND_QUERIES",
+ &max_parallel_lookups))
+ {
+ GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Failed to get max queries from cfg\n");
+ ok = -1;
+ GNUNET_free (alice_keyfile);
+ return;
+ }
+
+ alice_key = GNUNET_CRYPTO_rsa_key_create_from_file (alice_keyfile);
+ bob_key = GNUNET_CRYPTO_rsa_key_create_from_file (KEYFILE_BOB);
+
+ GNUNET_CRYPTO_rsa_key_get_public (alice_key, &alice_pkey);
+ GNUNET_CRYPTO_rsa_key_get_public (bob_key, &bob_pkey);
+
+ GNUNET_free(alice_keyfile);
+
+ struct GNUNET_NAMESTORE_RecordData rd;
+ char* ip = TEST_IP;
+ struct in_addr *web = GNUNET_malloc(sizeof(struct in_addr));
+ rd.expiration = GNUNET_TIME_UNIT_FOREVER_ABS;
+ GNUNET_assert(1 == inet_pton (AF_INET, ip, web));
+ rd.data_size = sizeof(struct in_addr);
+ rd.data = web;
+ rd.record_type = GNUNET_DNSPARSER_TYPE_A;
+
+ GNUNET_NAMESTORE_record_create (namestore_handle,
+ alice_key,
+ TEST_RECORD_NAME,
+ &rd,
+ NULL,
+ NULL);
+
+ GNUNET_CRYPTO_short_hash(&bob_pkey, sizeof(bob_pkey), &bob_hash);
+ rd.data_size = sizeof(struct GNUNET_CRYPTO_ShortHashCode);
+ rd.data = &bob_hash;
+ rd.record_type = GNUNET_GNS_RECORD_PKEY;
+
+ GNUNET_NAMESTORE_record_create (namestore_handle,
+ alice_key,
+ TEST_AUTHORITY_NAME,
+ &rd,
+ &commence_testing,
+ NULL);
+
+ GNUNET_CRYPTO_rsa_key_free(alice_key);
+ GNUNET_CRYPTO_rsa_key_free(bob_key);
+ GNUNET_free(web);
+
+}
+
+static void
+run (void *cls, char *const *args, const char *cfgfile,
+ const struct GNUNET_CONFIGURATION_Handle *c)
+{
+ cfg = c;
+ /* Get path from configuration file */
+ if (GNUNET_YES !=
+ GNUNET_CONFIGURATION_get_value_string (cfg, "paths", "servicehome",
+ &test_directory))
+ {
+ ok = 404;
+ return;
+ }
+
+
+ /* Set up a task to end testing if peer start fails */
+ die_task =
+ GNUNET_SCHEDULER_add_delayed (TIMEOUT, &end_badly,
+ "didn't start all daemons in reasonable amount of time!!!");
+
+ /* Start alice */
+ //d1 = GNUNET_TESTING_daemon_start(cfg, TIMEOUT, GNUNET_NO, NULL, NULL, 0,
+ // NULL, NULL, NULL, &do_lookup, NULL);
+ pg = GNUNET_TESTING_daemons_start(cfg, 1, 1, 1, TIMEOUT,
+ NULL, NULL, &do_lookup, NULL,
+ NULL, NULL, NULL);
+}
+
+static int
+check ()
+{
+ int ret;
+
+ /* Arguments for GNUNET_PROGRAM_run */
+ char *const argv[] = { "test-gns-max-queries", /* Name to give running binary */
+ "-c",
+ "test_gns_simple_lookup.conf", /* Config file to use */
+#if VERBOSE
+ "-L", "DEBUG",
+#endif
+ NULL
+ };
+ struct GNUNET_GETOPT_CommandLineOption options[] = {
+ GNUNET_GETOPT_OPTION_END
+ };
+ /* Run the run function as a new program */
+ ret =
+ GNUNET_PROGRAM_run ((sizeof (argv) / sizeof (char *)) - 1, argv,
+ "test-gns-max-queries", "nohelp", options, &run,
+ &ok);
+ if (ret != GNUNET_OK)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+ "`test-gns-simple-lookup': Failed with error code %d\n", ret);
+ }
+ return ok;
+}
+
+int
+main (int argc, char *argv[])
+{
+ int ret;
+
+ GNUNET_log_setup ("test-gns-simple-lookup",
+#if VERBOSE
+ "DEBUG",
+#else
+ "WARNING",
+#endif
+ NULL);
+ ret = check ();
+ /**
+ * Need to remove base directory, subdirectories taken care
+ * of by the testing framework.
+ */
+ return ret;
+}
+
+/* end of test_gns_twopeer.c */
diff --git a/src/gns/test_gns_pseu_shorten.c b/src/gns/test_gns_pseu_shorten.c
new file mode 100644
index 0000000..3c2d204
--- /dev/null
+++ b/src/gns/test_gns_pseu_shorten.c
@@ -0,0 +1,643 @@
+/*
+ This file is part of GNUnet.
+ (C) 2009 Christian Grothoff (and other contributing authors)
+
+ GNUnet is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 3, or (at your
+ option) any later version.
+
+ GNUnet is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GNUnet; see the file COPYING. If not, write to the
+ Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+/**
+ * @file gns/test_gns_pseu_shorten.c
+ * @brief base testcase for testing on the fly pseu import and shorten
+ *
+ */
+#include "platform.h"
+#include "gnunet_testing_lib.h"
+#include "gnunet_core_service.h"
+#include "block_gns.h"
+#include "gnunet_signatures.h"
+#include "gnunet_namestore_service.h"
+#include "../namestore/namestore.h"
+#include "gnunet_dnsparser_lib.h"
+#include "gnunet_dht_service.h"
+#include "gnunet_gns_service.h"
+
+/* DEFINES */
+#define VERBOSE GNUNET_YES
+
+/* Timeout for entire testcase */
+#define TIMEOUT GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_SECONDS, 5)
+
+/* If number of peers not in config file, use this number */
+#define DEFAULT_NUM_PEERS 2
+
+/* test records to resolve */
+#define TEST_DOMAIN "www.alice.bob.gnunet"
+#define TEST_IP "127.0.0.1"
+#define TEST_RECORD_NAME "www"
+
+#define TEST_AUTHORITY_BOB "bob"
+#define TEST_AUTHORITY_ALICE "alice"
+#define TEST_PSEU_ALICE "carol"
+#define TEST_EXPECTED_RESULT "www.carol.gnunet"
+
+#define DHT_OPERATION_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 30)
+
+#define KEYFILE_BOB "../namestore/zonefiles/HGU0A0VCU334DN7F2I9UIUMVQMM7JMSD142LIMNUGTTV9R0CF4EG.zkey"
+#define KEYFILE_ALICE "../namestore/zonefiles/N0UJMP015AFUNR2BTNM3FKPBLG38913BL8IDMCO2H0A1LIB81960.zkey"
+
+/* Globals */
+
+/**
+ * Directory to store temp data in, defined in config file
+ */
+static char *test_directory;
+
+static struct GNUNET_TESTING_PeerGroup *pg;
+
+/* Task handle to use to schedule test failure */
+static GNUNET_SCHEDULER_TaskIdentifier die_task;
+
+static GNUNET_SCHEDULER_TaskIdentifier disco_task;
+
+/* Global return value (0 for success, anything else for failure) */
+static int ok;
+
+static struct GNUNET_NAMESTORE_Handle *namestore_handle;
+
+static struct GNUNET_GNS_Handle *gns_handle;
+
+static struct GNUNET_DHT_Handle *dht_handle;
+
+const struct GNUNET_CONFIGURATION_Handle *cfg;
+
+struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded alice_pkey;
+struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded bob_pkey;
+struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded our_pkey;
+struct GNUNET_CRYPTO_RsaPrivateKey *alice_key;
+struct GNUNET_CRYPTO_RsaPrivateKey *bob_key;
+struct GNUNET_CRYPTO_RsaPrivateKey *our_key;
+struct GNUNET_CRYPTO_ShortHashCode alice_hash;
+struct GNUNET_CRYPTO_ShortHashCode bob_hash;
+
+/**
+ * Check whether peers successfully shut down.
+ */
+void
+shutdown_callback (void *cls, const char *emsg)
+{
+ if (disco_task != GNUNET_SCHEDULER_NO_TASK)
+ {
+ disco_task = GNUNET_SCHEDULER_NO_TASK;
+ GNUNET_SCHEDULER_cancel(disco_task);
+ GNUNET_DHT_disconnect(dht_handle);
+ dht_handle = NULL;
+ }
+
+ if (emsg != NULL)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Error on shutdown! ret=%d\n", ok);
+ if (ok == 0)
+ ok = 2;
+ }
+
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO, "done(ret=%d)!\n", ok);
+}
+
+static void
+disco_dht(void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
+{
+ disco_task = GNUNET_SCHEDULER_NO_TASK;
+ GNUNET_DHT_disconnect(dht_handle);
+ dht_handle = NULL;
+}
+
+/**
+ * Called when gns shorten finishes
+ */
+static void
+process_shorten_result(void* cls, const char* sname)
+{
+ GNUNET_GNS_disconnect(gns_handle);
+ //GNUNET_SCHEDULER_add_now(disco_dht, NULL);
+ ok = 0;
+
+ if (sname == NULL)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "shorten test failed!\n");
+ ok = 1;
+ }
+ else
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "%s shortened to %s\n", (char*)cls, sname);
+ if (0 != strcmp(sname, TEST_EXPECTED_RESULT))
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "shorten test failed! (wanted: %s got: %s\n",
+ (char*)cls, sname);
+ ok = 1;
+ }
+
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "shorten test succeeded!\n");
+ }
+
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Shutting down peer1!\n");
+ GNUNET_TESTING_daemons_stop (pg, TIMEOUT, &shutdown_callback, NULL);
+}
+
+static void
+do_shorten(void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
+{
+ GNUNET_GNS_shorten(gns_handle, TEST_DOMAIN, &process_shorten_result,
+TEST_DOMAIN);
+}
+
+static void
+on_lookup_result(void *cls, uint32_t rd_count,
+ const struct GNUNET_NAMESTORE_RecordData *rd)
+{
+ struct in_addr a;
+ int i;
+ char* addr;
+
+ if (rd_count == 0)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "Lookup failed, rp_filtering?\n");
+ ok = 2;
+ }
+ else
+ {
+ ok = 1;
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO, "name: %s\n", (char*)cls);
+ for (i=0; i<rd_count; i++)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO, "type: %d\n", rd[i].record_type);
+ if (rd[i].record_type == GNUNET_GNS_RECORD_TYPE_A)
+ {
+ memcpy(&a, rd[i].data, sizeof(a));
+ addr = inet_ntoa(a);
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO, "address: %s\n", addr);
+ if (0 == strcmp(addr, TEST_IP))
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+ "%s correctly resolved to %s!\n", TEST_DOMAIN, addr);
+ ok = 0;
+ }
+ }
+ else
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "No resolution!\n");
+ }
+ }
+ }
+
+ GNUNET_SCHEDULER_add_delayed (TIMEOUT, &do_shorten, NULL);
+}
+
+
+/**
+ * Function scheduled to be run on the successful start of services
+ * tries to look up the dns record for TEST_DOMAIN
+ */
+static void
+commence_testing (void *cls, int success)
+{
+ GNUNET_SCHEDULER_add_now(disco_dht, NULL);
+ //GNUNET_DHT_disconnect(dht_handle);
+
+ GNUNET_CRYPTO_rsa_key_free(our_key);
+ GNUNET_CRYPTO_rsa_key_free(bob_key);
+ GNUNET_CRYPTO_rsa_key_free(alice_key);
+
+ gns_handle = GNUNET_GNS_connect(cfg);
+
+ if (NULL == gns_handle)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "Failed to connect to GNS!\n");
+ }
+
+ GNUNET_GNS_lookup(gns_handle, TEST_DOMAIN, GNUNET_GNS_RECORD_TYPE_A,
+ &on_lookup_result, TEST_DOMAIN);
+}
+
+/**
+ * Continuation for the GNUNET_DHT_get_stop call, so that we don't shut
+ * down the peers without freeing memory associated with GET request.
+ */
+static void
+end_badly (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
+{
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Failing test with error: `%s'!\n",
+ (char *) cls);
+ ok = 1;
+
+ if (disco_task != GNUNET_SCHEDULER_NO_TASK)
+ {
+ disco_task = GNUNET_SCHEDULER_NO_TASK;
+ GNUNET_SCHEDULER_cancel(disco_task);
+ GNUNET_DHT_disconnect(dht_handle);
+ dht_handle = NULL;
+ }
+ if (pg != NULL)
+ GNUNET_TESTING_daemons_stop (pg, TIMEOUT, &shutdown_callback, NULL);
+ GNUNET_SCHEDULER_cancel (die_task);
+}
+
+static void
+put_pseu_dht(void *cls, int success)
+{
+ struct GNSNameRecordBlock *nrb;
+ struct GNUNET_CRYPTO_ShortHashCode name_hash;
+ struct GNUNET_CRYPTO_ShortHashCode zone_hash;
+ GNUNET_HashCode xor_hash;
+ GNUNET_HashCode name_hash_double;
+ GNUNET_HashCode zone_hash_double;
+ uint32_t rd_payload_length;
+ char* nrb_data = NULL;
+ struct GNUNET_CRYPTO_RsaSignature *sig;
+ struct GNUNET_NAMESTORE_RecordData rd;
+
+ rd.expiration = GNUNET_TIME_UNIT_FOREVER_ABS;
+ rd.data_size = strlen(TEST_PSEU_ALICE)+1;
+ rd.data = TEST_PSEU_ALICE;
+ rd.record_type = GNUNET_GNS_RECORD_PSEU;
+
+ sig = GNUNET_NAMESTORE_create_signature(alice_key,
+ GNUNET_TIME_UNIT_FOREVER_ABS,
+ "+",
+ &rd, 1);
+ rd_payload_length = GNUNET_NAMESTORE_records_get_size (1, &rd);
+ nrb = GNUNET_malloc(rd_payload_length + strlen("+") + 1
+ + sizeof(struct GNSNameRecordBlock));
+ nrb->signature = *sig;
+ nrb->public_key = alice_pkey;
+ nrb->rd_count = htonl(1);
+ memset(&nrb[1], 0, strlen("+") + 1);
+ strcpy((char*)&nrb[1], "+");
+ nrb_data = (char*)&nrb[1];
+ nrb_data += strlen("+") + 1;
+
+ if (-1 == GNUNET_NAMESTORE_records_serialize (1,
+ &rd,
+ rd_payload_length,
+ nrb_data))
+ {
+ GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Record serialization failed!\n");
+ ok = 3;
+ GNUNET_DHT_disconnect(dht_handle);
+
+
+ GNUNET_CRYPTO_rsa_key_free(our_key);
+ GNUNET_CRYPTO_rsa_key_free(bob_key);
+ GNUNET_CRYPTO_rsa_key_free(alice_key);
+ GNUNET_free(sig);
+ GNUNET_free (nrb);
+ return;
+ }
+ GNUNET_CRYPTO_short_hash("+", strlen("+"), &name_hash);
+ GNUNET_CRYPTO_short_hash(&alice_pkey,
+ sizeof(struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded),
+ &zone_hash);
+
+ GNUNET_CRYPTO_short_hash_double(&name_hash, &name_hash_double);
+ GNUNET_CRYPTO_short_hash_double(&zone_hash, &zone_hash_double);
+ GNUNET_CRYPTO_hash_xor(&zone_hash_double, &name_hash_double, &xor_hash);
+
+ rd_payload_length += sizeof(struct GNSNameRecordBlock) +
+ strlen("+") + 1;
+
+ GNUNET_DHT_put (dht_handle, &xor_hash,
+ 0,
+ GNUNET_DHT_RO_NONE,
+ GNUNET_BLOCK_TYPE_GNS_NAMERECORD,
+ rd_payload_length,
+ (char*)nrb,
+ rd.expiration,
+ DHT_OPERATION_TIMEOUT,
+ &commence_testing,
+ NULL);
+
+ GNUNET_free(sig);
+ GNUNET_free (nrb);
+}
+
+static void
+put_www_dht(void *cls, int success)
+{
+ struct GNSNameRecordBlock *nrb;
+ struct GNUNET_CRYPTO_ShortHashCode name_hash;
+ struct GNUNET_CRYPTO_ShortHashCode zone_hash;
+ GNUNET_HashCode xor_hash;
+ GNUNET_HashCode name_hash_double;
+ GNUNET_HashCode zone_hash_double;
+ uint32_t rd_payload_length;
+ char* nrb_data = NULL;
+ struct GNUNET_CRYPTO_RsaSignature *sig;
+ struct GNUNET_NAMESTORE_RecordData rd;
+ char* ip = TEST_IP;
+ struct in_addr *web = GNUNET_malloc(sizeof(struct in_addr));
+
+ rd.expiration = GNUNET_TIME_UNIT_FOREVER_ABS;
+ GNUNET_assert(1 == inet_pton (AF_INET, ip, web));
+ rd.data_size = sizeof(struct in_addr);
+ rd.data = web;
+ rd.record_type = GNUNET_DNSPARSER_TYPE_A;
+
+ sig = GNUNET_NAMESTORE_create_signature(alice_key,
+ GNUNET_TIME_UNIT_FOREVER_ABS,
+ TEST_RECORD_NAME,
+ &rd, 1);
+ rd_payload_length = GNUNET_NAMESTORE_records_get_size (1, &rd);
+ nrb = GNUNET_malloc(rd_payload_length + strlen(TEST_RECORD_NAME) + 1
+ + sizeof(struct GNSNameRecordBlock));
+ nrb->signature = *sig;
+ nrb->public_key = alice_pkey;
+ nrb->rd_count = htonl(1);
+ memset(&nrb[1], 0, strlen(TEST_RECORD_NAME) + 1);
+ strcpy((char*)&nrb[1], TEST_RECORD_NAME);
+ nrb_data = (char*)&nrb[1];
+ nrb_data += strlen(TEST_RECORD_NAME) + 1;
+
+ if (-1 == GNUNET_NAMESTORE_records_serialize (1,
+ &rd,
+ rd_payload_length,
+ nrb_data))
+ {
+ GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Record serialization failed!\n");
+ ok = 3;
+ GNUNET_DHT_disconnect(dht_handle);
+
+ GNUNET_CRYPTO_rsa_key_free(our_key);
+ GNUNET_CRYPTO_rsa_key_free(bob_key);
+ GNUNET_CRYPTO_rsa_key_free(alice_key);
+ GNUNET_free(web);
+ GNUNET_free (nrb);
+ return;
+ }
+ GNUNET_CRYPTO_short_hash(TEST_RECORD_NAME, strlen(TEST_RECORD_NAME), &name_hash);
+ GNUNET_CRYPTO_short_hash(&alice_pkey,
+ sizeof(struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded),
+ &zone_hash);
+ GNUNET_CRYPTO_short_hash_double(&zone_hash, &zone_hash_double);
+ GNUNET_CRYPTO_short_hash_double(&name_hash, &name_hash_double);
+ GNUNET_CRYPTO_hash_xor(&zone_hash_double, &name_hash_double, &xor_hash);
+
+ rd_payload_length += sizeof(struct GNSNameRecordBlock) +
+ strlen(TEST_RECORD_NAME) + 1;
+
+ GNUNET_DHT_put (dht_handle, &xor_hash,
+ 0,
+ GNUNET_DHT_RO_NONE,
+ GNUNET_BLOCK_TYPE_GNS_NAMERECORD,
+ rd_payload_length,
+ (char*)nrb,
+ rd.expiration,
+ DHT_OPERATION_TIMEOUT,
+ &put_pseu_dht,
+ NULL);
+
+ GNUNET_free(web);
+ GNUNET_free (nrb);
+}
+
+
+static void
+put_pkey_dht(void *cls, int32_t success, const char *emsg)
+{
+ struct GNSNameRecordBlock *nrb;
+ struct GNUNET_CRYPTO_ShortHashCode name_hash;
+ struct GNUNET_CRYPTO_ShortHashCode zone_hash;
+ GNUNET_HashCode xor_hash;
+ GNUNET_HashCode name_hash_double;
+ GNUNET_HashCode zone_hash_double;
+ uint32_t rd_payload_length;
+ char* nrb_data = NULL;
+ struct GNUNET_CRYPTO_RsaSignature *sig;
+ struct GNUNET_NAMESTORE_RecordData rd;
+
+ rd.expiration = GNUNET_TIME_UNIT_FOREVER_ABS;
+ rd.data_size = sizeof(struct GNUNET_CRYPTO_ShortHashCode);
+ rd.data = &alice_hash;
+ rd.record_type = GNUNET_GNS_RECORD_PKEY;
+
+ sig = GNUNET_NAMESTORE_create_signature(bob_key,
+ GNUNET_TIME_UNIT_FOREVER_ABS,
+ TEST_AUTHORITY_ALICE,
+ &rd,
+ 1);
+
+ rd_payload_length = GNUNET_NAMESTORE_records_get_size (1, &rd);
+ nrb = GNUNET_malloc(rd_payload_length + strlen(TEST_AUTHORITY_ALICE) + 1
+ + sizeof(struct GNSNameRecordBlock));
+ nrb->signature = *sig;
+ nrb->public_key = bob_pkey;
+ nrb->rd_count = htonl(1);
+ memset(&nrb[1], 0, strlen(TEST_AUTHORITY_ALICE) + 1);
+ strcpy((char*)&nrb[1], TEST_AUTHORITY_ALICE);
+ nrb_data = (char*)&nrb[1];
+ nrb_data += strlen(TEST_AUTHORITY_ALICE) + 1;
+
+ if (-1 == GNUNET_NAMESTORE_records_serialize (1,
+ &rd,
+ rd_payload_length,
+ nrb_data))
+ {
+ GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Record serialization failed!\n");
+ ok = 3;
+
+ GNUNET_CRYPTO_rsa_key_free(our_key);
+ GNUNET_CRYPTO_rsa_key_free(bob_key);
+ GNUNET_CRYPTO_rsa_key_free(alice_key);
+ GNUNET_free(sig);
+ GNUNET_free (nrb);
+ return;
+ }
+
+
+ GNUNET_CRYPTO_short_hash(TEST_AUTHORITY_ALICE,
+ strlen(TEST_AUTHORITY_ALICE), &name_hash);
+ GNUNET_CRYPTO_short_hash(&bob_pkey,
+ sizeof(struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded),
+ &zone_hash);
+ GNUNET_CRYPTO_short_hash_double(&zone_hash, &zone_hash_double);
+ GNUNET_CRYPTO_short_hash_double(&name_hash, &name_hash_double);
+ GNUNET_CRYPTO_hash_xor(&zone_hash_double, &name_hash_double, &xor_hash);
+
+ rd_payload_length += sizeof(struct GNSNameRecordBlock) +
+ strlen(TEST_AUTHORITY_ALICE) + 1;
+ GNUNET_DHT_put (dht_handle, &xor_hash,
+ 0,
+ GNUNET_DHT_RO_NONE,
+ GNUNET_BLOCK_TYPE_GNS_NAMERECORD,
+ rd_payload_length,
+ (char*)nrb,
+ rd.expiration,
+ DHT_OPERATION_TIMEOUT,
+ &put_www_dht,
+ NULL);
+ GNUNET_NAMESTORE_disconnect(namestore_handle, GNUNET_NO);
+ GNUNET_free (nrb);
+}
+
+static void
+do_lookup(void *cls, const struct GNUNET_PeerIdentity *id,
+ const struct GNUNET_CONFIGURATION_Handle *_cfg,
+ struct GNUNET_TESTING_Daemon *d, const char *emsg)
+{
+
+
+ char* our_keyfile;
+
+ cfg = _cfg;
+
+ GNUNET_SCHEDULER_cancel (die_task);
+
+ /* put records into namestore */
+ namestore_handle = GNUNET_NAMESTORE_connect(cfg);
+ if (NULL == namestore_handle)
+ {
+ GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Failed to connect to namestore\n");
+ ok = -1;
+ return;
+ }
+
+ /* dht */
+ dht_handle = GNUNET_DHT_connect(cfg, 1);
+ if (NULL == dht_handle)
+ {
+ GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Failed to connect to dht\n");
+ ok = -1;
+ return;
+ }
+
+ if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_filename (cfg, "gns",
+ "ZONEKEY",
+ &our_keyfile))
+ {
+ GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Failed to get key from cfg\n");
+ ok = -1;
+ return;
+ }
+
+ our_key = GNUNET_CRYPTO_rsa_key_create_from_file (our_keyfile);
+ bob_key = GNUNET_CRYPTO_rsa_key_create_from_file (KEYFILE_BOB);
+ alice_key = GNUNET_CRYPTO_rsa_key_create_from_file (KEYFILE_ALICE);
+
+ GNUNET_free(our_keyfile);
+
+ GNUNET_CRYPTO_rsa_key_get_public (our_key, &our_pkey);
+ GNUNET_CRYPTO_rsa_key_get_public (bob_key, &bob_pkey);
+ GNUNET_CRYPTO_rsa_key_get_public (alice_key, &alice_pkey);
+ GNUNET_CRYPTO_short_hash(&bob_pkey, sizeof(bob_pkey), &bob_hash);
+ GNUNET_CRYPTO_short_hash(&alice_pkey, sizeof(alice_pkey), &alice_hash);
+
+ struct GNUNET_NAMESTORE_RecordData rd;
+ rd.expiration = GNUNET_TIME_UNIT_FOREVER_ABS;
+ rd.data_size = sizeof(struct GNUNET_CRYPTO_ShortHashCode);
+ rd.data = &bob_hash;
+ rd.record_type = GNUNET_GNS_RECORD_PKEY;
+
+ GNUNET_NAMESTORE_record_create (namestore_handle,
+ our_key,
+ TEST_AUTHORITY_BOB,
+ &rd,
+ &put_pkey_dht,
+ NULL);
+
+
+}
+
+static void
+run (void *cls, char *const *args, const char *cfgfile,
+ const struct GNUNET_CONFIGURATION_Handle *c)
+{
+ cfg = c;
+ /* Get path from configuration file */
+ if (GNUNET_YES !=
+ GNUNET_CONFIGURATION_get_value_string (cfg, "paths", "servicehome",
+ &test_directory))
+ {
+ ok = 404;
+ return;
+ }
+
+
+ /* Set up a task to end testing if peer start fails */
+ die_task =
+ GNUNET_SCHEDULER_add_delayed (TIMEOUT, &end_badly,
+ "didn't start all daemons in reasonable amount of time!!!");
+
+ /* Start alice */
+ //d1 = GNUNET_TESTING_daemon_start(cfg, TIMEOUT, GNUNET_NO, NULL, NULL, 0,
+ // NULL, NULL, NULL, &do_lookup, NULL);
+ pg = GNUNET_TESTING_daemons_start(cfg, 1, 1, 1, TIMEOUT,
+ NULL, NULL, &do_lookup, NULL,
+ NULL, NULL, NULL);
+}
+
+static int
+check ()
+{
+ int ret;
+
+ /* Arguments for GNUNET_PROGRAM_run */
+ char *const argv[] = { "test-gns-pseu-shorten", /* Name to give running binary */
+ "-c",
+ "test_gns_simple_lookup.conf", /* Config file to use */
+#if VERBOSE
+ "-L", "DEBUG",
+#endif
+ NULL
+ };
+ struct GNUNET_GETOPT_CommandLineOption options[] = {
+ GNUNET_GETOPT_OPTION_END
+ };
+ /* Run the run function as a new program */
+ ret =
+ GNUNET_PROGRAM_run ((sizeof (argv) / sizeof (char *)) - 1, argv,
+ "test-gns-pseu-shorten", "nohelp", options, &run,
+ &ok);
+ if (ret != GNUNET_OK)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+ "`test-gns-pseu-shorten': Failed with error code %d\n", ret);
+ }
+ return ok;
+}
+
+int
+main (int argc, char *argv[])
+{
+ int ret;
+
+ GNUNET_log_setup ("test-gns-pseu-shorten",
+#if VERBOSE
+ "DEBUG",
+#else
+ "WARNING",
+#endif
+ NULL);
+ ret = check ();
+ /**
+ * Need to remove base directory, subdirectories taken care
+ * of by the testing framework.
+ */
+ return ret;
+}
+
+/* end of test_gns_twopeer.c */
diff --git a/src/gns/test_gns_simple_delegated_lookup.c b/src/gns/test_gns_simple_delegated_lookup.c
new file mode 100644
index 0000000..36fb969
--- /dev/null
+++ b/src/gns/test_gns_simple_delegated_lookup.c
@@ -0,0 +1,355 @@
+/*
+ This file is part of GNUnet.
+ (C) 2009 Christian Grothoff (and other contributing authors)
+
+ GNUnet is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 3, or (at your
+ option) any later version.
+
+ GNUnet is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GNUnet; see the file COPYING. If not, write to the
+ Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+/**
+ * @file gns/test_gns_twopeer.c
+ * @brief base testcase for testing DHT service with
+ * two running peers.
+ *
+ * This testcase starts peers using the GNUNET_TESTING_daemons_start
+ * function call. On peer start, connects to the peers DHT service
+ * by calling GNUNET_DHT_connected. Once notified about all peers
+ * being started (by the peers_started_callback function), calls
+ * GNUNET_TESTING_connect_topology, which connects the peers in a
+ * "straight line" topology. On notification that all peers have
+ * been properly connected, calls the do_get function which initiates
+ * a GNUNET_DHT_get from the *second* peer. Once the GNUNET_DHT_get
+ * function starts, runs the do_put function to insert data at the first peer.
+ * If the GET is successful, schedules finish_testing
+ * to stop the test and shut down peers. If GET is unsuccessful
+ * after GET_TIMEOUT seconds, prints an error message and shuts down
+ * the peers.
+ */
+#include "platform.h"
+#include "gnunet_testing_lib.h"
+#include "gnunet_core_service.h"
+#include "block_dns.h"
+#include "gnunet_signatures.h"
+#include "gnunet_namestore_service.h"
+#include "../namestore/namestore.h"
+#include "gnunet_dnsparser_lib.h"
+#include "gnunet_gns_service.h"
+
+/* DEFINES */
+#define VERBOSE GNUNET_YES
+
+/* Timeout for entire testcase */
+#define TIMEOUT GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_SECONDS, 20)
+
+/* If number of peers not in config file, use this number */
+#define DEFAULT_NUM_PEERS 2
+
+/* test records to resolve */
+#define TEST_DOMAIN "www.bob.gnunet"
+#define TEST_IP "127.0.0.1"
+#define TEST_RECORD_NAME "www"
+
+#define TEST_AUTHORITY_NAME "bob"
+
+#define KEYFILE_BOB "../namestore/zonefiles/HGU0A0VCU334DN7F2I9UIUMVQMM7JMSD142LIMNUGTTV9R0CF4EG.zkey"
+
+/* Globals */
+
+/**
+ * Directory to store temp data in, defined in config file
+ */
+static char *test_directory;
+
+static struct GNUNET_TESTING_PeerGroup *pg;
+
+/* Task handle to use to schedule test failure */
+GNUNET_SCHEDULER_TaskIdentifier die_task;
+
+/* Global return value (0 for success, anything else for failure) */
+static int ok;
+
+static struct GNUNET_NAMESTORE_Handle *namestore_handle;
+
+static struct GNUNET_GNS_Handle *gns_handle;
+
+const struct GNUNET_CONFIGURATION_Handle *cfg;
+
+/**
+ * Check whether peers successfully shut down.
+ */
+void
+shutdown_callback (void *cls, const char *emsg)
+{
+ if (emsg != NULL)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Error on shutdown! ret=%d\n", ok);
+ if (ok == 0)
+ ok = 2;
+ }
+
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO, "done(ret=%d)!\n", ok);
+}
+
+static void
+on_lookup_result(void *cls, uint32_t rd_count,
+ const struct GNUNET_NAMESTORE_RecordData *rd)
+{
+ struct in_addr a;
+ int i;
+ char* addr;
+
+ if (rd_count == 0)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "Lookup failed, rp_filtering?\n");
+ ok = 2;
+ }
+ else
+ {
+ ok = 1;
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO, "name: %s\n", (char*)cls);
+ for (i=0; i<rd_count; i++)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO, "type: %d\n", rd[i].record_type);
+ if (rd[i].record_type == GNUNET_GNS_RECORD_TYPE_A)
+ {
+ memcpy(&a, rd[i].data, sizeof(a));
+ addr = inet_ntoa(a);
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO, "address: %s\n", addr);
+ if (0 == strcmp(addr, TEST_IP))
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+ "%s correctly resolved to %s!\n", TEST_DOMAIN, addr);
+ ok = 0;
+ }
+ }
+ else
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "No resolution!\n");
+ }
+ }
+ }
+ GNUNET_GNS_disconnect(gns_handle);
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Shutting down peer1!\n");
+ GNUNET_TESTING_daemons_stop (pg, TIMEOUT, &shutdown_callback, NULL);
+}
+
+
+/**
+ * Function scheduled to be run on the successful start of services
+ * tries to look up the dns record for TEST_DOMAIN
+ */
+static void
+commence_testing (void *cls, int32_t success, const char *emsg)
+{
+ GNUNET_NAMESTORE_disconnect(namestore_handle, GNUNET_YES);
+
+ gns_handle = GNUNET_GNS_connect(cfg);
+
+ if (NULL == gns_handle)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "Failed to connect to GNS!\n");
+ }
+
+ GNUNET_GNS_lookup(gns_handle, TEST_DOMAIN, GNUNET_GNS_RECORD_TYPE_A,
+ &on_lookup_result, TEST_DOMAIN);
+}
+
+/**
+ * Continuation for the GNUNET_DHT_get_stop call, so that we don't shut
+ * down the peers without freeing memory associated with GET request.
+ */
+static void
+end_badly_cont (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
+{
+
+ if (pg != NULL)
+ GNUNET_TESTING_daemons_stop (pg, TIMEOUT, &shutdown_callback, NULL);
+ GNUNET_SCHEDULER_cancel (die_task);
+}
+
+/**
+ * Check if the get_handle is being used, if so stop the request. Either
+ * way, schedule the end_badly_cont function which actually shuts down the
+ * test.
+ */
+static void
+end_badly (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
+{
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Failing test with error: `%s'!\n",
+ (char *) cls);
+ GNUNET_SCHEDULER_add_now (&end_badly_cont, NULL);
+ ok = 1;
+}
+
+static void
+do_lookup(void *cls, const struct GNUNET_PeerIdentity *id,
+ const struct GNUNET_CONFIGURATION_Handle *_cfg,
+ struct GNUNET_TESTING_Daemon *d, const char *emsg)
+{
+ struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded alice_pkey;
+ struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded bob_pkey;
+ struct GNUNET_CRYPTO_RsaPrivateKey *alice_key;
+ struct GNUNET_CRYPTO_RsaPrivateKey *bob_key;
+ struct GNUNET_CRYPTO_ShortHashCode bob_hash;
+ struct GNUNET_CRYPTO_RsaSignature *sig;
+ char* alice_keyfile;
+
+ cfg = _cfg;
+
+ GNUNET_SCHEDULER_cancel (die_task);
+
+ /* put records into namestore */
+ namestore_handle = GNUNET_NAMESTORE_connect(cfg);
+ if (NULL == namestore_handle)
+ {
+ GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Failed to connect to namestore\n");
+ ok = -1;
+ return;
+ }
+
+ if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_filename (cfg, "gns",
+ "ZONEKEY",
+ &alice_keyfile))
+ {
+ GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Failed to get key from cfg\n");
+ ok = -1;
+ return;
+ }
+
+ alice_key = GNUNET_CRYPTO_rsa_key_create_from_file (alice_keyfile);
+ bob_key = GNUNET_CRYPTO_rsa_key_create_from_file (KEYFILE_BOB);
+
+ GNUNET_CRYPTO_rsa_key_get_public (alice_key, &alice_pkey);
+ GNUNET_CRYPTO_rsa_key_get_public (bob_key, &bob_pkey);
+
+ struct GNUNET_NAMESTORE_RecordData rd;
+ char* ip = TEST_IP;
+ struct in_addr *web = GNUNET_malloc(sizeof(struct in_addr));
+ rd.expiration = GNUNET_TIME_UNIT_FOREVER_ABS;
+ GNUNET_assert(1 == inet_pton (AF_INET, ip, web));
+
+ GNUNET_CRYPTO_short_hash(&bob_pkey, sizeof(bob_pkey), &bob_hash);
+
+ rd.data_size = sizeof(struct GNUNET_CRYPTO_ShortHashCode);
+ rd.data = &bob_hash;
+ rd.record_type = GNUNET_GNS_RECORD_PKEY;
+
+ GNUNET_NAMESTORE_record_create (namestore_handle,
+ alice_key,
+ TEST_AUTHORITY_NAME,
+ &rd,
+ NULL,
+ NULL);
+
+ rd.data_size = sizeof(struct in_addr);
+ rd.data = web;
+ rd.record_type = GNUNET_DNSPARSER_TYPE_A;
+ sig = GNUNET_NAMESTORE_create_signature(bob_key,
+ GNUNET_TIME_UNIT_FOREVER_ABS,
+ TEST_RECORD_NAME,
+ &rd, 1);
+
+ GNUNET_NAMESTORE_record_put (namestore_handle,
+ &bob_pkey,
+ TEST_RECORD_NAME,
+ rd.expiration,
+ 1,
+ &rd,
+ sig,
+ &commence_testing,
+ NULL);
+ GNUNET_free(sig);
+ GNUNET_CRYPTO_rsa_key_free(bob_key);
+ GNUNET_CRYPTO_rsa_key_free(alice_key);
+}
+
+static void
+run (void *cls, char *const *args, const char *cfgfile,
+ const struct GNUNET_CONFIGURATION_Handle *c)
+{
+ cfg = c;
+ /* Get path from configuration file */
+ if (GNUNET_YES !=
+ GNUNET_CONFIGURATION_get_value_string (cfg, "paths", "servicehome",
+ &test_directory))
+ {
+ ok = 404;
+ return;
+ }
+
+
+ /* Set up a task to end testing if peer start fails */
+ die_task =
+ GNUNET_SCHEDULER_add_delayed (TIMEOUT, &end_badly,
+ "didn't start all daemons in reasonable amount of time!!!");
+
+ /* Start alice */
+ pg = GNUNET_TESTING_daemons_start(cfg, 1, 1, 1, TIMEOUT,
+ NULL, NULL, &do_lookup, NULL,
+ NULL, NULL, NULL);
+}
+
+static int
+check ()
+{
+ int ret;
+
+ /* Arguments for GNUNET_PROGRAM_run */
+ char *const argv[] = { "test-gns-simple-delegated-lookup", /* Name to give running binary */
+ "-c",
+ "test_gns_simple_lookup.conf", /* Config file to use */
+#if VERBOSE
+ "-L", "DEBUG",
+#endif
+ NULL
+ };
+ struct GNUNET_GETOPT_CommandLineOption options[] = {
+ GNUNET_GETOPT_OPTION_END
+ };
+ /* Run the run function as a new program */
+ ret =
+ GNUNET_PROGRAM_run ((sizeof (argv) / sizeof (char *)) - 1, argv,
+ "test-gns-simple-delegated-lookup", "nohelp", options, &run,
+ &ok);
+ if (ret != GNUNET_OK)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+ "`test-gns-simple-delegated-lookup': Failed with error code %d\n", ret);
+ }
+ return ok;
+}
+
+int
+main (int argc, char *argv[])
+{
+ int ret;
+
+ GNUNET_log_setup ("test-gns-simple-lookup",
+#if VERBOSE
+ "DEBUG",
+#else
+ "WARNING",
+#endif
+ NULL);
+ ret = check ();
+ /**
+ * Need to remove base directory, subdirectories taken care
+ * of by the testing framework.
+ */
+ return ret;
+}
+
+/* end of test_gns_twopeer.c */
diff --git a/src/gns/test_gns_simple_get_authority.c b/src/gns/test_gns_simple_get_authority.c
new file mode 100644
index 0000000..dbecb7d
--- /dev/null
+++ b/src/gns/test_gns_simple_get_authority.c
@@ -0,0 +1,388 @@
+/*
+ This file is part of GNUnet.
+ (C) 2009 Christian Grothoff (and other contributing authors)
+
+ GNUnet is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 3, or (at your
+ option) any later version.
+
+ GNUnet is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GNUnet; see the file COPYING. If not, write to the
+ Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+/**
+ * @file gns/test_gns_simple_shorten.c
+ * @brief basic shorten test for gns api
+ *
+ */
+#include "platform.h"
+#include "gnunet_testing_lib.h"
+#include "gnunet_core_service.h"
+#include "block_dns.h"
+#include "gnunet_signatures.h"
+#include "gnunet_namestore_service.h"
+#include "../namestore/namestore.h"
+#include "gnunet_dnsparser_lib.h"
+#include "gnunet_gns_service.h"
+
+/* DEFINES */
+#define VERBOSE GNUNET_YES
+
+/* Timeout for entire testcase */
+#define TIMEOUT GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_SECONDS, 20)
+
+/* If number of peers not in config file, use this number */
+#define DEFAULT_NUM_PEERS 2
+
+/* test records to resolve */
+#define TEST_DOMAIN "www.alice.bob.gnunet"
+#define TEST_IP "127.0.0.1"
+#define TEST_RECORD_NAME "www"
+
+#define TEST_AUTHORITY_BOB "bob"
+#define TEST_AUTHORITY_ALICE "alice"
+#define TEST_ALICE_PSEU "carol"
+#define TEST_EXPECTED_RESULT "alice.bob.gnunet"
+
+#define KEYFILE_BOB "../namestore/zonefiles/HGU0A0VCU334DN7F2I9UIUMVQMM7JMSD142LIMNUGTTV9R0CF4EG.zkey"
+#define KEYFILE_ALICE "../namestore/zonefiles/N0UJMP015AFUNR2BTNM3FKPBLG38913BL8IDMCO2H0A1LIB81960.zkey"
+
+/* Globals */
+
+/**
+ * Directory to store temp data in, defined in config file
+ */
+static char *test_directory;
+
+static struct GNUNET_TESTING_PeerGroup *pg;
+
+/* Task handle to use to schedule test failure */
+GNUNET_SCHEDULER_TaskIdentifier die_task;
+
+/* Global return value (0 for success, anything else for failure) */
+static int ok;
+
+static struct GNUNET_NAMESTORE_Handle *namestore_handle;
+
+static struct GNUNET_GNS_Handle *gns_handle;
+
+const struct GNUNET_CONFIGURATION_Handle *cfg;
+
+/**
+ * Check whether peers successfully shut down.
+ */
+static void
+shutdown_callback (void *cls, const char *emsg)
+{
+ if (emsg != NULL)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Error on shutdown! ret=%d\n", ok);
+ if (ok == 0)
+ ok = 2;
+ }
+
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO, "done(ret=%d)!\n", ok);
+}
+
+/**
+ * Called when gns_get_authority finishes
+ */
+static void
+process_auth_result(void* cls, const char* aname)
+{
+ GNUNET_GNS_disconnect(gns_handle);
+
+ ok = 0;
+
+ if (aname == NULL)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "get_authority test failed!\n");
+ ok = 1;
+ }
+ else
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "%s authority is %s\n", (char*)cls, aname);
+ if (0 != strcmp(aname, TEST_EXPECTED_RESULT))
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "get_authority test failed! (wanted: %s got: %s\n",
+ TEST_EXPECTED_RESULT, aname);
+ ok = 1;
+ }
+
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "get_authority test finished!\n");
+
+ }
+
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Shutting down peer1!\n");
+ GNUNET_TESTING_daemons_stop (pg, TIMEOUT, &shutdown_callback, NULL);
+}
+
+/**
+ * Function scheduled to be run on the successful start of services
+ * tries to shorten the name TEST_DOMAIN using gns
+ */
+static void
+commence_testing (void *cls, int32_t success, const char *emsg)
+{
+
+
+
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "disconnecting from namestore\n");
+ GNUNET_NAMESTORE_disconnect(namestore_handle, GNUNET_YES);
+
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "connecting to gns\n");
+ gns_handle = GNUNET_GNS_connect(cfg);
+
+ if (NULL == gns_handle)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "failed to connect to gns\n");
+ ok = 1;
+ return;
+ }
+
+ GNUNET_GNS_get_authority(gns_handle, TEST_DOMAIN, &process_auth_result,
+ TEST_DOMAIN);
+
+}
+
+/**
+ * Continuation for the GNUNET_DHT_get_stop call, so that we don't shut
+ * down the peers without freeing memory associated with GET request.
+ */
+static void
+end_badly_cont (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
+{
+
+ if (pg != NULL)
+ GNUNET_TESTING_daemons_stop (pg, TIMEOUT, &shutdown_callback, NULL);
+ GNUNET_SCHEDULER_cancel (die_task);
+}
+
+/**
+ * Check if the get_handle is being used, if so stop the request. Either
+ * way, schedule the end_badly_cont function which actually shuts down the
+ * test.
+ */
+static void
+end_badly (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
+{
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Failing test with error: `%s'!\n",
+ (char *) cls);
+ GNUNET_SCHEDULER_add_now (&end_badly_cont, NULL);
+ ok = 1;
+}
+
+static void
+do_shorten(void *cls, const struct GNUNET_PeerIdentity *id,
+ const struct GNUNET_CONFIGURATION_Handle *_cfg,
+ struct GNUNET_TESTING_Daemon *d, const char *emsg)
+{
+ struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded our_pkey;
+ struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded alice_pkey;
+ struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded bob_pkey;
+ struct GNUNET_CRYPTO_RsaPrivateKey *our_key;
+ struct GNUNET_CRYPTO_RsaPrivateKey *alice_key;
+ struct GNUNET_CRYPTO_RsaPrivateKey *bob_key;
+ struct GNUNET_CRYPTO_ShortHashCode bob_hash;
+ struct GNUNET_CRYPTO_ShortHashCode alice_hash;
+ struct GNUNET_CRYPTO_RsaSignature *sig;
+ char* our_keyfile;
+
+ cfg = _cfg;
+
+ GNUNET_SCHEDULER_cancel (die_task);
+
+ /* put records into namestore */
+ namestore_handle = GNUNET_NAMESTORE_connect(cfg);
+ if (NULL == namestore_handle)
+ {
+ GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Failed to connect to namestore\n");
+ ok = -1;
+ return;
+ }
+
+ if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_filename (cfg, "gns",
+ "ZONEKEY",
+ &our_keyfile))
+ {
+ GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Failed to get key from cfg\n");
+ ok = -1;
+ return;
+ }
+
+ our_key = GNUNET_CRYPTO_rsa_key_create_from_file (our_keyfile);
+ GNUNET_free(our_keyfile);
+
+ bob_key = GNUNET_CRYPTO_rsa_key_create_from_file (KEYFILE_BOB);
+ alice_key = GNUNET_CRYPTO_rsa_key_create_from_file (KEYFILE_ALICE);
+
+ GNUNET_CRYPTO_rsa_key_get_public (our_key, &our_pkey);
+ GNUNET_CRYPTO_rsa_key_get_public (alice_key, &alice_pkey);
+ GNUNET_CRYPTO_rsa_key_get_public (bob_key, &bob_pkey);
+
+ struct GNUNET_NAMESTORE_RecordData rd;
+ char* ip = TEST_IP;
+ struct in_addr *web = GNUNET_malloc(sizeof(struct in_addr));
+ rd.expiration = GNUNET_TIME_UNIT_FOREVER_ABS;
+ GNUNET_assert(1 == inet_pton (AF_INET, ip, web));
+
+ GNUNET_CRYPTO_short_hash(&bob_pkey, sizeof(bob_pkey), &bob_hash);
+
+ rd.data_size = sizeof(struct GNUNET_CRYPTO_ShortHashCode);
+ rd.data = &bob_hash;
+ rd.record_type = GNUNET_GNS_RECORD_PKEY;
+
+ /* put bob into our zone */
+ GNUNET_NAMESTORE_record_create (namestore_handle,
+ our_key,
+ TEST_AUTHORITY_BOB,
+ &rd,
+ NULL,
+ NULL);
+
+ /* put alice into bobs zone */
+ GNUNET_CRYPTO_short_hash(&alice_pkey, sizeof(alice_pkey), &alice_hash);
+ rd.data = &alice_hash;
+ sig = GNUNET_NAMESTORE_create_signature(bob_key, GNUNET_TIME_UNIT_FOREVER_ABS, TEST_AUTHORITY_ALICE,
+ &rd, 1);
+
+ GNUNET_NAMESTORE_record_put (namestore_handle,
+ &bob_pkey,
+ TEST_AUTHORITY_ALICE,
+ GNUNET_TIME_UNIT_FOREVER_ABS,
+ 1,
+ &rd,
+ sig,
+ NULL,
+ NULL);
+
+ /* put www A record and PSEU into alice's zone */
+
+ rd.data_size = sizeof(struct in_addr);
+ rd.data = web;
+ rd.record_type = GNUNET_DNSPARSER_TYPE_A;
+ sig = GNUNET_NAMESTORE_create_signature(alice_key,GNUNET_TIME_UNIT_FOREVER_ABS, TEST_RECORD_NAME,
+ &rd, 1);
+
+ GNUNET_NAMESTORE_record_put (namestore_handle,
+ &alice_pkey,
+ TEST_RECORD_NAME,
+ GNUNET_TIME_UNIT_FOREVER_ABS,
+ 1,
+ &rd,
+ sig,
+ NULL,
+ NULL);
+
+ rd.data_size = strlen(TEST_ALICE_PSEU);
+ rd.data = TEST_ALICE_PSEU;
+ rd.record_type = GNUNET_GNS_RECORD_PSEU;
+ GNUNET_free(sig);
+
+ sig = GNUNET_NAMESTORE_create_signature(alice_key,GNUNET_TIME_UNIT_FOREVER_ABS, "",
+ &rd, 1);
+
+ GNUNET_NAMESTORE_record_put (namestore_handle,
+ &alice_pkey,
+ "",
+ GNUNET_TIME_UNIT_FOREVER_ABS,
+ 1,
+ &rd,
+ sig,
+ &commence_testing,
+ NULL);
+
+ GNUNET_free(sig);
+
+}
+
+static void
+run (void *cls, char *const *args, const char *cfgfile,
+ const struct GNUNET_CONFIGURATION_Handle *c)
+{
+ cfg = c;
+ /* Get path from configuration file */
+ if (GNUNET_YES !=
+ GNUNET_CONFIGURATION_get_value_string (cfg, "paths", "servicehome",
+ &test_directory))
+ {
+ ok = 404;
+ return;
+ }
+
+
+ /* Set up a task to end testing if peer start fails */
+ die_task =
+ GNUNET_SCHEDULER_add_delayed (TIMEOUT, &end_badly,
+ "didn't start all daemons in reasonable amount of time!!!");
+
+ /* Start alice */
+ pg = GNUNET_TESTING_daemons_start(cfg, 1, 1, 1, TIMEOUT,
+ NULL, NULL, &do_shorten, NULL,
+ NULL, NULL, NULL);
+}
+
+static int
+check ()
+{
+ int ret;
+
+ /* Arguments for GNUNET_PROGRAM_run */
+ char *const argv[] = { "test-gns-simple-get-authority", /* Name to give running binary */
+ "-c",
+ "test_gns_simple_lookup.conf", /* Config file to use */
+#if VERBOSE
+ "-L", "DEBUG",
+#endif
+ NULL
+ };
+ struct GNUNET_GETOPT_CommandLineOption options[] = {
+ GNUNET_GETOPT_OPTION_END
+ };
+ /* Run the run function as a new program */
+ ret =
+ GNUNET_PROGRAM_run ((sizeof (argv) / sizeof (char *)) - 1, argv,
+ "test-gns-simple-get-authority", "nohelp", options, &run,
+ &ok);
+ if (ret != GNUNET_OK)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+ "`test-gns-simple-get-authority': Failed with error code %d\n", ret);
+ }
+ return ok;
+}
+
+int
+main (int argc, char *argv[])
+{
+ int ret;
+
+ GNUNET_log_setup ("test-gns-simple-lookup",
+#if VERBOSE
+ "DEBUG",
+#else
+ "WARNING",
+#endif
+ NULL);
+ ret = check ();
+ /**
+ * Need to remove base directory, subdirectories taken care
+ * of by the testing framework.
+ */
+ return ret;
+}
+
+/* end of test_gns_twopeer.c */
diff --git a/src/gns/test_gns_simple_lookup.c b/src/gns/test_gns_simple_lookup.c
new file mode 100644
index 0000000..89a9aef
--- /dev/null
+++ b/src/gns/test_gns_simple_lookup.c
@@ -0,0 +1,317 @@
+/*
+ This file is part of GNUnet.
+ (C) 2009 Christian Grothoff (and other contributing authors)
+
+ GNUnet is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 3, or (at your
+ option) any later version.
+
+ GNUnet is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GNUnet; see the file COPYING. If not, write to the
+ Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+/**
+ * @file gns/test_gns_simple_lookup.c
+ * @brief base testcase for testing a local GNS record lookup
+ *
+ */
+#include "platform.h"
+#include "gnunet_testing_lib.h"
+#include "gnunet_core_service.h"
+#include "block_dns.h"
+#include "gnunet_signatures.h"
+#include "gnunet_namestore_service.h"
+#include "gnunet_dnsparser_lib.h"
+#include "gnunet_gns_service.h"
+
+/* DEFINES */
+#define VERBOSE GNUNET_YES
+
+/* Timeout for entire testcase */
+#define TIMEOUT GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_SECONDS, 20)
+
+/* If number of peers not in config file, use this number */
+#define DEFAULT_NUM_PEERS 2
+
+/* test records to resolve */
+#define TEST_DOMAIN "www.gnunet"
+#define TEST_IP "127.0.0.1"
+#define TEST_RECORD_NAME "www"
+
+/* Globals */
+
+/**
+ * Directory to store temp data in, defined in config file
+ */
+static char *test_directory;
+
+static struct GNUNET_TESTING_PeerGroup *pg;
+
+/* Task handle to use to schedule test failure */
+GNUNET_SCHEDULER_TaskIdentifier die_task;
+
+/* Global return value (0 for success, anything else for failure) */
+static int ok;
+
+static struct GNUNET_NAMESTORE_Handle *namestore_handle;
+
+static struct GNUNET_GNS_Handle *gns_handle;
+
+const struct GNUNET_CONFIGURATION_Handle *cfg;
+
+/**
+ * Check whether peers successfully shut down.
+ */
+void
+shutdown_callback (void *cls, const char *emsg)
+{
+ if (emsg != NULL)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Error on shutdown! ret=%d\n", ok);
+ if (ok == 0)
+ ok = 2;
+ }
+
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO, "done(ret=%d)!\n", ok);
+}
+
+
+static void
+on_lookup_result(void *cls, uint32_t rd_count,
+ const struct GNUNET_NAMESTORE_RecordData *rd)
+{
+ struct in_addr a;
+ int i;
+ char* addr;
+
+ if (rd_count == 0)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "Lookup failed, rp_filtering?\n");
+ ok = 2;
+ }
+ else
+ {
+ ok = 1;
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO, "name: %s\n", (char*)cls);
+ for (i=0; i<rd_count; i++)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO, "type: %d\n", rd[i].record_type);
+ if (rd[i].record_type == GNUNET_GNS_RECORD_TYPE_A)
+ {
+ memcpy(&a, rd[i].data, sizeof(a));
+ addr = inet_ntoa(a);
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO, "address: %s\n", addr);
+ if (0 == strcmp(addr, TEST_IP))
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+ "%s correctly resolved to %s!\n", TEST_DOMAIN, addr);
+ ok = 0;
+ }
+ }
+ else
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "No resolution!\n");
+ }
+ }
+ }
+ GNUNET_GNS_disconnect(gns_handle);
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Shutting down peer1!\n");
+ GNUNET_TESTING_daemons_stop (pg, TIMEOUT, &shutdown_callback, NULL);
+}
+
+
+/**
+ * Function scheduled to be run on the successful start of services
+ * tries to look up the dns record for TEST_DOMAIN
+ */
+static void
+commence_testing (void *cls, int32_t success, const char *emsg)
+{
+
+
+ GNUNET_NAMESTORE_disconnect(namestore_handle, GNUNET_YES);
+
+ gns_handle = GNUNET_GNS_connect(cfg);
+
+ if (NULL == gns_handle)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "Failed to connect to GNS!\n");
+ ok = 2;
+ }
+
+ GNUNET_GNS_lookup(gns_handle, TEST_DOMAIN, GNUNET_GNS_RECORD_TYPE_A,
+ &on_lookup_result, TEST_DOMAIN);
+}
+
+
+/**
+ * Continuation for the GNUNET_DHT_get_stop call, so that we don't shut
+ * down the peers without freeing memory associated with GET request.
+ */
+static void
+end_badly_cont (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
+{
+
+ if (pg != NULL)
+ GNUNET_TESTING_daemons_stop (pg, TIMEOUT, &shutdown_callback, NULL);
+ GNUNET_SCHEDULER_cancel (die_task);
+}
+
+/**
+ * Check if the get_handle is being used, if so stop the request. Either
+ * way, schedule the end_badly_cont function which actually shuts down the
+ * test.
+ */
+static void
+end_badly (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
+{
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Failing test with error: `%s'!\n",
+ (char *) cls);
+ GNUNET_SCHEDULER_add_now (&end_badly_cont, NULL);
+ ok = 1;
+}
+
+static void
+do_lookup(void *cls, const struct GNUNET_PeerIdentity *id,
+ const struct GNUNET_CONFIGURATION_Handle *_cfg,
+ struct GNUNET_TESTING_Daemon *d, const char *emsg)
+{
+ struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded alice_pkey;
+ struct GNUNET_CRYPTO_RsaPrivateKey *alice_key;
+ char* alice_keyfile;
+
+ cfg = _cfg;
+
+ GNUNET_SCHEDULER_cancel (die_task);
+
+ /* put records into namestore */
+ namestore_handle = GNUNET_NAMESTORE_connect(cfg);
+ if (NULL == namestore_handle)
+ {
+ GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Failed to connect to namestore\n");
+ ok = -1;
+ return;
+ }
+
+ if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_filename (cfg, "gns",
+ "ZONEKEY",
+ &alice_keyfile))
+ {
+ GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Failed to get key from cfg\n");
+ ok = -1;
+ return;
+ }
+
+ alice_key = GNUNET_CRYPTO_rsa_key_create_from_file (alice_keyfile);
+
+ GNUNET_CRYPTO_rsa_key_get_public (alice_key, &alice_pkey);
+
+ GNUNET_free(alice_keyfile);
+
+ struct GNUNET_NAMESTORE_RecordData rd;
+ char* ip = TEST_IP;
+ struct in_addr *web = GNUNET_malloc(sizeof(struct in_addr));
+ rd.expiration = GNUNET_TIME_UNIT_FOREVER_ABS;
+ GNUNET_assert(1 == inet_pton (AF_INET, ip, web));
+ rd.data_size = sizeof(struct in_addr);
+ rd.data = web;
+ rd.record_type = GNUNET_DNSPARSER_TYPE_A;
+
+ GNUNET_NAMESTORE_record_create (namestore_handle,
+ alice_key,
+ TEST_RECORD_NAME,
+ &rd,
+ &commence_testing,
+ NULL);
+
+ GNUNET_CRYPTO_rsa_key_free(alice_key);
+ GNUNET_free(web);
+
+}
+
+static void
+run (void *cls, char *const *args, const char *cfgfile,
+ const struct GNUNET_CONFIGURATION_Handle *c)
+{
+ cfg = c;
+ /* Get path from configuration file */
+ if (GNUNET_YES !=
+ GNUNET_CONFIGURATION_get_value_string (cfg, "paths", "servicehome",
+ &test_directory))
+ {
+ ok = 404;
+ return;
+ }
+
+
+ /* Set up a task to end testing if peer start fails */
+ die_task =
+ GNUNET_SCHEDULER_add_delayed (TIMEOUT, &end_badly,
+ "didn't start all daemons in reasonable amount of time!!!");
+
+ /* Start alice */
+ pg = GNUNET_TESTING_daemons_start(cfg, 1, 1, 1, TIMEOUT,
+ NULL, NULL, &do_lookup, NULL,
+ NULL, NULL, NULL);
+}
+
+static int
+check ()
+{
+ int ret;
+
+ /* Arguments for GNUNET_PROGRAM_run */
+ char *const argv[] = { "test-gns-simple-lookup", /* Name to give running binary */
+ "-c",
+ "test_gns_simple_lookup.conf", /* Config file to use */
+#if VERBOSE
+ "-L", "DEBUG",
+#endif
+ NULL
+ };
+ struct GNUNET_GETOPT_CommandLineOption options[] = {
+ GNUNET_GETOPT_OPTION_END
+ };
+ /* Run the run function as a new program */
+ ret =
+ GNUNET_PROGRAM_run ((sizeof (argv) / sizeof (char *)) - 1, argv,
+ "test-gns-simple-lookup", "nohelp", options, &run,
+ &ok);
+ if (ret != GNUNET_OK)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+ "`test-gns-simple-lookup': Failed with error code %d\n", ret);
+ }
+ return ok;
+}
+
+int
+main (int argc, char *argv[])
+{
+ int ret;
+
+ GNUNET_log_setup ("test-gns-simple-lookup",
+#if VERBOSE
+ "DEBUG",
+#else
+ "WARNING",
+#endif
+ NULL);
+ ret = check ();
+ /**
+ * Need to remove base directory, subdirectories taken care
+ * of by the testing framework.
+ */
+ return ret;
+}
+
+/* end of test_gns_twopeer.c */
diff --git a/src/gns/test_gns_simple_lookup.conf b/src/gns/test_gns_simple_lookup.conf
new file mode 100644
index 0000000..9a32fe5
--- /dev/null
+++ b/src/gns/test_gns_simple_lookup.conf
@@ -0,0 +1,112 @@
+@INLINE@ test_gns_defaults.conf
+[fs]
+AUTOSTART = NO
+
+[resolver]
+AUTOSTART = NO
+HOSTNAME = localhost
+
+[dht]
+DEBUG = NO
+AUTOSTART = YES
+ACCEPT_FROM6 = ::1;
+ACCEPT_FROM = 127.0.0.1;
+HOSTNAME = localhost
+PORT = 12100
+BINARY = gnunet-service-dht
+
+[block]
+plugins = dht test gns
+
+[dhtcache]
+QUOTA = 1 MB
+DATABASE = sqlite
+
+[transport]
+PLUGINS = tcp
+DEBUG = NO
+ACCEPT_FROM6 = ::1;
+ACCEPT_FROM = 127.0.0.1;
+NEIGHBOUR_LIMIT = 50
+PORT = 12365
+
+[ats]
+WAN_QUOTA_IN = 1 GB
+WAN_QUOTA_OUT = 1 GB
+
+[core]
+PORT = 12092
+
+[arm]
+DEFAULTSERVICES = core dht namestore gns
+PORT = 12366
+DEBUG = NO
+
+[transport-tcp]
+TIMEOUT = 300 s
+PORT = 12368
+BINDTO = 127.0.0.1
+
+[TESTING]
+WEAKRANDOM = YES
+
+[gnunetd]
+HOSTKEY = $SERVICEHOME/.hostkey
+
+[PATHS]
+DEFAULTCONFIG = test_gns_simple_lookup.conf
+SERVICEHOME = /tmp/test-gnunetd-gns-peer-1/
+
+
+[nat]
+DISABLEV6 = YES
+ENABLE_UPNP = NO
+BEHIND_NAT = NO
+ALLOW_NAT = NO
+INTERNAL_ADDRESS = 127.0.0.1
+EXTERNAL_ADDRESS = 127.0.0.1
+USE_LOCALADDR = NO
+
+[dns]
+AUTOSTART = YES
+DNS_EXIT = 8.8.8.8
+
+[gns]
+#PREFIX = valgrind -v --leak-check=full --track-origins=yes
+AUTOSTART = YES
+BINARY = gnunet-service-gns
+ZONEKEY = $SERVICEHOME/.hostkey
+#ZONEKEY = $SERVICEHOME/gns/zonekey.zkey
+HIJACK_DNS = NO
+UNIXPATH = /tmp/gnunet-service-gns.sock
+HOME = $SERVICEHOME
+CONFIG = $DEFAULTCONFIG
+AUTO_IMPORT_PKEY = YES
+MAX_PARALLEL_BACKGROUND_QUERIES = 10
+DEFAULT_LOOKUP_TIMEOUT = 5
+RECORD_PUT_INTERVAL = 1
+ZONE_PUT_INTERVAL = 5
+
+[nse]
+AUTOSTART = NO
+
+[statistics]
+AUTOSTART = NO
+
+[namestore]
+PORT = 22371
+AUTOSTART = YES
+UNIXPATH = /tmp/gnunet-service-namestore-default.sock
+UNIX_MATCH_UID = YES
+UNIX_MATCH_GID = YES
+HOSTNAME = localhost
+HOME = $SERVICEHOME
+CONFIG = $DEFAULTCONFIG
+BINARY = gnunet-service-namestore
+ACCEPT_FROM = 127.0.0.1;
+ACCEPT_FROM6 = ::1;
+DATABASE = sqlite
+ZONEFILE_DIRECTORY = $SERVICEHOME
+
+[namestore-sqlite]
+FILENAME = $SERVICEHOME/sqlite-default.db
diff --git a/src/gns/test_gns_simple_mx_lookup.c b/src/gns/test_gns_simple_mx_lookup.c
new file mode 100644
index 0000000..fdc639a
--- /dev/null
+++ b/src/gns/test_gns_simple_mx_lookup.c
@@ -0,0 +1,396 @@
+/*
+ This file is part of GNUnet.
+ (C) 2009 Christian Grothoff (and other contributing authors)
+
+ GNUnet is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 3, or (at your
+ option) any later version.
+
+ GNUnet is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GNUnet; see the file COPYING. If not, write to the
+ Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+/**
+ * @file gns/test_gns_simple_mx_lookup.c
+ * @brief base testcase for testing GNS MX lookups
+ *
+ */
+#include "platform.h"
+#include "gnunet_testing_lib.h"
+#include "gnunet_core_service.h"
+#include "block_dns.h"
+#include "gnunet_signatures.h"
+#include "gnunet_namestore_service.h"
+#include "../namestore/namestore.h"
+#include "gnunet_dnsparser_lib.h"
+#include "gnunet_gns_service.h"
+
+/* DEFINES */
+#define VERBOSE GNUNET_YES
+
+/* Timeout for entire testcase */
+#define TIMEOUT GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_SECONDS, 20)
+
+/* If number of peers not in config file, use this number */
+#define DEFAULT_NUM_PEERS 2
+
+/* test records to resolve */
+#define TEST_DOMAIN "bob.gnunet"
+#define TEST_IP "127.0.0.1"
+#define TEST_RECORD_NAME "mail"
+#define TEST_MX_NAME "mail.+"
+#define TEST_EXPECTED_MX "mail.bob.gnunet"
+
+#define TEST_AUTHORITY_NAME "bob"
+
+#define KEYFILE_BOB "../namestore/zonefiles/HGU0A0VCU334DN7F2I9UIUMVQMM7JMSD142LIMNUGTTV9R0CF4EG.zkey"
+
+/* Globals */
+
+/**
+ * Directory to store temp data in, defined in config file
+ */
+static char *test_directory;
+
+static struct GNUNET_TESTING_PeerGroup *pg;
+
+/* Task handle to use to schedule test failure */
+GNUNET_SCHEDULER_TaskIdentifier die_task;
+
+/* Global return value (0 for success, anything else for failure) */
+static int ok;
+
+static struct GNUNET_NAMESTORE_Handle *namestore_handle;
+
+static struct GNUNET_GNS_Handle *gns_handle;
+
+const struct GNUNET_CONFIGURATION_Handle *cfg;
+
+/**
+ * Check whether peers successfully shut down.
+ */
+void
+shutdown_callback (void *cls, const char *emsg)
+{
+ if (emsg != NULL)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Error on shutdown! ret=%d\n", ok);
+ if (ok == 0)
+ ok = 2;
+ }
+
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO, "done(ret=%d)!\n", ok);
+}
+
+static void
+on_lookup_result(void *cls, uint32_t rd_count,
+ const struct GNUNET_NAMESTORE_RecordData *rd)
+{
+ struct in_addr a;
+ int i;
+ char* addr;
+ int mx_found = 0;
+ int ip_found = 0;
+ uint16_t mx_preference;
+ char* mx;
+
+ if (rd_count == 0)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "Lookup failed, rp_filtering?\n");
+ ok = 2;
+ }
+ else
+ {
+ ok = 1;
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO, "name: %s\n", (char*)cls);
+ for (i=0; i<rd_count; i++)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO, "type: %d\n", rd[i].record_type);
+ if (rd[i].record_type == GNUNET_GNS_RECORD_TYPE_A)
+ {
+ memcpy(&a, rd[i].data, sizeof(a));
+ addr = inet_ntoa(a);
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO, "address: %s\n", addr);
+ if (0 == strcmp(addr, TEST_IP))
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+ "%s correctly resolved to %s!\n", TEST_DOMAIN, addr);
+ ip_found = 1;
+ }
+ }
+ else if (rd[i].record_type == GNUNET_GNS_RECORD_MX)
+ {
+ mx = (char*)rd[i].data+sizeof(uint16_t);
+ mx_preference = *(uint16_t*)rd[i].data;
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+ "Got MX %s with preference %d\n", mx, mx_preference);
+ if (0 == strcmp(mx, TEST_EXPECTED_MX))
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+ "%s correctly resolved to %s!\n", TEST_DOMAIN,
+ TEST_EXPECTED_MX);
+ mx_found = 1;
+ }
+ }
+ }
+ }
+
+ if (ip_found && mx_found)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+ "Test succeeded!\n");
+ ok = 0;
+ }
+
+ if (!ip_found && mx_found)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+ "Test partially succeeded: A record not passed along!(NOT IMPLEMENTED)\n");
+ ok = 0;
+ }
+
+ GNUNET_GNS_disconnect(gns_handle);
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Shutting down peer1!\n");
+ GNUNET_TESTING_daemons_stop (pg, TIMEOUT, &shutdown_callback, NULL);
+}
+
+
+/**
+ * Function scheduled to be run on the successful start of services
+ * tries to look up the dns record for TEST_DOMAIN
+ */
+static void
+commence_testing (void *cls, int32_t success, const char *emsg)
+{
+ GNUNET_NAMESTORE_disconnect(namestore_handle, GNUNET_YES);
+
+ gns_handle = GNUNET_GNS_connect(cfg);
+
+ if (NULL == gns_handle)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "Failed to connect to GNS!\n");
+ }
+
+ GNUNET_GNS_lookup(gns_handle, TEST_DOMAIN, GNUNET_GNS_RECORD_MX,
+ &on_lookup_result, TEST_DOMAIN);
+}
+
+/**
+ * Continuation for the GNUNET_DHT_get_stop call, so that we don't shut
+ * down the peers without freeing memory associated with GET request.
+ */
+static void
+end_badly_cont (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
+{
+
+ if (pg != NULL)
+ GNUNET_TESTING_daemons_stop (pg, TIMEOUT, &shutdown_callback, NULL);
+ GNUNET_SCHEDULER_cancel (die_task);
+}
+
+/**
+ * Check if the get_handle is being used, if so stop the request. Either
+ * way, schedule the end_badly_cont function which actually shuts down the
+ * test.
+ */
+static void
+end_badly (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
+{
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Failing test with error: `%s'!\n",
+ (char *) cls);
+ GNUNET_SCHEDULER_add_now (&end_badly_cont, NULL);
+ ok = 1;
+}
+
+static void
+do_lookup(void *cls, const struct GNUNET_PeerIdentity *id,
+ const struct GNUNET_CONFIGURATION_Handle *_cfg,
+ struct GNUNET_TESTING_Daemon *d, const char *emsg)
+{
+ struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded alice_pkey;
+ struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded bob_pkey;
+ struct GNUNET_CRYPTO_RsaPrivateKey *alice_key;
+ struct GNUNET_CRYPTO_RsaPrivateKey *bob_key;
+ struct GNUNET_CRYPTO_ShortHashCode bob_hash;
+ struct GNUNET_CRYPTO_RsaSignature *sig;
+ char* alice_keyfile;
+
+ cfg = _cfg;
+
+ GNUNET_SCHEDULER_cancel (die_task);
+
+ /* put records into namestore */
+ namestore_handle = GNUNET_NAMESTORE_connect(cfg);
+ if (NULL == namestore_handle)
+ {
+ GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Failed to connect to namestore\n");
+ ok = -1;
+ return;
+ }
+
+ if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_filename (cfg, "gns",
+ "ZONEKEY",
+ &alice_keyfile))
+ {
+ GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Failed to get key from cfg\n");
+ ok = -1;
+ return;
+ }
+
+ alice_key = GNUNET_CRYPTO_rsa_key_create_from_file (alice_keyfile);
+ bob_key = GNUNET_CRYPTO_rsa_key_create_from_file (KEYFILE_BOB);
+
+ GNUNET_CRYPTO_rsa_key_get_public (alice_key, &alice_pkey);
+ GNUNET_CRYPTO_rsa_key_get_public (bob_key, &bob_pkey);
+
+ struct GNUNET_NAMESTORE_RecordData rd;
+ char* ip = TEST_IP;
+ struct in_addr *mail = GNUNET_malloc(sizeof(struct in_addr));
+ char *mx_record;
+ uint16_t mx_preference = 1;
+ rd.expiration = GNUNET_TIME_UNIT_FOREVER_ABS;
+ GNUNET_assert(1 == inet_pton (AF_INET, ip, mail));
+
+ GNUNET_CRYPTO_short_hash(&bob_pkey, sizeof(bob_pkey), &bob_hash);
+
+ rd.data_size = sizeof(struct GNUNET_CRYPTO_ShortHashCode);
+ rd.data = &bob_hash;
+ rd.record_type = GNUNET_GNS_RECORD_PKEY;
+
+ GNUNET_NAMESTORE_record_create (namestore_handle,
+ alice_key,
+ TEST_AUTHORITY_NAME,
+ &rd,
+ NULL,
+ NULL);
+
+ rd.data_size = sizeof(struct in_addr);
+ rd.data = mail;
+ rd.record_type = GNUNET_DNSPARSER_TYPE_A;
+ sig = GNUNET_NAMESTORE_create_signature(bob_key,
+ GNUNET_TIME_UNIT_FOREVER_ABS,
+ TEST_RECORD_NAME,
+ &rd, 1);
+
+ GNUNET_NAMESTORE_record_put (namestore_handle,
+ &bob_pkey,
+ TEST_RECORD_NAME,
+ rd.expiration,
+ 1,
+ &rd,
+ sig,
+ NULL,
+ NULL);
+
+ rd.data_size = sizeof(struct GNUNET_DNSPARSER_MxRecord)+strlen(TEST_MX_NAME)+1;
+ mx_record = GNUNET_malloc(sizeof(uint16_t)+strlen(TEST_MX_NAME)+1);
+ memcpy(mx_record, &mx_preference, sizeof(uint16_t));
+ strcpy(mx_record+sizeof(uint16_t), TEST_MX_NAME);
+ rd.data = mx_record;
+ rd.record_type = GNUNET_GNS_RECORD_MX;
+ sig = GNUNET_NAMESTORE_create_signature(bob_key,
+ GNUNET_TIME_UNIT_FOREVER_ABS,
+ "+",
+ &rd, 1);
+ GNUNET_NAMESTORE_record_put (namestore_handle,
+ &bob_pkey,
+ "+",
+ rd.expiration,
+ 1,
+ &rd,
+ sig,
+ &commence_testing,
+ NULL);
+ GNUNET_free(mx_record);
+ GNUNET_free(mail);
+ GNUNET_free(sig);
+ GNUNET_CRYPTO_rsa_key_free(bob_key);
+ GNUNET_CRYPTO_rsa_key_free(alice_key);
+}
+
+static void
+run (void *cls, char *const *args, const char *cfgfile,
+ const struct GNUNET_CONFIGURATION_Handle *c)
+{
+ cfg = c;
+ /* Get path from configuration file */
+ if (GNUNET_YES !=
+ GNUNET_CONFIGURATION_get_value_string (cfg, "paths", "servicehome",
+ &test_directory))
+ {
+ ok = 404;
+ return;
+ }
+
+
+ /* Set up a task to end testing if peer start fails */
+ die_task =
+ GNUNET_SCHEDULER_add_delayed (TIMEOUT, &end_badly,
+ "didn't start all daemons in reasonable amount of time!!!");
+
+ /* Start alice */
+ pg = GNUNET_TESTING_daemons_start(cfg, 1, 1, 1, TIMEOUT,
+ NULL, NULL, &do_lookup, NULL,
+ NULL, NULL, NULL);
+}
+
+static int
+check ()
+{
+ int ret;
+
+ /* Arguments for GNUNET_PROGRAM_run */
+ char *const argv[] = { "test-gns-simple-delegated-lookup", /* Name to give running binary */
+ "-c",
+ "test_gns_simple_lookup.conf", /* Config file to use */
+#if VERBOSE
+ "-L", "DEBUG",
+#endif
+ NULL
+ };
+ struct GNUNET_GETOPT_CommandLineOption options[] = {
+ GNUNET_GETOPT_OPTION_END
+ };
+ /* Run the run function as a new program */
+ ret =
+ GNUNET_PROGRAM_run ((sizeof (argv) / sizeof (char *)) - 1, argv,
+ "test-gns-simple-delegated-lookup", "nohelp", options, &run,
+ &ok);
+ if (ret != GNUNET_OK)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+ "`test-gns-simple-delegated-lookup': Failed with error code %d\n", ret);
+ }
+ return ok;
+}
+
+int
+main (int argc, char *argv[])
+{
+ int ret;
+
+ GNUNET_log_setup ("test-gns-simple-lookup",
+#if VERBOSE
+ "DEBUG",
+#else
+ "WARNING",
+#endif
+ NULL);
+ ret = check ();
+ /**
+ * Need to remove base directory, subdirectories taken care
+ * of by the testing framework.
+ */
+ return ret;
+}
+
+/* end of test_gns_twopeer.c */
diff --git a/src/gns/test_gns_simple_shorten.c b/src/gns/test_gns_simple_shorten.c
new file mode 100644
index 0000000..5371793
--- /dev/null
+++ b/src/gns/test_gns_simple_shorten.c
@@ -0,0 +1,388 @@
+/*
+ This file is part of GNUnet.
+ (C) 2009 Christian Grothoff (and other contributing authors)
+
+ GNUnet is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 3, or (at your
+ option) any later version.
+
+ GNUnet is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GNUnet; see the file COPYING. If not, write to the
+ Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+/**
+ * @file gns/test_gns_simple_shorten.c
+ * @brief basic shorten test for gns api
+ *
+ */
+#include "platform.h"
+#include "gnunet_testing_lib.h"
+#include "gnunet_core_service.h"
+#include "block_dns.h"
+#include "gnunet_signatures.h"
+#include "gnunet_namestore_service.h"
+#include "../namestore/namestore.h"
+#include "gnunet_dnsparser_lib.h"
+#include "gnunet_gns_service.h"
+
+/* DEFINES */
+#define VERBOSE GNUNET_YES
+
+/* Timeout for entire testcase */
+#define TIMEOUT GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_SECONDS, 20)
+
+/* If number of peers not in config file, use this number */
+#define DEFAULT_NUM_PEERS 2
+
+/* test records to resolve */
+#define TEST_DOMAIN "www.alice.bob.gnunet"
+#define TEST_IP "127.0.0.1"
+#define TEST_RECORD_NAME "www"
+
+#define TEST_AUTHORITY_BOB "bob"
+#define TEST_AUTHORITY_ALICE "alice"
+#define TEST_ALICE_PSEU "carol"
+#define TEST_EXPECTED_RESULT "www.carol.gnunet"
+
+#define KEYFILE_BOB "../namestore/zonefiles/HGU0A0VCU334DN7F2I9UIUMVQMM7JMSD142LIMNUGTTV9R0CF4EG.zkey"
+#define KEYFILE_ALICE "../namestore/zonefiles/N0UJMP015AFUNR2BTNM3FKPBLG38913BL8IDMCO2H0A1LIB81960.zkey"
+
+/* Globals */
+
+/**
+ * Directory to store temp data in, defined in config file
+ */
+static char *test_directory;
+
+static struct GNUNET_TESTING_PeerGroup *pg;
+
+/* Task handle to use to schedule test failure */
+GNUNET_SCHEDULER_TaskIdentifier die_task;
+
+/* Global return value (0 for success, anything else for failure) */
+static int ok;
+
+static struct GNUNET_NAMESTORE_Handle *namestore_handle;
+
+static struct GNUNET_GNS_Handle *gns_handle;
+
+const struct GNUNET_CONFIGURATION_Handle *cfg;
+
+/**
+ * Check whether peers successfully shut down.
+ */
+static void
+shutdown_callback (void *cls, const char *emsg)
+{
+ if (emsg != NULL)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Error on shutdown! ret=%d\n", ok);
+ if (ok == 0)
+ ok = 2;
+ }
+
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO, "done(ret=%d)!\n", ok);
+}
+
+/**
+ * Called when gns shorten finishes
+ */
+static void
+process_shorten_result(void* cls, const char* sname)
+{
+ GNUNET_GNS_disconnect(gns_handle);
+
+ ok = 0;
+
+ if (sname == NULL)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "shorten test failed!\n");
+ ok = 1;
+ }
+ else
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "%s shortened to %s\n", (char*)cls, sname);
+ if (0 != strcmp(sname, TEST_EXPECTED_RESULT))
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "shorten test failed! (wanted: %s got: %s\n",
+ (char*)cls, sname);
+ ok = 1;
+ }
+
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "shorten test succeeded!\n");
+
+ }
+
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Shutting down peer1!\n");
+ GNUNET_TESTING_daemons_stop (pg, TIMEOUT, &shutdown_callback, NULL);
+}
+
+/**
+ * Function scheduled to be run on the successful start of services
+ * tries to shorten the name TEST_DOMAIN using gns
+ */
+static void
+commence_testing (void *cls, int32_t success, const char *emsg)
+{
+
+
+
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "disconnecting from namestore\n");
+ GNUNET_NAMESTORE_disconnect(namestore_handle, GNUNET_YES);
+
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "connecting to gns\n");
+ gns_handle = GNUNET_GNS_connect(cfg);
+
+ if (NULL == gns_handle)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "failed to connect to gns\n");
+ ok = 1;
+ return;
+ }
+
+ GNUNET_GNS_shorten(gns_handle, TEST_DOMAIN, &process_shorten_result,
+ TEST_DOMAIN);
+
+}
+
+/**
+ * Continuation for the GNUNET_DHT_get_stop call, so that we don't shut
+ * down the peers without freeing memory associated with GET request.
+ */
+static void
+end_badly_cont (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
+{
+
+ if (pg != NULL)
+ GNUNET_TESTING_daemons_stop (pg, TIMEOUT, &shutdown_callback, NULL);
+ GNUNET_SCHEDULER_cancel (die_task);
+}
+
+/**
+ * Check if the get_handle is being used, if so stop the request. Either
+ * way, schedule the end_badly_cont function which actually shuts down the
+ * test.
+ */
+static void
+end_badly (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
+{
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Failing test with error: `%s'!\n",
+ (char *) cls);
+ GNUNET_SCHEDULER_add_now (&end_badly_cont, NULL);
+ ok = 1;
+}
+
+static void
+do_shorten(void *cls, const struct GNUNET_PeerIdentity *id,
+ const struct GNUNET_CONFIGURATION_Handle *_cfg,
+ struct GNUNET_TESTING_Daemon *d, const char *emsg)
+{
+ struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded our_pkey;
+ struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded alice_pkey;
+ struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded bob_pkey;
+ struct GNUNET_CRYPTO_RsaPrivateKey *our_key;
+ struct GNUNET_CRYPTO_RsaPrivateKey *alice_key;
+ struct GNUNET_CRYPTO_RsaPrivateKey *bob_key;
+ struct GNUNET_CRYPTO_ShortHashCode bob_hash;
+ struct GNUNET_CRYPTO_ShortHashCode alice_hash;
+ struct GNUNET_CRYPTO_RsaSignature *sig;
+ char* our_keyfile;
+
+ cfg = _cfg;
+
+ GNUNET_SCHEDULER_cancel (die_task);
+
+ /* put records into namestore */
+ namestore_handle = GNUNET_NAMESTORE_connect(cfg);
+ if (NULL == namestore_handle)
+ {
+ GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Failed to connect to namestore\n");
+ ok = -1;
+ return;
+ }
+
+ if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_filename (cfg, "gns",
+ "ZONEKEY",
+ &our_keyfile))
+ {
+ GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Failed to get key from cfg\n");
+ ok = -1;
+ return;
+ }
+
+ our_key = GNUNET_CRYPTO_rsa_key_create_from_file (our_keyfile);
+ GNUNET_free(our_keyfile);
+
+ bob_key = GNUNET_CRYPTO_rsa_key_create_from_file (KEYFILE_BOB);
+ alice_key = GNUNET_CRYPTO_rsa_key_create_from_file (KEYFILE_ALICE);
+
+ GNUNET_CRYPTO_rsa_key_get_public (our_key, &our_pkey);
+ GNUNET_CRYPTO_rsa_key_get_public (alice_key, &alice_pkey);
+ GNUNET_CRYPTO_rsa_key_get_public (bob_key, &bob_pkey);
+
+ struct GNUNET_NAMESTORE_RecordData rd;
+ char* ip = TEST_IP;
+ struct in_addr *web = GNUNET_malloc(sizeof(struct in_addr));
+ rd.expiration = GNUNET_TIME_UNIT_FOREVER_ABS;
+ GNUNET_assert(1 == inet_pton (AF_INET, ip, web));
+
+ GNUNET_CRYPTO_short_hash(&bob_pkey, sizeof(bob_pkey), &bob_hash);
+
+ rd.data_size = sizeof(struct GNUNET_CRYPTO_ShortHashCode);
+ rd.data = &bob_hash;
+ rd.record_type = GNUNET_GNS_RECORD_PKEY;
+
+ /* put bob into our zone */
+ GNUNET_NAMESTORE_record_create (namestore_handle,
+ our_key,
+ TEST_AUTHORITY_BOB,
+ &rd,
+ NULL,
+ NULL);
+
+ /* put alice into bobs zone */
+ GNUNET_CRYPTO_short_hash(&alice_pkey, sizeof(alice_pkey), &alice_hash);
+ rd.data = &alice_hash;
+ sig = GNUNET_NAMESTORE_create_signature(bob_key,
+ GNUNET_TIME_UNIT_FOREVER_ABS,
+ TEST_AUTHORITY_ALICE,
+ &rd, 1);
+
+ GNUNET_NAMESTORE_record_put (namestore_handle,
+ &bob_pkey,
+ TEST_AUTHORITY_ALICE,
+ GNUNET_TIME_UNIT_FOREVER_ABS,
+ 1,
+ &rd,
+ sig,
+ NULL,
+ NULL);
+ GNUNET_free(sig);
+ /* put www A record and PSEU into alice's zone */
+
+ rd.data_size = sizeof(struct in_addr);
+ rd.data = web;
+ rd.record_type = GNUNET_DNSPARSER_TYPE_A;
+ sig = GNUNET_NAMESTORE_create_signature(alice_key,
+ GNUNET_TIME_UNIT_FOREVER_ABS,
+ TEST_RECORD_NAME,
+ &rd, 1);
+
+ GNUNET_NAMESTORE_record_put (namestore_handle,
+ &alice_pkey,
+ TEST_RECORD_NAME,
+ GNUNET_TIME_UNIT_FOREVER_ABS,
+ 1,
+ &rd,
+ sig,
+ NULL,
+ NULL);
+
+ rd.data_size = sizeof(struct GNUNET_CRYPTO_ShortHashCode);
+ rd.data = &alice_hash;
+ rd.record_type = GNUNET_GNS_RECORD_PKEY;
+ GNUNET_free(sig);
+
+ GNUNET_NAMESTORE_record_create (namestore_handle,
+ our_key,
+ TEST_ALICE_PSEU,
+ &rd,
+ &commence_testing,
+ NULL);
+
+ GNUNET_free(web);
+ GNUNET_CRYPTO_rsa_key_free(our_key);
+ GNUNET_CRYPTO_rsa_key_free(bob_key);
+ GNUNET_CRYPTO_rsa_key_free(alice_key);
+}
+
+static void
+run (void *cls, char *const *args, const char *cfgfile,
+ const struct GNUNET_CONFIGURATION_Handle *c)
+{
+ cfg = c;
+ /* Get path from configuration file */
+ if (GNUNET_YES !=
+ GNUNET_CONFIGURATION_get_value_string (cfg, "paths", "servicehome",
+ &test_directory))
+ {
+ ok = 404;
+ return;
+ }
+
+
+ /* Set up a task to end testing if peer start fails */
+ die_task =
+ GNUNET_SCHEDULER_add_delayed (TIMEOUT, &end_badly,
+ "didn't start all daemons in reasonable amount of time!!!");
+
+ /* Start alice */
+ pg = GNUNET_TESTING_daemons_start(cfg, 1, 1, 1, TIMEOUT,
+ NULL, NULL, &do_shorten, NULL,
+ NULL, NULL, NULL);
+}
+
+static int
+check ()
+{
+ int ret;
+
+ /* Arguments for GNUNET_PROGRAM_run */
+ char *const argv[] = { "test-gns-simple-shorten", /* Name to give running binary */
+ "-c",
+ "test_gns_simple_lookup.conf", /* Config file to use */
+#if VERBOSE
+ "-L", "DEBUG",
+#endif
+ NULL
+ };
+ struct GNUNET_GETOPT_CommandLineOption options[] = {
+ GNUNET_GETOPT_OPTION_END
+ };
+ /* Run the run function as a new program */
+ ret =
+ GNUNET_PROGRAM_run ((sizeof (argv) / sizeof (char *)) - 1, argv,
+ "test-gns-simple-shorten", "nohelp", options, &run,
+ &ok);
+ if (ret != GNUNET_OK)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+ "`test-gns-simple-shorten': Failed with error code %d\n", ret);
+ }
+ return ok;
+}
+
+int
+main (int argc, char *argv[])
+{
+ int ret;
+
+ GNUNET_log_setup ("test-gns-simple-shorten",
+#if VERBOSE
+ "DEBUG",
+#else
+ "WARNING",
+#endif
+ NULL);
+ ret = check ();
+ /**
+ * Need to remove base directory, subdirectories taken care
+ * of by the testing framework.
+ */
+ return ret;
+}
+
+/* end of test_gns_twopeer.c */
diff --git a/src/gns/test_gns_simple_zkey_lookup.c b/src/gns/test_gns_simple_zkey_lookup.c
new file mode 100644
index 0000000..8b9b78b
--- /dev/null
+++ b/src/gns/test_gns_simple_zkey_lookup.c
@@ -0,0 +1,358 @@
+/*
+ This file is part of GNUnet.
+ (C) 2009 Christian Grothoff (and other contributing authors)
+
+ GNUnet is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 3, or (at your
+ option) any later version.
+
+ GNUnet is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GNUnet; see the file COPYING. If not, write to the
+ Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+/**
+ * @file gns/test_gns_simple_zkey_lookup.c
+ * @brief base testcase for testing zkey lookup
+ *
+ */
+#include "platform.h"
+#include "gnunet_testing_lib.h"
+#include "gnunet_core_service.h"
+#include "block_dns.h"
+#include "gnunet_signatures.h"
+#include "gnunet_namestore_service.h"
+#include "../namestore/namestore.h"
+#include "gnunet_dnsparser_lib.h"
+#include "gnunet_gns_service.h"
+#include "gns.h"
+
+/* DEFINES */
+#define VERBOSE GNUNET_YES
+
+/* Timeout for entire testcase */
+#define TIMEOUT GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_SECONDS, 20)
+
+/* If number of peers not in config file, use this number */
+#define DEFAULT_NUM_PEERS 2
+
+/* test records to resolve */
+#define TEST_IP "127.0.0.1"
+#define TEST_RECORD_NAME "www"
+
+#define TEST_AUTHORITY_NAME "bob"
+
+#define KEYFILE_BOB "../namestore/zonefiles/HGU0A0VCU334DN7F2I9UIUMVQMM7JMSD142LIMNUGTTV9R0CF4EG.zkey"
+
+/* Globals */
+
+/**
+ * Directory to store temp data in, defined in config file
+ */
+static char *test_directory;
+
+static struct GNUNET_TESTING_PeerGroup *pg;
+
+/* Task handle to use to schedule test failure */
+GNUNET_SCHEDULER_TaskIdentifier die_task;
+
+/* Global return value (0 for success, anything else for failure) */
+static int ok;
+
+static struct GNUNET_NAMESTORE_Handle *namestore_handle;
+
+static struct GNUNET_GNS_Handle *gns_handle;
+
+const struct GNUNET_CONFIGURATION_Handle *cfg;
+
+struct GNUNET_CRYPTO_ShortHashCode bob_hash;
+
+/**
+ * Check whether peers successfully shut down.
+ */
+void
+shutdown_callback (void *cls, const char *emsg)
+{
+ if (emsg != NULL)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Error on shutdown! ret=%d\n", ok);
+ if (ok == 0)
+ ok = 2;
+ }
+
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO, "done(ret=%d)!\n", ok);
+}
+
+static void
+on_lookup_result(void *cls, uint32_t rd_count,
+ const struct GNUNET_NAMESTORE_RecordData *rd)
+{
+ struct in_addr a;
+ int i;
+ char* addr;
+
+ if (rd_count == 0)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "Lookup failed, rp_filtering?\n");
+ ok = 2;
+ }
+ else
+ {
+ ok = 1;
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO, "name: %s\n", (char*)cls);
+ for (i=0; i<rd_count; i++)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO, "type: %d\n", rd[i].record_type);
+ if (rd[i].record_type == GNUNET_GNS_RECORD_TYPE_A)
+ {
+ memcpy(&a, rd[i].data, sizeof(a));
+ addr = inet_ntoa(a);
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO, "address: %s\n", addr);
+ if (0 == strcmp(addr, TEST_IP))
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+ "ZKEY correctly resolved to %s!\n", addr);
+ ok = 0;
+ }
+ }
+ else
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "No resolution!\n");
+ }
+ }
+ }
+ GNUNET_GNS_disconnect(gns_handle);
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Shutting down peer1!\n");
+ GNUNET_TESTING_daemons_stop (pg, TIMEOUT, &shutdown_callback, NULL);
+}
+
+
+/**
+ * Function scheduled to be run on the successful start of services
+ * tries to look up the dns record for TEST_DOMAIN
+ */
+static void
+commence_testing (void *cls, int32_t success, const char *emsg)
+{
+ char name[MAX_DNS_NAME_LENGTH];
+ char* pos;
+ struct GNUNET_CRYPTO_ShortHashAsciiEncoded hash_str;
+
+ GNUNET_NAMESTORE_disconnect(namestore_handle, GNUNET_YES);
+
+ gns_handle = GNUNET_GNS_connect(cfg);
+
+ if (NULL == gns_handle)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "Failed to connect to GNS!\n");
+ }
+
+ pos = name;
+ strcpy(pos, TEST_RECORD_NAME);
+ pos += strlen(TEST_RECORD_NAME);
+ strcpy(pos, ".");
+ pos++;
+ GNUNET_CRYPTO_short_hash_to_enc(&bob_hash, &hash_str);
+ strcpy(pos, (char*)&hash_str);
+ pos += strlen((char*)&hash_str);
+ strcpy(pos, ".");
+ pos++;
+ strcpy(pos, GNUNET_GNS_TLD_ZKEY);
+
+ GNUNET_GNS_lookup(gns_handle, name, GNUNET_GNS_RECORD_TYPE_A,
+ &on_lookup_result, NULL);
+}
+
+/**
+ * Continuation for the GNUNET_DHT_get_stop call, so that we don't shut
+ * down the peers without freeing memory associated with GET request.
+ */
+static void
+end_badly_cont (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
+{
+
+ if (pg != NULL)
+ GNUNET_TESTING_daemons_stop (pg, TIMEOUT, &shutdown_callback, NULL);
+ GNUNET_SCHEDULER_cancel (die_task);
+}
+
+/**
+ * Check if the get_handle is being used, if so stop the request. Either
+ * way, schedule the end_badly_cont function which actually shuts down the
+ * test.
+ */
+static void
+end_badly (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
+{
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Failing test with error: `%s'!\n",
+ (char *) cls);
+ GNUNET_SCHEDULER_add_now (&end_badly_cont, NULL);
+ ok = 1;
+}
+
+static void
+do_lookup(void *cls, const struct GNUNET_PeerIdentity *id,
+ const struct GNUNET_CONFIGURATION_Handle *_cfg,
+ struct GNUNET_TESTING_Daemon *d, const char *emsg)
+{
+ struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded alice_pkey;
+ struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded bob_pkey;
+ struct GNUNET_CRYPTO_RsaPrivateKey *alice_key;
+ struct GNUNET_CRYPTO_RsaPrivateKey *bob_key;
+ struct GNUNET_CRYPTO_RsaSignature *sig;
+ char* alice_keyfile;
+
+ cfg = _cfg;
+
+ GNUNET_SCHEDULER_cancel (die_task);
+
+ /* put records into namestore */
+ namestore_handle = GNUNET_NAMESTORE_connect(cfg);
+ if (NULL == namestore_handle)
+ {
+ GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Failed to connect to namestore\n");
+ ok = -1;
+ return;
+ }
+
+ if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_filename (cfg, "gns",
+ "ZONEKEY",
+ &alice_keyfile))
+ {
+ GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Failed to get key from cfg\n");
+ ok = -1;
+ return;
+ }
+
+ alice_key = GNUNET_CRYPTO_rsa_key_create_from_file (alice_keyfile);
+ bob_key = GNUNET_CRYPTO_rsa_key_create_from_file (KEYFILE_BOB);
+
+ GNUNET_CRYPTO_rsa_key_get_public (alice_key, &alice_pkey);
+ GNUNET_CRYPTO_rsa_key_get_public (bob_key, &bob_pkey);
+
+ struct GNUNET_NAMESTORE_RecordData rd;
+ char* ip = TEST_IP;
+ struct in_addr *web = GNUNET_malloc(sizeof(struct in_addr));
+ rd.expiration = GNUNET_TIME_UNIT_FOREVER_ABS;
+ GNUNET_assert(1 == inet_pton (AF_INET, ip, web));
+
+ GNUNET_CRYPTO_short_hash(&bob_pkey, sizeof(bob_pkey), &bob_hash);
+
+ rd.data_size = sizeof(struct GNUNET_CRYPTO_ShortHashCode);
+ rd.data = &bob_hash;
+ rd.record_type = GNUNET_GNS_RECORD_PKEY;
+
+ GNUNET_NAMESTORE_record_create (namestore_handle,
+ alice_key,
+ TEST_AUTHORITY_NAME,
+ &rd,
+ NULL,
+ NULL);
+
+ rd.data_size = sizeof(struct in_addr);
+ rd.data = web;
+ rd.record_type = GNUNET_DNSPARSER_TYPE_A;
+ sig = GNUNET_NAMESTORE_create_signature(bob_key,
+ GNUNET_TIME_UNIT_FOREVER_ABS,
+ TEST_RECORD_NAME,
+ &rd, 1);
+
+ GNUNET_NAMESTORE_record_put (namestore_handle,
+ &bob_pkey,
+ TEST_RECORD_NAME,
+ rd.expiration,
+ 1,
+ &rd,
+ sig,
+ &commence_testing,
+ NULL);
+ GNUNET_free(sig);
+ GNUNET_CRYPTO_rsa_key_free(bob_key);
+ GNUNET_CRYPTO_rsa_key_free(alice_key);
+}
+
+static void
+run (void *cls, char *const *args, const char *cfgfile,
+ const struct GNUNET_CONFIGURATION_Handle *c)
+{
+ cfg = c;
+ /* Get path from configuration file */
+ if (GNUNET_YES !=
+ GNUNET_CONFIGURATION_get_value_string (cfg, "paths", "servicehome",
+ &test_directory))
+ {
+ ok = 404;
+ return;
+ }
+
+
+ /* Set up a task to end testing if peer start fails */
+ die_task =
+ GNUNET_SCHEDULER_add_delayed (TIMEOUT, &end_badly,
+ "didn't start all daemons in reasonable amount of time!!!");
+
+ /* Start alice */
+ pg = GNUNET_TESTING_daemons_start(cfg, 1, 1, 1, TIMEOUT,
+ NULL, NULL, &do_lookup, NULL,
+ NULL, NULL, NULL);
+}
+
+static int
+check ()
+{
+ int ret;
+
+ /* Arguments for GNUNET_PROGRAM_run */
+ char *const argv[] = { "test-gns-simple-delegated-lookup", /* Name to give running binary */
+ "-c",
+ "test_gns_simple_lookup.conf", /* Config file to use */
+#if VERBOSE
+ "-L", "DEBUG",
+#endif
+ NULL
+ };
+ struct GNUNET_GETOPT_CommandLineOption options[] = {
+ GNUNET_GETOPT_OPTION_END
+ };
+ /* Run the run function as a new program */
+ ret =
+ GNUNET_PROGRAM_run ((sizeof (argv) / sizeof (char *)) - 1, argv,
+ "test-gns-simple-delegated-lookup", "nohelp", options, &run,
+ &ok);
+ if (ret != GNUNET_OK)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+ "`test-gns-simple-delegated-lookup': Failed with error code %d\n", ret);
+ }
+ return ok;
+}
+
+int
+main (int argc, char *argv[])
+{
+ int ret;
+
+ GNUNET_log_setup ("test-gns-simple-lookup",
+#if VERBOSE
+ "DEBUG",
+#else
+ "WARNING",
+#endif
+ NULL);
+ ret = check ();
+ /**
+ * Need to remove base directory, subdirectories taken care
+ * of by the testing framework.
+ */
+ return ret;
+}
+
+/* end of test_gns_twopeer.c */
diff --git a/src/gns/test_gns_twopeer.c b/src/gns/test_gns_twopeer.c
deleted file mode 100644
index 3bd36fb..0000000
--- a/src/gns/test_gns_twopeer.c
+++ /dev/null
@@ -1,463 +0,0 @@
-/*
- This file is part of GNUnet.
- (C) 2009 Christian Grothoff (and other contributing authors)
-
- GNUnet is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published
- by the Free Software Foundation; either version 3, or (at your
- option) any later version.
-
- GNUnet is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with GNUnet; see the file COPYING. If not, write to the
- Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- Boston, MA 02111-1307, USA.
-*/
-/**
- * @file gns/test_gns_twopeer.c
- * @brief base testcase for testing DHT service with
- * two running peers.
- *
- * This testcase starts peers using the GNUNET_TESTING_daemons_start
- * function call. On peer start, connects to the peers DHT service
- * by calling GNUNET_DHT_connected. Once notified about all peers
- * being started (by the peers_started_callback function), calls
- * GNUNET_TESTING_connect_topology, which connects the peers in a
- * "straight line" topology. On notification that all peers have
- * been properly connected, calls the do_get function which initiates
- * a GNUNET_DHT_get from the *second* peer. Once the GNUNET_DHT_get
- * function starts, runs the do_put function to insert data at the first peer.
- * If the GET is successful, schedules finish_testing
- * to stop the test and shut down peers. If GET is unsuccessful
- * after GET_TIMEOUT seconds, prints an error message and shuts down
- * the peers.
- */
-#include "platform.h"
-#include "gnunet_testing_lib.h"
-#include "gnunet_core_service.h"
-#include "gnunet_dht_service.h"
-#include "block_dns.h"
-#include "gnunet_signatures.h"
-
-/* DEFINES */
-#define VERBOSE GNUNET_YES
-
-/* Timeout for entire testcase */
-#define TIMEOUT GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_SECONDS, 40)
-
-/* If number of peers not in config file, use this number */
-#define DEFAULT_NUM_PEERS 2
-
-/* Globals */
-
-/**
- * Directory to store temp data in, defined in config file
- */
-static char *test_directory;
-
-/**
- * Variable used to store the number of connections we should wait for.
- */
-static unsigned int expected_connections;
-
-/**
- * Variable used to keep track of how many peers aren't yet started.
- */
-static unsigned long long peers_left;
-
-struct GNUNET_TESTING_Daemon *d1;
-struct GNUNET_TESTING_Daemon *d2;
-
-
-/**
- * Total number of peers to run, set based on config file.
- */
-static unsigned long long num_peers;
-
-/**
- * Global used to count how many connections we have currently
- * been notified about (how many times has topology_callback been called
- * with success?)
- */
-static unsigned int total_connections;
-
-/**
- * Global used to count how many failed connections we have
- * been notified about (how many times has topology_callback
- * been called with failure?)
- */
-static unsigned int failed_connections;
-
-/* Task handle to use to schedule test failure */
-GNUNET_SCHEDULER_TaskIdentifier die_task;
-
-GNUNET_SCHEDULER_TaskIdentifier bob_task;
-
-/* Global return value (0 for success, anything else for failure) */
-static int ok;
-
-int bob_online, alice_online;
-
-/**
- * Check whether peers successfully shut down.
- */
-void
-shutdown_callback (void *cls, const char *emsg)
-{
- if (emsg != NULL)
- {
- if (ok == 0)
- ok = 2;
- }
-}
-
-/**
- * Function scheduled to be run on the successful completion of this
- * testcase. Specifically, called when our get request completes.
- */
-static void
-finish_testing (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
-{
- ok = 0;
- GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Shutting down peer1!\n");
- GNUNET_TESTING_daemon_stop (d1, TIMEOUT, &shutdown_callback, NULL,
- GNUNET_YES, GNUNET_NO);
- GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Shutting down peer2!\n");
- GNUNET_TESTING_daemon_stop (d2, TIMEOUT, &shutdown_callback, NULL,
- GNUNET_YES, GNUNET_NO);
- GNUNET_SCHEDULER_cancel(bob_task);
- GNUNET_SCHEDULER_cancel(die_task);
-}
-
-/**
- * Continuation for the GNUNET_DHT_get_stop call, so that we don't shut
- * down the peers without freeing memory associated with GET request.
- */
-static void
-end_badly_cont (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
-{
- if (d1 != NULL)
- GNUNET_TESTING_daemon_stop (d1, TIMEOUT, &shutdown_callback, NULL,
- GNUNET_YES, GNUNET_NO);
- if (d2 != NULL)
- GNUNET_TESTING_daemon_stop (d2, TIMEOUT, &shutdown_callback, NULL,
- GNUNET_YES, GNUNET_NO);
-}
-
-/**
- * Check if the get_handle is being used, if so stop the request. Either
- * way, schedule the end_badly_cont function which actually shuts down the
- * test.
- */
-static void
-end_badly (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
-{
- GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Failing test with error: `%s'!\n",
- (char *) cls);
- GNUNET_SCHEDULER_cancel(bob_task);
- GNUNET_SCHEDULER_add_now (&end_badly_cont, NULL);
- ok = 1;
-}
-
-static void
-do_lookup(void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
-{
- //do lookup here
- GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply
- (GNUNET_TIME_UNIT_SECONDS, 30),
- &finish_testing, NULL);
-}
-
-static void
-gns_started(void *cls, const struct GNUNET_PeerIdentity *id,
- const struct GNUNET_CONFIGURATION_Handle *cfg,
- struct GNUNET_TESTING_Daemon *d, const char *emsg)
-{
- if (NULL != emsg)
- {
- if (d == d1)
- GNUNET_log (GNUNET_ERROR_TYPE_INFO, "GNS failed to start alice\n");
- else
- GNUNET_log (GNUNET_ERROR_TYPE_INFO, "GNS failed to start bob\n");
- return;
- }
- if (d == d1)
- {
- /* start gns for bob */
- GNUNET_log (GNUNET_ERROR_TYPE_INFO, "GNS started on alice\n");
- GNUNET_TESTING_daemon_start_service (d2, "gns", TIMEOUT, &gns_started,
- NULL);
- return;
- }
-
- GNUNET_log (GNUNET_ERROR_TYPE_INFO, "GNS started on bob\n");
-
- /* start the lookup tests */
- GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply
- (GNUNET_TIME_UNIT_SECONDS, 1),
- &do_lookup, NULL);
-}
-
-/**
- * This function is called whenever a connection attempt is finished between two of
- * the started peers (started with GNUNET_TESTING_daemons_start). The total
- * number of times this function is called should equal the number returned
- * from the GNUNET_TESTING_connect_topology call.
- *
- * The emsg variable is NULL on success (peers connected), and non-NULL on
- * failure (peers failed to connect).
- */
-void
-notify_connect (void *cls, const struct GNUNET_PeerIdentity *first,
- const struct GNUNET_PeerIdentity *second, uint32_t distance,
- const struct GNUNET_CONFIGURATION_Handle *first_cfg,
- const struct GNUNET_CONFIGURATION_Handle *second_cfg,
- struct GNUNET_TESTING_Daemon *first_daemon,
- struct GNUNET_TESTING_Daemon *second_daemon,
- const char *emsg)
-{
- if (emsg == NULL)
- {
- total_connections++;
-#if VERBOSE
- GNUNET_log (GNUNET_ERROR_TYPE_INFO,
- "connected peer %s to peer %s, distance %u\n",
- first_daemon->shortname, second_daemon->shortname, distance);
-#endif
- }
-#if VERBOSE
- else
- {
- failed_connections++;
- GNUNET_log (GNUNET_ERROR_TYPE_INFO,
- "Failed to connect peer %s to peer %s with error :\n%s\n",
- first_daemon->shortname, second_daemon->shortname, emsg);
- }
-#endif
-
- if (total_connections == expected_connections)
- {
-#if VERBOSE
- GNUNET_log (GNUNET_ERROR_TYPE_INFO,
- "Created %d total connections, which is our target number! Starting next phase of testing.\n",
- total_connections);
-#endif
- GNUNET_SCHEDULER_cancel (die_task);
- die_task =
- GNUNET_SCHEDULER_add_delayed (TIMEOUT, &end_badly, "from test lookup");
-
- /* start gns for alice */
- GNUNET_TESTING_daemon_start_service (d1, "gns", TIMEOUT, &gns_started, NULL);
-
- }
- else if (total_connections + failed_connections == expected_connections)
- {
- GNUNET_SCHEDULER_cancel (die_task);
- die_task =
- GNUNET_SCHEDULER_add_now (&end_badly,
- "from topology_callback (too many failed connections)");
- }
-}
-
-/**
- * Set up some data, and call API PUT function
- */
-static void
-alice_idle (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
-{
-
- alice_online = 1;
- if (!bob_online)
- {
- GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply
- (GNUNET_TIME_UNIT_SECONDS, 2),
- &alice_idle, NULL);
- return;
- }
-
- GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Connecting peers\n");
- GNUNET_TESTING_daemons_connect (d1, d2, TIMEOUT, 5, 1,
- &notify_connect, NULL);
-}
-
-static void
-bob_idle (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
-{
- /* he's lazy FIXME forever */
- bob_online = 1;
- bob_task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply
- (GNUNET_TIME_UNIT_SECONDS, 20),
- &bob_idle, NULL);
-}
-
-
-
-
-/**
- * Callback which is called whenever a peer is started (as a result of the
- * GNUNET_TESTING_daemons_start call.
- *
- * @param cls closure argument given to GNUNET_TESTING_daemons_start
- * @param id the GNUNET_PeerIdentity of the started peer
- * @param cfg the configuration for this specific peer (needed to connect
- * to the DHT)
- * @param d the handle to the daemon started
- * @param emsg NULL if peer started, non-NULL on error
- */
-static void
-alice_started (void *cls, const struct GNUNET_PeerIdentity *id,
- const struct GNUNET_CONFIGURATION_Handle *cfg,
- struct GNUNET_TESTING_Daemon *d, const char *emsg)
-{
- if (emsg != NULL)
- {
- GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
- "Failed to start daemon with error: `%s'\n", emsg);
- return;
- }
- GNUNET_assert (id != NULL);
-
- GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply
- (GNUNET_TIME_UNIT_SECONDS, 2),
- &alice_idle, NULL);
-}
-
-static void
-bob_started (void *cls, const struct GNUNET_PeerIdentity *id,
- const struct GNUNET_CONFIGURATION_Handle *cfg,
- struct GNUNET_TESTING_Daemon *d, const char *emsg)
-{
- if (emsg != NULL)
- {
- GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
- "Failed to start daemon with error: `%s'\n", emsg);
- return;
- }
- GNUNET_assert (id != NULL);
-
- GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply
- (GNUNET_TIME_UNIT_SECONDS, 2),
- &bob_idle, NULL);
-}
-
-static void
-run (void *cls, char *const *args, const char *cfgfile,
- const struct GNUNET_CONFIGURATION_Handle *cfg)
-{
-
- /* Get path from configuration file */
- if (GNUNET_YES !=
- GNUNET_CONFIGURATION_get_value_string (cfg, "paths", "servicehome",
- &test_directory))
- {
- ok = 404;
- return;
- }
-
- /* Get number of peers to start from configuration (should be two) */
- if (GNUNET_SYSERR ==
- GNUNET_CONFIGURATION_get_value_number (cfg, "testing", "num_peers",
- &num_peers))
- num_peers = DEFAULT_NUM_PEERS;
-
- /* Set peers_left so we know when all peers started */
- peers_left = num_peers;
-
- /* Set up a task to end testing if peer start fails */
- die_task =
- GNUNET_SCHEDULER_add_delayed (TIMEOUT, &end_badly,
- "didn't start all daemons in reasonable amount of time!!!");
-
- alice_online = 0;
- bob_online = 0;
- expected_connections = 1;
-
- /* Start alice */
- d1 = GNUNET_TESTING_daemon_start(cfg, TIMEOUT, GNUNET_NO, NULL, NULL, 0,
- NULL, NULL, NULL, &alice_started, NULL);
-
- /* Somebody care to explain? */
- uint16_t port = 6000;
- uint32_t upnum = 23;
- uint32_t fdnum = 42;
-
-
- /**
- * Modify some config options for bob
- * namely swap keys and disable dns hijacking
- */
- struct GNUNET_CONFIGURATION_Handle *cfg2 = GNUNET_TESTING_create_cfg(cfg,
- 23, &port, &upnum,
- NULL, &fdnum);
-
- GNUNET_CONFIGURATION_set_value_string (cfg2, "paths", "servicehome",
- "/tmp/test-gnunetd-gns-peer-2/");
- GNUNET_CONFIGURATION_set_value_string (cfg2, "gns", "HIJACK_DNS",
- "NO");
- GNUNET_CONFIGURATION_set_value_string (cfg2, "gns", "ZONEKEY",
- "/tmp/bobkey");
- GNUNET_CONFIGURATION_set_value_string (cfg2, "gns", "TRUSTED",
- "alice:/tmp/alicekey");
-
- //Start bob
- d2 = GNUNET_TESTING_daemon_start(cfg2, TIMEOUT, GNUNET_NO, NULL, NULL, 0,
- NULL, NULL, NULL, &bob_started, NULL);
-
-
-}
-
-static int
-check ()
-{
- int ret;
-
- /* Arguments for GNUNET_PROGRAM_run */
- char *const argv[] = { "test-gns-twopeer", /* Name to give running binary */
- "-c",
- "test_gns_twopeer.conf", /* Config file to use */
-#if VERBOSE
- "-L", "DEBUG",
-#endif
- NULL
- };
- struct GNUNET_GETOPT_CommandLineOption options[] = {
- GNUNET_GETOPT_OPTION_END
- };
- /* Run the run function as a new program */
- ret =
- GNUNET_PROGRAM_run ((sizeof (argv) / sizeof (char *)) - 1, argv,
- "test-gns-twopeer", "nohelp", options, &run,
- &ok);
- if (ret != GNUNET_OK)
- {
- GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
- "`test-gns-twopeer': Failed with error code %d\n", ret);
- }
- return ok;
-}
-
-int
-main (int argc, char *argv[])
-{
- int ret;
-
- GNUNET_log_setup ("test-gns-twopeer",
-#if VERBOSE
- "DEBUG",
-#else
- "WARNING",
-#endif
- NULL);
- ret = check ();
- /**
- * Need to remove base directory, subdirectories taken care
- * of by the testing framework.
- */
- return ret;
-}
-
-/* end of test_gns_twopeer.c */
diff --git a/src/gns/test_gns_twopeer.conf b/src/gns/test_gns_twopeer.conf
deleted file mode 100644
index 4048297..0000000
--- a/src/gns/test_gns_twopeer.conf
+++ /dev/null
@@ -1,80 +0,0 @@
-[fs]
-AUTOSTART = NO
-
-[resolver]
-AUTOSTART = NO
-
-[dht]
-DEBUG = NO
-AUTOSTART = YES
-ACCEPT_FROM6 = ::1;
-ACCEPT_FROM = 127.0.0.1;
-HOSTNAME = localhost
-PORT = 2100
-BINARY = gnunet-service-dht
-
-[block]
-plugins = dht test gns
-
-[dhtcache]
-QUOTA = 1 MB
-DATABASE = sqlite
-
-[transport]
-PLUGINS = tcp
-DEBUG = NO
-ACCEPT_FROM6 = ::1;
-ACCEPT_FROM = 127.0.0.1;
-NEIGHBOUR_LIMIT = 50
-PORT = 12365
-
-[ats]
-WAN_QUOTA_IN = 1 GB
-WAN_QUOTA_OUT = 1 GB
-
-[core]
-PORT = 12092
-
-[arm]
-DEFAULTSERVICES = core
-PORT = 12366
-DEBUG = NO
-
-[transport-tcp]
-TIMEOUT = 300 s
-PORT = 12368
-BINDTO = 127.0.0.1
-
-[TESTING]
-WEAKRANDOM = YES
-
-[gnunetd]
-HOSTKEY = $SERVICEHOME/.hostkey
-
-[PATHS]
-DEFAULTCONFIG = gns.conf
-SERVICEHOME = /tmp/test-gnunetd-gns-peer-1/
-
-
-[nat]
-DISABLEV6 = YES
-ENABLE_UPNP = NO
-BEHIND_NAT = NO
-ALLOW_NAT = NO
-INTERNAL_ADDRESS = 127.0.0.1
-EXTERNAL_ADDRESS = 127.0.0.1
-USE_LOCALADDR = NO
-
-[dns]
-AUTOSTART = YES
-
-[gns]
-AUTOSTART = YES
-BINARY = gnunet-service-gns
-ZONEKEY = /tmp/alicekey
-
-
-[nse]
-AUTOSTART = NO
-
-
diff --git a/src/gns/test_gnunet_gns.sh b/src/gns/test_gnunet_gns.sh
deleted file mode 100755
index cd68027..0000000
--- a/src/gns/test_gnunet_gns.sh
+++ /dev/null
@@ -1,22 +0,0 @@
-#!/bin/bash
-
-ME=`whoami`
-if [ "$ME" != "root" ]
-then
- echo "This test only works if run as root. Skipping."
- exit 0
-fi
-export PATH=".:$PATH"
-gnunet-service-gns -c gns.conf &
-sleep 1
-LO=`nslookup alice.gnunet | grep Address | tail -n1`
-if [ "$LO" != "Address: 1.2.3.4" ]
-then
- echo "Fail: $LO"
-fi
-LO=`nslookup www.bob.gnunet | grep Address | tail -n1`
-if [ "$LO" != "Address: 4.5.6.7" ]
-then
- echo "Fail: $LO"
-fi
-kill `jobs -p`