diff options
author | Bertrand Marc <beberking@gmail.com> | 2012-05-02 21:43:37 +0200 |
---|---|---|
committer | Bertrand Marc <beberking@gmail.com> | 2012-05-02 21:43:37 +0200 |
commit | 2b81464a43485fcc8ce079fafdee7b7a171835f4 (patch) | |
tree | 394774c0f735199b57d51a2d3840356317853fe1 /src/gns |
Imported Upstream version 0.9.2upstream/0.9.2
Diffstat (limited to 'src/gns')
-rw-r--r-- | src/gns/Makefile.am | 113 | ||||
-rw-r--r-- | src/gns/Makefile.in | 998 | ||||
-rw-r--r-- | src/gns/gns.conf.in | 17 | ||||
-rw-r--r-- | src/gns/gns.h | 97 | ||||
-rw-r--r-- | src/gns/gns_api.c | 635 | ||||
-rw-r--r-- | src/gns/gnunet-service-gns.c | 1399 | ||||
-rw-r--r-- | src/gns/namestore_stub_api.c | 438 | ||||
-rw-r--r-- | src/gns/plugin_block_gns.c | 226 | ||||
-rw-r--r-- | src/gns/test_gns_twopeer.c | 463 | ||||
-rw-r--r-- | src/gns/test_gns_twopeer.conf | 80 | ||||
-rwxr-xr-x | src/gns/test_gnunet_gns.sh | 22 |
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, + ¬ify_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` |