aboutsummaryrefslogtreecommitdiff
path: root/src/gns
diff options
context:
space:
mode:
authorBertrand Marc <beberking@gmail.com>2012-05-02 21:43:37 +0200
committerBertrand Marc <beberking@gmail.com>2012-05-02 21:43:37 +0200
commit2b81464a43485fcc8ce079fafdee7b7a171835f4 (patch)
tree394774c0f735199b57d51a2d3840356317853fe1 /src/gns
Imported Upstream version 0.9.2upstream/0.9.2
Diffstat (limited to 'src/gns')
-rw-r--r--src/gns/Makefile.am113
-rw-r--r--src/gns/Makefile.in998
-rw-r--r--src/gns/gns.conf.in17
-rw-r--r--src/gns/gns.h97
-rw-r--r--src/gns/gns_api.c635
-rw-r--r--src/gns/gnunet-service-gns.c1399
-rw-r--r--src/gns/namestore_stub_api.c438
-rw-r--r--src/gns/plugin_block_gns.c226
-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
11 files changed, 4488 insertions, 0 deletions
diff --git a/src/gns/Makefile.am b/src/gns/Makefile.am
new file mode 100644
index 0000000..cc19939
--- /dev/null
+++ b/src/gns/Makefile.am
@@ -0,0 +1,113 @@
+INCLUDES = -I$(top_srcdir)/src/include
+
+if MINGW
+ WINFLAGS = -Wl,--no-undefined -Wl,--export-all-symbols
+endif
+
+if USE_COVERAGE
+ AM_CFLAGS = --coverage -O0
+endif
+
+pkgcfgdir= $(pkgdatadir)/config.d/
+
+plugindir = $(libdir)/gnunet
+
+pkgcfg_DATA = \
+ gns.conf
+
+lib_LTLIBRARIES = \
+ libgnunetgns.la libgnunetnamestore.la
+
+bin_PROGRAMS = \
+ gnunet-service-gns
+
+#noinst_PROGRAMS = \
+# gnunet-gns-lookup
+
+check_SCRIPTS = \
+ test_gnunet_gns.sh
+
+check_PROGRAMS = \
+ test_gns_twopeer
+
+
+plugin_LTLIBRARIES = \
+ libgnunet_plugin_block_gns.la
+
+test_gns_twopeer_SOURCES = \
+ test_gns_twopeer.c
+test_gns_twopeer_LDADD = \
+ $(top_builddir)/src/util/libgnunetutil.la \
+ $(top_builddir)/src/testing/libgnunettesting.la
+test_gns_twopeer_DEPENDENCIES = \
+ $(top_builddir)/src/util/libgnunetutil.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
+
+gnunet_service_gns_SOURCES = \
+ gnunet-service-gns.c
+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 \
+ $(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
+
+libgnunetgns_la_SOURCES = \
+ gns_api.c gns.h
+libgnunetgns_la_LIBADD = \
+ $(top_builddir)/src/util/libgnunetutil.la $(XLIB)
+libgnunetgns_la_LDFLAGS = \
+ $(GN_LIB_LDFLAGS)
+libgnunetgns_la_DEPENDENCIES = \
+ $(top_builddir)/src/util/libgnunetutil.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
+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
+
+#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
+
+if ENABLE_TEST_RUN
+TESTS = $(check_PROGRAMS) $(check_SCRIPTS)
+endif
+
+EXTRA_DIST = \
+ $(check_SCRIPTS) \
+ test_gns_twopeer.conf
diff --git a/src/gns/Makefile.in b/src/gns/Makefile.in
new file mode 100644
index 0000000..87422ab
--- /dev/null
+++ b/src/gns/Makefile.in
@@ -0,0 +1,998 @@
+# 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@
+
+
+
+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@
+bin_PROGRAMS = gnunet-service-gns$(EXEEXT)
+check_PROGRAMS = test_gns_twopeer$(EXEEXT)
+subdir = src/gns
+DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in \
+ $(srcdir)/gns.conf.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 = gns.conf
+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)$(libdir)" "$(DESTDIR)$(plugindir)" \
+ "$(DESTDIR)$(bindir)" "$(DESTDIR)$(pkgcfgdir)"
+LTLIBRARIES = $(lib_LTLIBRARIES) $(plugin_LTLIBRARIES)
+am_libgnunet_plugin_block_gns_la_OBJECTS = plugin_block_gns.lo
+libgnunet_plugin_block_gns_la_OBJECTS = \
+ $(am_libgnunet_plugin_block_gns_la_OBJECTS)
+AM_V_lt = $(am__v_lt_$(V))
+am__v_lt_ = $(am__v_lt_$(AM_DEFAULT_VERBOSITY))
+am__v_lt_0 = --silent
+libgnunet_plugin_block_gns_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \
+ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \
+ $(AM_CFLAGS) $(CFLAGS) \
+ $(libgnunet_plugin_block_gns_la_LDFLAGS) $(LDFLAGS) -o $@
+am_libgnunetgns_la_OBJECTS = gns_api.lo
+libgnunetgns_la_OBJECTS = $(am_libgnunetgns_la_OBJECTS)
+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 $@
+PROGRAMS = $(bin_PROGRAMS)
+am_gnunet_service_gns_OBJECTS = gnunet-service-gns.$(OBJEXT)
+gnunet_service_gns_OBJECTS = $(am_gnunet_service_gns_OBJECTS)
+am__DEPENDENCIES_1 =
+am_test_gns_twopeer_OBJECTS = test_gns_twopeer.$(OBJEXT)
+test_gns_twopeer_OBJECTS = $(am_test_gns_twopeer_OBJECTS)
+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 = $(libgnunet_plugin_block_gns_la_SOURCES) \
+ $(libgnunetgns_la_SOURCES) $(libgnunetnamestore_la_SOURCES) \
+ $(gnunet_service_gns_SOURCES) $(test_gns_twopeer_SOURCES)
+DIST_SOURCES = $(libgnunet_plugin_block_gns_la_SOURCES) \
+ $(libgnunetgns_la_SOURCES) $(libgnunetnamestore_la_SOURCES) \
+ $(gnunet_service_gns_SOURCES) $(test_gns_twopeer_SOURCES)
+DATA = $(pkgcfg_DATA)
+ETAGS = etags
+CTAGS = ctags
+am__tty_colors = \
+red=; grn=; lgn=; blu=; std=
+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@
+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 = @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@
+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@
+INCLUDES = -I$(top_srcdir)/src/include
+@MINGW_TRUE@WINFLAGS = -Wl,--no-undefined -Wl,--export-all-symbols
+@USE_COVERAGE_TRUE@AM_CFLAGS = --coverage -O0
+pkgcfgdir = $(pkgdatadir)/config.d/
+plugindir = $(libdir)/gnunet
+pkgcfg_DATA = \
+ gns.conf
+
+lib_LTLIBRARIES = \
+ libgnunetgns.la libgnunetnamestore.la
+
+
+#noinst_PROGRAMS = \
+# gnunet-gns-lookup
+check_SCRIPTS = \
+ test_gnunet_gns.sh
+
+plugin_LTLIBRARIES = \
+ libgnunet_plugin_block_gns.la
+
+test_gns_twopeer_SOURCES = \
+ test_gns_twopeer.c
+
+test_gns_twopeer_LDADD = \
+ $(top_builddir)/src/util/libgnunetutil.la \
+ $(top_builddir)/src/testing/libgnunettesting.la
+
+test_gns_twopeer_DEPENDENCIES = \
+ $(top_builddir)/src/util/libgnunetutil.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
+gnunet_service_gns_SOURCES = \
+ gnunet-service-gns.c
+
+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 \
+ $(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
+
+libgnunetgns_la_SOURCES = \
+ gns_api.c gns.h
+
+libgnunetgns_la_LIBADD = \
+ $(top_builddir)/src/util/libgnunetutil.la $(XLIB)
+
+libgnunetgns_la_LDFLAGS = \
+ $(GN_LIB_LDFLAGS)
+
+libgnunetgns_la_DEPENDENCIES = \
+ $(top_builddir)/src/util/libgnunetutil.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
+
+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
+
+
+#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)
+EXTRA_DIST = \
+ $(check_SCRIPTS) \
+ test_gns_twopeer.conf
+
+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/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --gnu src/gns/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):
+gns.conf: $(top_builddir)/config.status $(srcdir)/gns.conf.in
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@
+install-libLTLIBRARIES: $(lib_LTLIBRARIES)
+ @$(NORMAL_INSTALL)
+ test -z "$(libdir)" || $(MKDIR_P) "$(DESTDIR)$(libdir)"
+ @list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || 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)$(libdir)'"; \
+ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(libdir)"; \
+ }
+
+uninstall-libLTLIBRARIES:
+ @$(NORMAL_UNINSTALL)
+ @list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \
+ for p in $$list; do \
+ $(am__strip_dir) \
+ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(libdir)/$$f'"; \
+ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(libdir)/$$f"; \
+ done
+
+clean-libLTLIBRARIES:
+ -test -z "$(lib_LTLIBRARIES)" || rm -f $(lib_LTLIBRARIES)
+ @list='$(lib_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
+install-pluginLTLIBRARIES: $(plugin_LTLIBRARIES)
+ @$(NORMAL_INSTALL)
+ test -z "$(plugindir)" || $(MKDIR_P) "$(DESTDIR)$(plugindir)"
+ @list='$(plugin_LTLIBRARIES)'; test -n "$(plugindir)" || 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)$(plugindir)'"; \
+ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(plugindir)"; \
+ }
+
+uninstall-pluginLTLIBRARIES:
+ @$(NORMAL_UNINSTALL)
+ @list='$(plugin_LTLIBRARIES)'; test -n "$(plugindir)" || list=; \
+ for p in $$list; do \
+ $(am__strip_dir) \
+ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(plugindir)/$$f'"; \
+ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(plugindir)/$$f"; \
+ done
+
+clean-pluginLTLIBRARIES:
+ -test -z "$(plugin_LTLIBRARIES)" || rm -f $(plugin_LTLIBRARIES)
+ @list='$(plugin_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
+libgnunet_plugin_block_gns.la: $(libgnunet_plugin_block_gns_la_OBJECTS) $(libgnunet_plugin_block_gns_la_DEPENDENCIES)
+ $(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)"
+ @list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \
+ for p in $$list; do echo "$$p $$p"; done | \
+ sed 's/$(EXEEXT)$$//' | \
+ while read p p1; do if test -f $$p || test -f $$p1; \
+ then echo "$$p"; echo "$$p"; else :; fi; \
+ done | \
+ sed -e 'p;s,.*/,,;n;h' -e 's|.*|.|' \
+ -e 'p;x;s,.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/' | \
+ sed 'N;N;N;s,\n, ,g' | \
+ $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1 } \
+ { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \
+ if ($$2 == $$4) files[d] = files[d] " " $$1; \
+ else { print "f", $$3 "/" $$4, $$1; } } \
+ END { for (d in files) print "f", d, files[d] }' | \
+ while read type dir files; do \
+ if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \
+ test -z "$$files" || { \
+ echo " $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files '$(DESTDIR)$(bindir)$$dir'"; \
+ $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(bindir)$$dir" || exit $$?; \
+ } \
+ ; done
+
+uninstall-binPROGRAMS:
+ @$(NORMAL_UNINSTALL)
+ @list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \
+ files=`for p in $$list; do echo "$$p"; done | \
+ sed -e 'h;s,^.*/,,;s/$(EXEEXT)$$//;$(transform)' \
+ -e 's/$$/$(EXEEXT)/' `; \
+ test -n "$$list" || exit 0; \
+ echo " ( cd '$(DESTDIR)$(bindir)' && rm -f" $$files ")"; \
+ cd "$(DESTDIR)$(bindir)" && rm -f $$files
+
+clean-binPROGRAMS:
+ @list='$(bin_PROGRAMS)'; test -n "$$list" || exit 0; \
+ echo " rm -f" $$list; \
+ rm -f $$list || exit $$?; \
+ test -n "$(EXEEXT)" || exit 0; \
+ list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \
+ echo " rm -f" $$list; \
+ rm -f $$list
+
+clean-checkPROGRAMS:
+ @list='$(check_PROGRAMS)'; test -n "$$list" || exit 0; \
+ echo " rm -f" $$list; \
+ rm -f $$list || exit $$?; \
+ test -n "$(EXEEXT)" || exit 0; \
+ list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \
+ echo " rm -f" $$list; \
+ rm -f $$list
+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)
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+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-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)/plugin_block_gns.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_gns_twopeer.Po@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 $@ $<
+
+mostlyclean-libtool:
+ -rm -f *.lo
+
+clean-libtool:
+ -rm -rf .libs _libs
+install-pkgcfgDATA: $(pkgcfg_DATA)
+ @$(NORMAL_INSTALL)
+ test -z "$(pkgcfgdir)" || $(MKDIR_P) "$(DESTDIR)$(pkgcfgdir)"
+ @list='$(pkgcfg_DATA)'; test -n "$(pkgcfgdir)" || list=; \
+ for p in $$list; do \
+ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
+ echo "$$d$$p"; \
+ done | $(am__base_list) | \
+ while read files; do \
+ echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(pkgcfgdir)'"; \
+ $(INSTALL_DATA) $$files "$(DESTDIR)$(pkgcfgdir)" || exit $$?; \
+ done
+
+uninstall-pkgcfgDATA:
+ @$(NORMAL_UNINSTALL)
+ @list='$(pkgcfg_DATA)'; test -n "$(pkgcfgdir)" || list=; \
+ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \
+ test -n "$$files" || exit 0; \
+ echo " ( cd '$(DESTDIR)$(pkgcfgdir)' && rm -f" $$files ")"; \
+ cd "$(DESTDIR)$(pkgcfgdir)" && rm -f $$files
+
+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
+
+check-TESTS: $(TESTS)
+ @failed=0; all=0; xfail=0; xpass=0; skip=0; \
+ srcdir=$(srcdir); export srcdir; \
+ list=' $(TESTS) '; \
+ $(am__tty_colors); \
+ if test -n "$$list"; then \
+ for tst in $$list; do \
+ if test -f ./$$tst; then dir=./; \
+ elif test -f $$tst; then dir=; \
+ else dir="$(srcdir)/"; fi; \
+ if $(TESTS_ENVIRONMENT) $${dir}$$tst; then \
+ all=`expr $$all + 1`; \
+ case " $(XFAIL_TESTS) " in \
+ *[\ \ ]$$tst[\ \ ]*) \
+ xpass=`expr $$xpass + 1`; \
+ failed=`expr $$failed + 1`; \
+ col=$$red; res=XPASS; \
+ ;; \
+ *) \
+ col=$$grn; res=PASS; \
+ ;; \
+ esac; \
+ elif test $$? -ne 77; then \
+ all=`expr $$all + 1`; \
+ case " $(XFAIL_TESTS) " in \
+ *[\ \ ]$$tst[\ \ ]*) \
+ xfail=`expr $$xfail + 1`; \
+ col=$$lgn; res=XFAIL; \
+ ;; \
+ *) \
+ failed=`expr $$failed + 1`; \
+ col=$$red; res=FAIL; \
+ ;; \
+ esac; \
+ else \
+ skip=`expr $$skip + 1`; \
+ col=$$blu; res=SKIP; \
+ fi; \
+ echo "$${col}$$res$${std}: $$tst"; \
+ done; \
+ if test "$$all" -eq 1; then \
+ tests="test"; \
+ All=""; \
+ else \
+ tests="tests"; \
+ All="All "; \
+ fi; \
+ if test "$$failed" -eq 0; then \
+ if test "$$xfail" -eq 0; then \
+ banner="$$All$$all $$tests passed"; \
+ else \
+ if test "$$xfail" -eq 1; then failures=failure; else failures=failures; fi; \
+ banner="$$All$$all $$tests behaved as expected ($$xfail expected $$failures)"; \
+ fi; \
+ else \
+ if test "$$xpass" -eq 0; then \
+ banner="$$failed of $$all $$tests failed"; \
+ else \
+ if test "$$xpass" -eq 1; then passes=pass; else passes=passes; fi; \
+ banner="$$failed of $$all $$tests did not behave as expected ($$xpass unexpected $$passes)"; \
+ fi; \
+ fi; \
+ dashes="$$banner"; \
+ skipped=""; \
+ if test "$$skip" -ne 0; then \
+ if test "$$skip" -eq 1; then \
+ skipped="($$skip test was not run)"; \
+ else \
+ skipped="($$skip tests were not run)"; \
+ fi; \
+ test `echo "$$skipped" | wc -c` -le `echo "$$banner" | wc -c` || \
+ dashes="$$skipped"; \
+ fi; \
+ report=""; \
+ if test "$$failed" -ne 0 && test -n "$(PACKAGE_BUGREPORT)"; then \
+ report="Please report to $(PACKAGE_BUGREPORT)"; \
+ test `echo "$$report" | wc -c` -le `echo "$$banner" | wc -c` || \
+ dashes="$$report"; \
+ fi; \
+ dashes=`echo "$$dashes" | sed s/./=/g`; \
+ if test "$$failed" -eq 0; then \
+ echo "$$grn$$dashes"; \
+ else \
+ echo "$$red$$dashes"; \
+ fi; \
+ echo "$$banner"; \
+ test -z "$$skipped" || echo "$$skipped"; \
+ test -z "$$report" || echo "$$report"; \
+ echo "$$dashes$$std"; \
+ test "$$failed" -eq 0; \
+ else :; fi
+
+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
+ $(MAKE) $(AM_MAKEFLAGS) $(check_PROGRAMS) $(check_SCRIPTS)
+ $(MAKE) $(AM_MAKEFLAGS) check-TESTS
+check: check-am
+all-am: Makefile $(LTLIBRARIES) $(PROGRAMS) $(DATA)
+install-binPROGRAMS: install-libLTLIBRARIES
+
+installdirs:
+ 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-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-binPROGRAMS clean-checkPROGRAMS clean-generic \
+ clean-libLTLIBRARIES clean-libtool clean-pluginLTLIBRARIES \
+ 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-pkgcfgDATA install-pluginLTLIBRARIES
+
+install-dvi: install-dvi-am
+
+install-dvi-am:
+
+install-exec-am: install-binPROGRAMS install-libLTLIBRARIES
+
+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-binPROGRAMS uninstall-libLTLIBRARIES \
+ uninstall-pkgcfgDATA uninstall-pluginLTLIBRARIES
+
+.MAKE: check-am install-am install-strip
+
+.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 \
+ 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 \
+ install-exec install-exec-am install-html install-html-am \
+ install-info install-info-am install-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
+
+
+# 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/gns.conf.in b/src/gns/gns.conf.in
new file mode 100644
index 0000000..422efdb
--- /dev/null
+++ b/src/gns/gns.conf.in
@@ -0,0 +1,17 @@
+[gns]
+AUTOSTART = YES
+HOSTNAME = localhost
+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
+
+# 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
new file mode 100644
index 0000000..cb47c81
--- /dev/null
+++ b/src/gns/gns.h
@@ -0,0 +1,97 @@
+/*
+ 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 2, 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/gns.h
+ * @brief IPC messages between GNS API and GNS service
+ * @author Martin Schanzenbach
+ */
+#ifndef GNS_H
+#define GNS_H
+
+GNUNET_NETWORK_STRUCT_BEGIN
+
+/**
+ * Message from client to GNS service to lookup records.
+ */
+struct GNUNET_GNS_ClientLookupMessage
+{
+ /**
+ * Header of type GNUNET_MESSAGE_TYPE_GNS_CLIENT_LOOKUP
+ */
+ struct GNUNET_MessageHeader header;
+
+ /**
+ * A key. TODO some uid
+ */
+ GNUNET_HashCode key;
+
+ /**
+ * Unique identifier for this request (for key collisions).
+ */
+ // FIXME: unaligned
+ uint64_t unique_id;
+
+ /**
+ * the type of record to look up
+ */
+ // FIXME: bad type - should be of GNUNET_GNS_RecordType
+ int type;
+
+ /* Followed by the name to look up */
+};
+
+
+/**
+ * Message from GNS service to client: new results.
+ */
+struct GNUNET_GNS_ClientResultMessage
+{
+ /**
+ * Header of type GNUNET_MESSAGE_TYPE_GNS_CLIENT_RESULT
+ */
+ struct GNUNET_MessageHeader header;
+
+ /**
+ * 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;
+
+ /**
+ * The number of records contained in response
+ */
+ uint32_t num_records;
+
+ // FIXME: what format has a GNS_Record?
+ /* followed by num_records GNUNET_GNS_Records*/
+
+};
+
+
+GNUNET_NETWORK_STRUCT_END
+
+#endif
diff --git a/src/gns/gns_api.c b/src/gns/gns_api.c
new file mode 100644
index 0000000..ec9c159
--- /dev/null
+++ b/src/gns/gns_api.c
@@ -0,0 +1,635 @@
+/*
+ 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.
+*/
+
+/**
+ * TODO: Do we really need a client API?
+ *
+ * @file gns/gns_api.c
+ * @brief library to access the GNS service
+ * @author Martin Schanzenbach
+ */
+
+#include "platform.h"
+#include "gnunet_util_lib.h"
+#include "gnunet_constants.h"
+#include "gnunet_arm_service.h"
+#include "gnunet_hello_lib.h"
+#include "gnunet_protocols.h"
+#include "gnunet_dht_service.h"
+#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
+
+/**
+ * Entry in our list of messages to be (re-)transmitted.
+ */
+struct PendingMessage
+{
+ /**
+ * 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.
+ */
+
+ int free_on_send;
+ /**
+ * GNUNET_YES if this message is in our pending queue right now.
+ */
+ int in_pending_queue;
+
+};
+
+/**
+ * Handle to a Lookup request
+ */
+struct GNUNET_GNS_LookupHandle
+{
+
+ /**
+ * Iterator to call on data receipt
+ */
+ GNUNET_GNS_LookupIterator iter;
+
+ /**
+ * Closure for the iterator callback
+ */
+ void *iter_cls;
+
+ /**
+ * Main handle to this GNS api
+ */
+ struct GNUNET_GNS_Handle *gns_handle;
+
+ /**
+ * Key that this get request is for
+ */
+ GNUNET_HashCode key;
+
+ /**
+ * Unique identifier for this request (for key collisions).
+ */
+ uint64_t unique_id;
+
+ struct PendingMessage *message;
+
+};
+
+/**
+ * Connection to the GNS service.
+ */
+struct GNUNET_GNS_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;
+
+ /**
+ * Head of linked list of messages we would like to transmit.
+ */
+ struct PendingMessage *pending_head;
+
+ /**
+ * Tail of linked list of messages we would like to transmit.
+ */
+ struct PendingMessage *pending_tail;
+
+ /**
+ * Hash map containing the current outstanding unique requests.
+ */
+ struct GNUNET_CONTAINER_MultiHashMap *active_requests;
+
+ GNUNET_SCHEDULER_TaskIdentifier reconnect_task;
+
+ /**
+ * How quickly should we retry? Used for exponential back-off on
+ * connect-errors.
+ */
+ struct GNUNET_TIME_Relative retry_time;
+
+ /**
+ * Generator for unique ids.
+ */
+ uint64_t uid_gen;
+
+ /**
+ * Did we start our receive loop yet?
+ */
+ int in_receive;
+};
+
+/**
+ * Try to send messages from list of messages to send
+ * @param handle 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).
+ *
+ * @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)
+ */
+static int
+add_request_to_pending (void *cls, const GNUNET_HashCode * key, void *value)
+{
+ 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;
+}
+
+/**
+ * Try reconnecting to the GNS service.
+ *
+ * @param cls GNUNET_GNS_Handle
+ * @param tc scheduler context
+ */
+static void
+try_reconnect (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
+{
+ struct GNUNET_GNS_Handle *handle = 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);
+}
+
+
+/**
+ * Try reconnecting to the GNS service.
+ *
+ * @param handle handle to gns to (possibly) disconnect and reconnect
+ */
+static void
+do_disconnect (struct GNUNET_GNS_Handle *handle)
+{
+ 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);
+}
+
+/**
+ * Transmit the next pending message, called by notify_transmit_ready
+ */
+static size_t
+transmit_pending (void *cls, size_t size, void *buf);
+
+/**
+ * Handler for messages received from the GNS service
+ *
+ * @param cls the 'struct GNUNET_GNS_Handle'
+ * @param msg the incoming message
+ */
+static void
+message_handler (void *cls, const struct GNUNET_MessageHeader *msg);
+
+/**
+ * Try to send messages from list of messages to send
+ */
+static void
+process_pending_messages (struct GNUNET_GNS_Handle *handle)
+{
+ struct PendingMessage *head;
+
+ if (handle->client == NULL)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "process_pending_messages called, but client is null, reconnecting\n");
+ do_disconnect (handle);
+ return;
+ }
+ if (handle->th != NULL)
+ return;
+ if (NULL == (head = handle->pending_head))
+ return;
+ handle->th =
+ GNUNET_CLIENT_notify_transmit_ready (handle->client,
+ ntohs (head->msg->size),
+ GNUNET_TIME_UNIT_FOREVER_REL,
+ GNUNET_YES, &transmit_pending,
+ handle);
+ if (NULL != handle->th)
+ return;
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "notify_transmit_ready returned NULL, reconnecting\n");
+ do_disconnect (handle);
+}
+
+
+/**
+ * Transmit the next pending message, called by notify_transmit_ready
+ */
+static size_t
+transmit_pending (void *cls, size_t size, void *buf)
+{
+ struct GNUNET_GNS_Handle *handle = cls;
+ struct PendingMessage *head;
+ size_t tsize;
+
+ handle->th = NULL;
+ if (buf == NULL)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Transmission to GNS service failed! Reconnecting!\n");
+ do_disconnect (handle);
+ return 0;
+ }
+ if (NULL == (head = handle->pending_head))
+ return 0;
+
+ tsize = ntohs (head->msg->size);
+ if (size < tsize)
+ {
+ process_pending_messages (handle);
+ 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)
+ {
+#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);
+ }
+ return tsize;
+}
+
+/**
+ * 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
+ */
+static int
+process_reply (void *cls, const GNUNET_HashCode * key, void *value)
+{
+ 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;
+
+ if (gns_msg->unique_id != lookup_handle->unique_id)
+ {
+ /* 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;
+ }
+ 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_break (0);
+ return GNUNET_NO;
+ }
+#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;
+}
+
+
+/**
+ * Handler for messages received from the GNS service
+ *
+ * @param cls the 'struct GNUNET_GNS_Handle'
+ * @param msg the incoming message
+ */
+static void
+message_handler (void *cls, const struct GNUNET_MessageHeader *msg)
+{
+ struct GNUNET_GNS_Handle *handle = cls;
+ const struct GNUNET_GNS_ClientResultMessage *gns_msg;
+
+ if (msg == NULL)
+ {
+#if DEBUG_GNS
+ LOG (GNUNET_ERROR_TYPE_DEBUG,
+ "Error receiving data from GNS service, reconnecting\n");
+#endif
+ do_disconnect (handle);
+ return;
+ }
+ if (ntohs (msg->type) != GNUNET_MESSAGE_TYPE_GNS_CLIENT_RESULT)
+ {
+ GNUNET_break (0);
+ do_disconnect (handle);
+ return;
+ }
+ if (ntohs (msg->size) < sizeof (struct GNUNET_GNS_ClientResultMessage))
+ {
+ GNUNET_break (0);
+ do_disconnect (handle);
+ 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);
+}
+
+
+/**
+ * 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)
+{
+ struct GNUNET_GNS_Handle *handle;
+
+ handle = GNUNET_malloc (sizeof (struct GNUNET_GNS_Handle));
+ 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;
+ }
+ return handle;
+}
+
+
+/**
+ * Shutdown connection with the GNS service.
+ *
+ * @param handle handle of the GNS connection to stop
+ */
+void
+GNUNET_GNS_disconnect (struct GNUNET_GNS_Handle *handle)
+{
+ /* disco from GNS */
+}
+
+
+/**
+ * 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
+ */
+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)
+{
+ /* IPC to look for local entries, start dht lookup, return lookup_handle */
+ struct GNUNET_GNS_ClientLookupMessage *lookup_msg;
+ struct GNUNET_GNS_LookupHandle *lookup_handle;
+ GNUNET_HashCode key;
+ size_t msize;
+ struct PendingMessage *pending;
+
+ if (NULL == name)
+ {
+ return NULL;
+ }
+
+ GNUNET_CRYPTO_hash (name, strlen(name), &key);
+
+ 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);
+ 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.size = htons (msize);
+ lookup_msg->header.type = htons (GNUNET_MESSAGE_TYPE_GNS_CLIENT_LOOKUP);
+ lookup_msg->key = key;
+ 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,
+ 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;
+}
+
+
+/**
+ * Stop async GNS lookup.
+ *
+ * @param lookup_handle handle to the GNS lookup operation to stop
+ */
+void
+GNUNET_GNS_lookup_stop (struct GNUNET_GNS_LookupHandle *lookup_handle)
+{
+ /* TODO Stop dht lookups */
+}
+
+
+/* end of gns_api.c */
diff --git a/src/gns/gnunet-service-gns.c b/src/gns/gnunet-service-gns.c
new file mode 100644
index 0000000..b5649f3
--- /dev/null
+++ b/src/gns/gnunet-service-gns.c
@@ -0,0 +1,1399 @@
+/*
+ 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.
+*/
+
+/**
+ *
+ * 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
+ */
+#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_dht_service.h"
+#include "gnunet_namestore_service.h"
+#include "gnunet_gns_service.h"
+#include "block_gns.h"
+#include "gns.h"
+
+/* 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
+ */
+struct GNUNET_GNS_ResolverHandle
+{
+ /* The name to resolve */
+ char *name;
+
+ /* 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;
+
+ /* has this query been answered? how many matches */
+ int answered;
+
+ /* 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;
+
+ /* a handle for dht lookups. should be NULL if no lookups are in progress */
+ struct GNUNET_DHT_GetHandle *get_handle;
+
+};
+
+
+/**
+ * Our handle to the DNS handler library
+ */
+struct GNUNET_DNS_Handle *dns_handle;
+
+/**
+ * Our handle to the DHT
+ */
+struct GNUNET_DHT_Handle *dht_handle;
+
+/**
+ * Our zone's private key
+ */
+struct GNUNET_CRYPTO_RsaPrivateKey *zone_key;
+
+/**
+ * Our handle to the namestore service
+ * FIXME maybe need a second handle for iteration
+ */
+struct GNUNET_NAMESTORE_Handle *namestore_handle;
+
+/**
+ * Handle to iterate over our authoritative zone in namestore
+ */
+struct GNUNET_NAMESTORE_ZoneIterator *namestore_iter;
+
+/**
+ * The configuration the GNS service is running with
+ */
+const struct GNUNET_CONFIGURATION_Handle *GNS_cfg;
+
+/**
+ * Our notification context.
+ */
+static struct GNUNET_SERVER_NotificationContext *nc;
+
+/**
+ * Our zone hash
+ */
+GNUNET_HashCode zone_hash;
+
+/**
+ * Our tld. Maybe get from config file
+ */
+const char* gnunet_tld = ".gnunet";
+
+/**
+ * Useful for zone update for DHT put
+ */
+static int num_public_records = 3600;
+struct GNUNET_TIME_Relative dht_update_interval;
+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);
+
+/**
+ * Task run during shutdown.
+ *
+ * @param cls unused
+ * @param tc unused
+ */
+static void
+shutdown_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
+{
+ /* 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_DHT_disconnect(dht_handle);
+}
+
+/**
+ * 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, "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);
+}
+
+/**
+ * Function called when we get a result from the dht
+ * for our 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
+ */
+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)
+{
+ 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);
+}
+
+/**
+ * Start DHT lookup for a name -> PKEY (compare NS) record in
+ * query->authority's zone
+ *
+ * @param rh the pending gns query
+ * @param name the name of the PKEY record
+ */
+void
+resolve_authority_dht(struct GNUNET_GNS_ResolverHandle *rh)
+{
+ 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);
+
+}
+
+/**
+ * Function called when we get a result from the dht
+ * for our 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
+ */
+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)
+{
+ 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];
+
+ 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 = (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);
+
+ }
+
+ 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
+
+ if (rh->answered)
+ reply_to_dns(rh, num_records, rd);
+ else
+ reply_to_dns(rh, 0, NULL);
+
+}
+
+/**
+ * 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);
+
+ timeout = GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 5);
+
+ 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);
+
+}
+
+//Prototype
+void
+resolve_name(struct GNUNET_GNS_ResolverHandle *rh);
+
+/**
+ * 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)
+ {
+ /**
+ * 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);
+ 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
+ */
+ GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
+ "Authority lookup successful but no PKEY... never get here\n");
+ reply_to_dns(rh, 0, NULL);
+}
+
+
+/**
+ * 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);
+
+ 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;
+
+ 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(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);
+ }
+
+ GNUNET_free(rh->name);
+ GNUNET_free(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_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)
+{
+ 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);
+
+ if (rd_count == 0)
+ {
+ /**
+ * Lookup terminated and no results
+ * -> DHT Phase unless data is recent
+ */
+ 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;
+
+ }
+ else
+ {
+
+ 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);
+ }
+}
+
+/**
+ * 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
+ */
+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
+ * @return the tld
+ */
+char* pop_tld(char* name)
+{
+ uint32_t len;
+
+ if (is_canonical(name))
+ return NULL;
+
+ for (len = strlen(name); len > 0; len--)
+ {
+ if (*(name+len) == '.')
+ break;
+ }
+
+ if (len == 0)
+ return NULL;
+
+ name[len] = '\0';
+
+ return (name+len+1);
+}
+
+
+/**
+ * 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
+ */
+void
+resolve_name(struct GNUNET_GNS_ResolverHandle *rh)
+{
+ 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
+ {
+ /* 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);
+ }
+}
+
+/**
+ * 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);
+
+ rh = GNUNET_malloc(sizeof (struct GNUNET_GNS_ResolverHandle));
+ rh->packet = p;
+ rh->query = q;
+ rh->authority = zone_hash;
+
+ 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));
+
+ rh->request_handle = request;
+
+ /* Start resolution in our zone */
+ resolve_name(rh);
+}
+
+/**
+ * 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
+ */
+void
+handle_dns_request(void *cls,
+ struct GNUNET_DNS_RequestHandle *rh,
+ size_t request_length,
+ const char *request)
+{
+ struct GNUNET_DNSPARSER_Packet *p;
+ char *tldoffset;
+
+ 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);
+ 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);
+ }
+
+ 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
+ */
+ tldoffset = p->queries[0].name + strlen(p->queries[0].name);
+
+ while ((*tldoffset) != '.')
+ tldoffset--;
+
+ if (0 == strcmp(tldoffset, gnunet_tld))
+ {
+ start_resolution(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);
+ }
+
+}
+
+/**
+ * test function that stores some data in the namestore
+ * This will also be replaced by a test progrm that
+ * directl interfaces with the namestore
+ */
+void
+put_some_records(void)
+{
+ 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";
+
+ struct in_addr *web = GNUNET_malloc(sizeof(struct in_addr));
+ struct GNUNET_NAMESTORE_RecordData rdb_web;
+
+ GNUNET_assert(1 == inet_pton (AF_INET, ipB, web));
+
+ 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);
+}
+
+/**
+ * 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
+ *
+ * @param cls closure
+ * @param tc task context
+ */
+void
+record_dht_put(void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
+{
+ 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 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)
+ {
+ 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);
+ return;
+ }
+
+ 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++)
+ {
+ rd_payload_length += rd[i].data_size;
+ }
+
+ 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));
+
+ nrb->rd_count = htonl(rd_count);
+
+ memcpy(&nrb[1], name, strlen(name) + 1); //FIXME is this 0 terminated??
+
+ rb = (struct GNSRecordBlock *)((char*)&nrb[1] + strlen(name) + 1);
+
+ for (i=0; i<rd_count; i++)
+ {
+ 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;
+ }
+
+ /**
+ * 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);
+
+ 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
+
+ num_public_records++;
+
+ /**
+ * 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.
+ *
+ * @param name name of entity
+ * @param keyfile keyfile
+ */
+void
+put_trusted(char* name, char* keyfile)
+{
+ 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);
+}
+
+
+
+/**
+ * Periodically iterate over our zone and store everything in dht
+ *
+ * @param cls NULL
+ * @param tc task context
+ */
+static void
+update_zone_dht_start(void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
+{
+ GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Starting DHT zone update!\n");
+ if (0 == num_public_records)
+ {
+ dht_update_interval = GNUNET_TIME_relative_multiply(
+ GNUNET_TIME_UNIT_SECONDS,
+ 1);
+ }
+ else
+ {
+ dht_update_interval = GNUNET_TIME_relative_multiply(
+ GNUNET_TIME_UNIT_SECONDS,
+ (3600/num_public_records));
+ }
+ 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 server the initialized server
+ * @param c configuration to use
+ */
+static void
+run (void *cls, struct GNUNET_SERVER_Handle *server,
+ const struct GNUNET_CONFIGURATION_Handle *c)
+{
+
+ GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Initializing GNS\n");
+
+ char* keyfile;
+ char* trusted_entities;
+ struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded pkey;
+
+ if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_string (c, "gns",
+ "ZONEKEY", &keyfile))
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "No private key for root zone specified%s!\n", keyfile);
+ GNUNET_SCHEDULER_shutdown(0);
+ return;
+ }
+
+ 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),
+ &zone_hash);
+
+ 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
+ */
+ namestore_handle = GNUNET_NAMESTORE_connect(c);
+
+ if (NULL == namestore_handle)
+ {
+ //FIXME do error handling;
+ GNUNET_log(GNUNET_ERROR_TYPE_ERROR,
+ "Failed to connect to the namestore!\n");
+ GNUNET_SCHEDULER_shutdown(0);
+ 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))
+ {
+ 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
+ }
+ }
+
+ }
+
+ /**
+ * handle to the dht
+ */
+ dht_handle = GNUNET_DHT_connect(c, 1); //FIXME get ht_len from cfg
+
+ if (NULL == dht_handle)
+ {
+ GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Could not connect to DHT!\n");
+ }
+
+ put_some_records(); //FIXME for testing
+
+ /**
+ * 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,
+ 1);
+ zone_update_taskid = GNUNET_SCHEDULER_add_now (&update_zone_dht_start, NULL);
+
+}
+
+
+/**
+ * The main function for the GNS service.
+ *
+ * @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)
+{
+ int ret;
+
+ ret =
+ (GNUNET_OK ==
+ GNUNET_SERVICE_run (argc, argv, "gns", GNUNET_SERVICE_OPTION_NONE, &run,
+ NULL)) ? 0 : 1;
+ return ret;
+}
+
+/* end of gnunet-service-gns.c */
diff --git a/src/gns/namestore_stub_api.c b/src/gns/namestore_stub_api.c
new file mode 100644
index 0000000..d067bca
--- /dev/null
+++ b/src/gns/namestore_stub_api.c
@@ -0,0 +1,438 @@
+/*
+ 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/plugin_block_gns.c b/src/gns/plugin_block_gns.c
new file mode 100644
index 0000000..a4d6ad9
--- /dev/null
+++ b/src/gns/plugin_block_gns.c
@@ -0,0 +1,226 @@
+/*
+ This file is part of GNUnet
+ (C) 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/plugin_block_gns.c
+ * @brief blocks used for GNS records
+ * @author Martin Schanzenbach
+ */
+
+#include "platform.h"
+#include "gnunet_block_plugin.h"
+#include "gnunet_namestore_service.h"
+#include "block_gns.h"
+#include "gnunet_signatures.h"
+
+/**
+ * Number of bits we set per entry in the bloomfilter.
+ * Do not change! -from fs
+ */
+#define BLOOMFILTER_K 16
+
+/**
+ * Function called to validate a reply or a request. For
+ * request evaluation, simply pass "NULL" for the reply_block.
+ * Note that it is assumed that the reply has already been
+ * matched to the key (and signatures checked) as it would
+ * be done with the "get_key" function.
+ *
+ * @param cls closure
+ * @param type block type
+ * @param query original query (hash)
+ * @param bf pointer to bloom filter associated with query; possibly updated (!)
+ * @param bf_mutator mutation value for bf
+ * @param xquery extrended query data (can be NULL, depending on type)
+ * @param xquery_size number of bytes in xquery
+ * @param reply_block response to validate
+ * @param reply_block_size number of bytes in reply block
+ * @return characterization of result
+ */
+static enum GNUNET_BLOCK_EvaluationResult
+block_plugin_gns_evaluate (void *cls, enum GNUNET_BLOCK_Type type,
+ const GNUNET_HashCode * query,
+ struct GNUNET_CONTAINER_BloomFilter **bf,
+ int32_t bf_mutator, const void *xquery,
+ 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 query_key;
+ GNUNET_HashCode name_hash;
+ GNUNET_HashCode mhash;
+ GNUNET_HashCode chash;
+ struct GNSNameRecordBlock *nrb;
+ struct GNSRecordBlock *rb;
+ uint32_t rd_count;
+
+ nrb = (struct GNSNameRecordBlock *)reply_block;
+ name = (char*)&nrb[1];
+ GNUNET_CRYPTO_hash(&nrb->public_key,
+ sizeof(nrb->public_key),
+ &pkey_hash);
+
+ GNUNET_CRYPTO_hash(name, strlen(name), &name_hash);
+
+ GNUNET_CRYPTO_hash_xor(&pkey_hash, &name_hash, &query_key);
+
+ /* Check query key against public key */
+ if (0 != GNUNET_CRYPTO_hash_cmp(query, &query_key))
+ return GNUNET_BLOCK_EVALUATION_REQUEST_VALID;
+
+ 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[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);
+
+ if (xquery_size == 0)
+ continue;
+
+ if (rd[i].record_type == record_xquery)
+ {
+ record_match++;
+ }
+ }
+
+
+ /*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;
+ }*/
+
+ //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;
+ }
+ else
+ {
+ *bf = GNUNET_CONTAINER_bloomfilter_init(NULL, 8, BLOOMFILTER_K);
+ }
+ GNUNET_CONTAINER_bloomfilter_add(*bf, &mhash);
+ }
+ GNUNET_log(GNUNET_ERROR_TYPE_INFO, "No dup\n");
+ return GNUNET_BLOCK_EVALUATION_OK_MORE;
+}
+
+
+/**
+ * Function called to obtain the key for a block.
+ *
+ * @param cls closure
+ * @param type block type
+ * @param block block to get the key for
+ * @param block_size number of bytes in block
+ * @param key set to the key (query) for the given block
+ * @return GNUNET_OK on success, GNUNET_SYSERR if type not supported
+ * (or if extracting a key from a block of this type does not work)
+ */
+static int
+block_plugin_gns_get_key (void *cls, enum GNUNET_BLOCK_Type type,
+ const void *block, size_t block_size,
+ GNUNET_HashCode * key)
+{
+ if (type != GNUNET_BLOCK_TYPE_GNS_NAMERECORD)
+ return GNUNET_SYSERR;
+ GNUNET_HashCode name_hash;
+ GNUNET_HashCode pkey_hash;
+ struct GNSNameRecordBlock *nrb = (struct GNSNameRecordBlock *)block;
+
+ GNUNET_CRYPTO_hash(&nrb[1], strlen((char*)&nrb[1]), &name_hash);
+ GNUNET_CRYPTO_hash(&nrb->public_key,
+ sizeof(struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded),
+ &pkey_hash);
+
+ GNUNET_CRYPTO_hash_xor(&name_hash, &pkey_hash, key);
+
+ //FIXME calculate key from name and hash(pkey) here
+ return GNUNET_OK;
+}
+
+
+/**
+ * Entry point for the plugin.
+ */
+void *
+libgnunet_plugin_block_gns_init (void *cls)
+{
+ static enum GNUNET_BLOCK_Type types[] =
+ {
+ GNUNET_BLOCK_TYPE_GNS_NAMERECORD,
+ GNUNET_BLOCK_TYPE_ANY /* end of list */
+ };
+ struct GNUNET_BLOCK_PluginFunctions *api;
+
+ api = GNUNET_malloc (sizeof (struct GNUNET_BLOCK_PluginFunctions));
+ api->evaluate = &block_plugin_gns_evaluate;
+ api->get_key = &block_plugin_gns_get_key;
+ api->types = types;
+ return api;
+}
+
+
+/**
+ * Exit point from the plugin.
+ */
+void *
+libgnunet_plugin_block_gns_done (void *cls)
+{
+ struct GNUNET_TRANSPORT_PluginFunctions *api = cls;
+
+ GNUNET_free (api);
+ return NULL;
+}
+
+/* end of plugin_block_gns.c */
diff --git a/src/gns/test_gns_twopeer.c b/src/gns/test_gns_twopeer.c
new file mode 100644
index 0000000..3bd36fb
--- /dev/null
+++ b/src/gns/test_gns_twopeer.c
@@ -0,0 +1,463 @@
+/*
+ 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
new file mode 100644
index 0000000..4048297
--- /dev/null
+++ b/src/gns/test_gns_twopeer.conf
@@ -0,0 +1,80 @@
+[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
new file mode 100755
index 0000000..cd68027
--- /dev/null
+++ b/src/gns/test_gnunet_gns.sh
@@ -0,0 +1,22 @@
+#!/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`