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/namestore |
Imported Upstream version 0.9.2upstream/0.9.2
Diffstat (limited to 'src/namestore')
-rw-r--r-- | src/namestore/Makefile.am | 105 | ||||
-rw-r--r-- | src/namestore/Makefile.in | 918 | ||||
-rw-r--r-- | src/namestore/gnunet-service-namestore.c | 845 | ||||
-rw-r--r-- | src/namestore/hostkey | bin | 0 -> 913 bytes | |||
-rw-r--r-- | src/namestore/namestore.conf.in | 30 | ||||
-rw-r--r-- | src/namestore/namestore.h | 424 | ||||
-rw-r--r-- | src/namestore/namestore_api.c | 1194 | ||||
-rw-r--r-- | src/namestore/namestore_common.c | 159 | ||||
-rw-r--r-- | src/namestore/plugin_namestore_sqlite.c | 806 | ||||
-rw-r--r-- | src/namestore/test_namestore_api.c | 213 | ||||
-rw-r--r-- | src/namestore/test_namestore_api.conf | 34 | ||||
-rw-r--r-- | src/namestore/test_namestore_api_zone_iteration.c | 219 | ||||
-rw-r--r-- | src/namestore/test_namestore_record_serialization.c | 157 | ||||
-rw-r--r-- | src/namestore/test_plugin_namestore.c | 248 | ||||
-rw-r--r-- | src/namestore/test_plugin_namestore_sqlite.conf | 2 |
15 files changed, 5354 insertions, 0 deletions
diff --git a/src/namestore/Makefile.am b/src/namestore/Makefile.am new file mode 100644 index 0000000..47517b9 --- /dev/null +++ b/src/namestore/Makefile.am @@ -0,0 +1,105 @@ +INCLUDES = -I$(top_srcdir)/src/include + +plugindir = $(libdir)/gnunet + +pkgcfgdir= $(pkgnamedir)/config.d/ + +pkgcfg_NAME = \ + namestore.conf + +if MINGW + WINFLAGS = -Wl,--no-undefined -Wl,--export-all-symbols +endif + +if USE_COVERAGE + AM_CFLAGS = --coverage -O0 + XLIBS = -lgcov +endif + +if HAVE_SQLITE +SQLITE_TESTS = \ + test_plugin_namestore_sqlite +endif + + +check_PROGRAMS = \ + $(SQLITE_TESTS) \ + test_namestore_api \ + test_namestore_api_zone_iteration \ + test_namestore_record_serialization + +if HAVE_EXPERIMENTAL + check_PROGRAMS +endif + +lib_LTLIBRARIES = \ + libgnunetnamestore.la + +libgnunetnamestore_la_SOURCES = \ + namestore_api.c namestore.h +libgnunetnamestore_la_LIBADD = \ + $(top_builddir)/src/statistics/libgnunetstatistics.la \ + $(top_builddir)/src/util/libgnunetutil.la \ + $(GN_LIBINTL) +libgnunetnamestore_la_LDFLAGS = \ + $(GN_LIB_LDFLAGS) $(WINFLAGS) \ + -version-info 0:0:0 + +bin_PROGRAMS = \ + gnunet-service-namestore + +gnunet_service_namestore_SOURCES = \ + gnunet-service-namestore.c \ + namestore_common.c +gnunet_service_namestore_LDADD = \ + $(top_builddir)/src/statistics/libgnunetstatistics.la \ + $(top_builddir)/src/util/libgnunetutil.la \ + $(GN_LIBINTL) + +if HAVE_SQLITE + SQLITE_PLUGIN = libgnunet_plugin_namestore_sqlite.la +endif + +plugin_LTLIBRARIES = \ + $(SQLITE_PLUGIN) + +libgnunet_plugin_namestore_sqlite_la_SOURCES = \ + plugin_namestore_sqlite.c +libgnunet_plugin_namestore_sqlite_la_LIBADD = \ + $(top_builddir)/src/statistics/libgnunetstatistics.la \ + $(top_builddir)/src/util/libgnunetutil.la $(XLIBS) -lsqlite3 +libgnunet_plugin_namestore_sqlite_la_LDFLAGS = \ + $(GN_PLUGIN_LDFLAGS) + + +test_namestore_api_SOURCES = \ + test_namestore_api.c \ + namestore_common.c +test_namestore_api_LDADD = \ + $(top_builddir)/src/util/libgnunetutil.la \ + $(top_builddir)/src/namestore/libgnunetnamestore.la + +test_namestore_api_zone_iteration_SOURCES = \ + test_namestore_api_zone_iteration.c \ + namestore_common.c +test_namestore_api_zone_iteration_LDADD = \ + $(top_builddir)/src/util/libgnunetutil.la \ + $(top_builddir)/src/namestore/libgnunetnamestore.la + +test_namestore_record_serialization_SOURCES = \ + test_namestore_record_serialization.c \ + namestore_common.c +test_namestore_record_serialization_LDADD = \ + $(top_builddir)/src/util/libgnunetutil.la \ + $(top_builddir)/src/namestore/libgnunetnamestore.la + +EXTRA_DIST = \ + test_namestore_api.conf \ + test_plugin_namestore_sqlite.conf\ + hostkey + + +test_plugin_namestore_sqlite_SOURCES = \ + test_plugin_namestore.c +test_plugin_namestore_sqlite_LDADD = \ + $(top_builddir)/src/util/libgnunetutil.la diff --git a/src/namestore/Makefile.in b/src/namestore/Makefile.in new file mode 100644 index 0000000..2ed2a46 --- /dev/null +++ b/src/namestore/Makefile.in @@ -0,0 +1,918 @@ +# 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@ +check_PROGRAMS = $(am__EXEEXT_1) test_namestore_api$(EXEEXT) \ + test_namestore_api_zone_iteration$(EXEEXT) \ + test_namestore_record_serialization$(EXEEXT) +bin_PROGRAMS = gnunet-service-namestore$(EXEEXT) +subdir = src/namestore +DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in \ + $(srcdir)/namestore.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 = namestore.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)" +LTLIBRARIES = $(lib_LTLIBRARIES) $(plugin_LTLIBRARIES) +am__DEPENDENCIES_1 = +libgnunet_plugin_namestore_sqlite_la_DEPENDENCIES = \ + $(top_builddir)/src/statistics/libgnunetstatistics.la \ + $(top_builddir)/src/util/libgnunetutil.la \ + $(am__DEPENDENCIES_1) +am_libgnunet_plugin_namestore_sqlite_la_OBJECTS = \ + plugin_namestore_sqlite.lo +libgnunet_plugin_namestore_sqlite_la_OBJECTS = \ + $(am_libgnunet_plugin_namestore_sqlite_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_namestore_sqlite_la_LINK = $(LIBTOOL) $(AM_V_lt) \ + --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link \ + $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(libgnunet_plugin_namestore_sqlite_la_LDFLAGS) $(LDFLAGS) -o \ + $@ +@HAVE_SQLITE_TRUE@am_libgnunet_plugin_namestore_sqlite_la_rpath = \ +@HAVE_SQLITE_TRUE@ -rpath $(plugindir) +libgnunetnamestore_la_DEPENDENCIES = \ + $(top_builddir)/src/statistics/libgnunetstatistics.la \ + $(top_builddir)/src/util/libgnunetutil.la \ + $(am__DEPENDENCIES_1) +am_libgnunetnamestore_la_OBJECTS = namestore_api.lo +libgnunetnamestore_la_OBJECTS = $(am_libgnunetnamestore_la_OBJECTS) +libgnunetnamestore_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ + $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ + $(AM_CFLAGS) $(CFLAGS) $(libgnunetnamestore_la_LDFLAGS) \ + $(LDFLAGS) -o $@ +@HAVE_SQLITE_TRUE@am__EXEEXT_1 = \ +@HAVE_SQLITE_TRUE@ test_plugin_namestore_sqlite$(EXEEXT) +PROGRAMS = $(bin_PROGRAMS) +am_gnunet_service_namestore_OBJECTS = \ + gnunet-service-namestore.$(OBJEXT) namestore_common.$(OBJEXT) +gnunet_service_namestore_OBJECTS = \ + $(am_gnunet_service_namestore_OBJECTS) +gnunet_service_namestore_DEPENDENCIES = \ + $(top_builddir)/src/statistics/libgnunetstatistics.la \ + $(top_builddir)/src/util/libgnunetutil.la \ + $(am__DEPENDENCIES_1) +am_test_namestore_api_OBJECTS = test_namestore_api.$(OBJEXT) \ + namestore_common.$(OBJEXT) +test_namestore_api_OBJECTS = $(am_test_namestore_api_OBJECTS) +test_namestore_api_DEPENDENCIES = \ + $(top_builddir)/src/util/libgnunetutil.la \ + $(top_builddir)/src/namestore/libgnunetnamestore.la +am_test_namestore_api_zone_iteration_OBJECTS = \ + test_namestore_api_zone_iteration.$(OBJEXT) \ + namestore_common.$(OBJEXT) +test_namestore_api_zone_iteration_OBJECTS = \ + $(am_test_namestore_api_zone_iteration_OBJECTS) +test_namestore_api_zone_iteration_DEPENDENCIES = \ + $(top_builddir)/src/util/libgnunetutil.la \ + $(top_builddir)/src/namestore/libgnunetnamestore.la +am_test_namestore_record_serialization_OBJECTS = \ + test_namestore_record_serialization.$(OBJEXT) \ + namestore_common.$(OBJEXT) +test_namestore_record_serialization_OBJECTS = \ + $(am_test_namestore_record_serialization_OBJECTS) +test_namestore_record_serialization_DEPENDENCIES = \ + $(top_builddir)/src/util/libgnunetutil.la \ + $(top_builddir)/src/namestore/libgnunetnamestore.la +am_test_plugin_namestore_sqlite_OBJECTS = \ + test_plugin_namestore.$(OBJEXT) +test_plugin_namestore_sqlite_OBJECTS = \ + $(am_test_plugin_namestore_sqlite_OBJECTS) +test_plugin_namestore_sqlite_DEPENDENCIES = \ + $(top_builddir)/src/util/libgnunetutil.la +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_namestore_sqlite_la_SOURCES) \ + $(libgnunetnamestore_la_SOURCES) \ + $(gnunet_service_namestore_SOURCES) \ + $(test_namestore_api_SOURCES) \ + $(test_namestore_api_zone_iteration_SOURCES) \ + $(test_namestore_record_serialization_SOURCES) \ + $(test_plugin_namestore_sqlite_SOURCES) +DIST_SOURCES = $(libgnunet_plugin_namestore_sqlite_la_SOURCES) \ + $(libgnunetnamestore_la_SOURCES) \ + $(gnunet_service_namestore_SOURCES) \ + $(test_namestore_api_SOURCES) \ + $(test_namestore_api_zone_iteration_SOURCES) \ + $(test_namestore_record_serialization_SOURCES) \ + $(test_plugin_namestore_sqlite_SOURCES) +ETAGS = etags +CTAGS = ctags +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AR = @AR@ +ARGZ_H = @ARGZ_H@ +AS = @AS@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CXX = @CXX@ +CXXCPP = @CXXCPP@ +CXXDEPMODE = @CXXDEPMODE@ +CXXFLAGS = @CXXFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFAULT_INTERFACE = @DEFAULT_INTERFACE@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DLLDIR = @DLLDIR@ +DLLTOOL = @DLLTOOL@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +EXT_LIBS = @EXT_LIBS@ +EXT_LIB_PATH = @EXT_LIB_PATH@ +FGREP = @FGREP@ +GMSGFMT = @GMSGFMT@ +GMSGFMT_015 = @GMSGFMT_015@ +GNUNETDNS_GROUP = @GNUNETDNS_GROUP@ +GN_DAEMON_CONFIG_DIR = @GN_DAEMON_CONFIG_DIR@ +GN_DAEMON_HOME_DIR = @GN_DAEMON_HOME_DIR@ +GN_INTLINCL = @GN_INTLINCL@ +GN_LIBINTL = @GN_LIBINTL@ +GN_LIB_LDFLAGS = @GN_LIB_LDFLAGS@ +GN_PLUGIN_LDFLAGS = @GN_PLUGIN_LDFLAGS@ +GN_USER_HOME_DIR = @GN_USER_HOME_DIR@ +GREP = @GREP@ +HAVE_LIBUNISTRING = @HAVE_LIBUNISTRING@ +INCLTDL = @INCLTDL@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +INTLLIBS = @INTLLIBS@ +INTL_MACOSX_LIBS = @INTL_MACOSX_LIBS@ +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 +plugindir = $(libdir)/gnunet +pkgcfgdir = $(pkgnamedir)/config.d/ +pkgcfg_NAME = \ + namestore.conf + +@MINGW_TRUE@WINFLAGS = -Wl,--no-undefined -Wl,--export-all-symbols +@USE_COVERAGE_TRUE@AM_CFLAGS = --coverage -O0 +@USE_COVERAGE_TRUE@XLIBS = -lgcov +@HAVE_SQLITE_TRUE@SQLITE_TESTS = \ +@HAVE_SQLITE_TRUE@ test_plugin_namestore_sqlite + +lib_LTLIBRARIES = \ + libgnunetnamestore.la + +libgnunetnamestore_la_SOURCES = \ + namestore_api.c namestore.h + +libgnunetnamestore_la_LIBADD = \ + $(top_builddir)/src/statistics/libgnunetstatistics.la \ + $(top_builddir)/src/util/libgnunetutil.la \ + $(GN_LIBINTL) + +libgnunetnamestore_la_LDFLAGS = \ + $(GN_LIB_LDFLAGS) $(WINFLAGS) \ + -version-info 0:0:0 + +gnunet_service_namestore_SOURCES = \ + gnunet-service-namestore.c \ + namestore_common.c + +gnunet_service_namestore_LDADD = \ + $(top_builddir)/src/statistics/libgnunetstatistics.la \ + $(top_builddir)/src/util/libgnunetutil.la \ + $(GN_LIBINTL) + +@HAVE_SQLITE_TRUE@SQLITE_PLUGIN = libgnunet_plugin_namestore_sqlite.la +plugin_LTLIBRARIES = \ + $(SQLITE_PLUGIN) + +libgnunet_plugin_namestore_sqlite_la_SOURCES = \ + plugin_namestore_sqlite.c + +libgnunet_plugin_namestore_sqlite_la_LIBADD = \ + $(top_builddir)/src/statistics/libgnunetstatistics.la \ + $(top_builddir)/src/util/libgnunetutil.la $(XLIBS) -lsqlite3 + +libgnunet_plugin_namestore_sqlite_la_LDFLAGS = \ + $(GN_PLUGIN_LDFLAGS) + +test_namestore_api_SOURCES = \ + test_namestore_api.c \ + namestore_common.c + +test_namestore_api_LDADD = \ + $(top_builddir)/src/util/libgnunetutil.la \ + $(top_builddir)/src/namestore/libgnunetnamestore.la + +test_namestore_api_zone_iteration_SOURCES = \ + test_namestore_api_zone_iteration.c \ + namestore_common.c + +test_namestore_api_zone_iteration_LDADD = \ + $(top_builddir)/src/util/libgnunetutil.la \ + $(top_builddir)/src/namestore/libgnunetnamestore.la + +test_namestore_record_serialization_SOURCES = \ + test_namestore_record_serialization.c \ + namestore_common.c + +test_namestore_record_serialization_LDADD = \ + $(top_builddir)/src/util/libgnunetutil.la \ + $(top_builddir)/src/namestore/libgnunetnamestore.la + +EXTRA_DIST = \ + test_namestore_api.conf \ + test_plugin_namestore_sqlite.conf\ + hostkey + +test_plugin_namestore_sqlite_SOURCES = \ + test_plugin_namestore.c + +test_plugin_namestore_sqlite_LDADD = \ + $(top_builddir)/src/util/libgnunetutil.la + +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/namestore/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --gnu src/namestore/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): +namestore.conf: $(top_builddir)/config.status $(srcdir)/namestore.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_namestore_sqlite.la: $(libgnunet_plugin_namestore_sqlite_la_OBJECTS) $(libgnunet_plugin_namestore_sqlite_la_DEPENDENCIES) + $(AM_V_CCLD)$(libgnunet_plugin_namestore_sqlite_la_LINK) $(am_libgnunet_plugin_namestore_sqlite_la_rpath) $(libgnunet_plugin_namestore_sqlite_la_OBJECTS) $(libgnunet_plugin_namestore_sqlite_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-namestore$(EXEEXT): $(gnunet_service_namestore_OBJECTS) $(gnunet_service_namestore_DEPENDENCIES) + @rm -f gnunet-service-namestore$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(gnunet_service_namestore_OBJECTS) $(gnunet_service_namestore_LDADD) $(LIBS) +test_namestore_api$(EXEEXT): $(test_namestore_api_OBJECTS) $(test_namestore_api_DEPENDENCIES) + @rm -f test_namestore_api$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(test_namestore_api_OBJECTS) $(test_namestore_api_LDADD) $(LIBS) +test_namestore_api_zone_iteration$(EXEEXT): $(test_namestore_api_zone_iteration_OBJECTS) $(test_namestore_api_zone_iteration_DEPENDENCIES) + @rm -f test_namestore_api_zone_iteration$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(test_namestore_api_zone_iteration_OBJECTS) $(test_namestore_api_zone_iteration_LDADD) $(LIBS) +test_namestore_record_serialization$(EXEEXT): $(test_namestore_record_serialization_OBJECTS) $(test_namestore_record_serialization_DEPENDENCIES) + @rm -f test_namestore_record_serialization$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(test_namestore_record_serialization_OBJECTS) $(test_namestore_record_serialization_LDADD) $(LIBS) +test_plugin_namestore_sqlite$(EXEEXT): $(test_plugin_namestore_sqlite_OBJECTS) $(test_plugin_namestore_sqlite_DEPENDENCIES) + @rm -f test_plugin_namestore_sqlite$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(test_plugin_namestore_sqlite_OBJECTS) $(test_plugin_namestore_sqlite_LDADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gnunet-service-namestore.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/namestore_api.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/namestore_common.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/plugin_namestore_sqlite.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_namestore_api.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_namestore_api_zone_iteration.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_namestore_record_serialization.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_plugin_namestore.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 + +ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + mkid -fID $$unique +tags: TAGS + +TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + set x; \ + here=`pwd`; \ + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: CTAGS +CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am + $(MAKE) $(AM_MAKEFLAGS) $(check_PROGRAMS) +check: check-am +all-am: Makefile $(LTLIBRARIES) $(PROGRAMS) +install-binPROGRAMS: install-libLTLIBRARIES + +installdirs: + for dir in "$(DESTDIR)$(libdir)" "$(DESTDIR)$(plugindir)" "$(DESTDIR)$(bindir)"; 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-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-pluginLTLIBRARIES + +.MAKE: check-am install-am install-strip + +.PHONY: CTAGS GTAGS all all-am check 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-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-pluginLTLIBRARIES + + +@HAVE_EXPERIMENTAL_TRUE@ check_PROGRAMS + +# 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/namestore/gnunet-service-namestore.c b/src/namestore/gnunet-service-namestore.c new file mode 100644 index 0000000..92eb218 --- /dev/null +++ b/src/namestore/gnunet-service-namestore.c @@ -0,0 +1,845 @@ +/* + 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 namestore/gnunet-service-namestore.c + * @brief namestore for the GNUnet naming system + * @author Matthias Wachs + */ +#include "platform.h" +#include "gnunet_getopt_lib.h" +#include "gnunet_service_lib.h" +#include "gnunet_namestore_service.h" +#include "gnunet_namestore_plugin.h" +#include "namestore.h" + + + +/** + * A namestore operation. + */ +struct GNUNET_NAMESTORE_ZoneIteration +{ + struct GNUNET_NAMESTORE_ZoneIteration *next; + struct GNUNET_NAMESTORE_ZoneIteration *prev; + + struct GNUNET_NAMESTORE_Client * client; + + GNUNET_HashCode zone; + + uint64_t op_id; + uint32_t offset; + +}; + + +/** + * A namestore client + */ +struct GNUNET_NAMESTORE_Client +{ + struct GNUNET_NAMESTORE_Client *next; + struct GNUNET_NAMESTORE_Client *prev; + + struct GNUNET_SERVER_Client * client; + + struct GNUNET_NAMESTORE_ZoneIteration *op_head; + struct GNUNET_NAMESTORE_ZoneIteration *op_tail; +}; + + + +/** + * Configuration handle. + */ +const struct GNUNET_CONFIGURATION_Handle *GSN_cfg; + +static struct GNUNET_NAMESTORE_PluginFunctions *GSN_database; + +/** + * Our notification context. + */ +static struct GNUNET_SERVER_NotificationContext *snc; + +static char *db_lib_name; + +static struct GNUNET_NAMESTORE_Client *client_head; +static struct GNUNET_NAMESTORE_Client *client_tail; + + +/** + * Task run during shutdown. + * + * @param cls unused + * @param tc unused + */ +static void +cleanup_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) +{ + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Stopping namestore service\n"); + + struct GNUNET_NAMESTORE_ZoneIteration * no; + struct GNUNET_NAMESTORE_ZoneIteration * tmp; + struct GNUNET_NAMESTORE_Client * nc; + struct GNUNET_NAMESTORE_Client * next; + + for (nc = client_head; nc != NULL; nc = next) + { + next = nc->next; + for (no = nc->op_head; no != NULL; no = tmp) + { + GNUNET_CONTAINER_DLL_remove (nc->op_head, nc->op_tail, no); + tmp = no->next; + GNUNET_free (no); + } + + GNUNET_CONTAINER_DLL_remove (client_head, client_tail, nc); + GNUNET_free (nc); + + } + + GNUNET_SERVER_notification_context_destroy (snc); + snc = NULL; + + GNUNET_break (NULL == GNUNET_PLUGIN_unload (db_lib_name, GSN_database)); + GNUNET_free (db_lib_name); +} + +static struct GNUNET_NAMESTORE_Client * +client_lookup (struct GNUNET_SERVER_Client *client) +{ + struct GNUNET_NAMESTORE_Client * nc; + + GNUNET_assert (NULL != client); + + for (nc = client_head; nc != NULL; nc = nc->next) + { + if (client == nc->client) + break; + } + return nc; +} + + +/** + * Called whenever a client is disconnected. Frees our + * resources associated with that client. + * + * @param cls closure + * @param client identification of the client + */ +static void +client_disconnect_notification (void *cls, struct GNUNET_SERVER_Client *client) +{ + struct GNUNET_NAMESTORE_ZoneIteration * no; + struct GNUNET_NAMESTORE_Client * nc; + if (NULL == client) + return; + + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Client %p disconnected \n", client); + + nc = client_lookup (client); + + if ((NULL == client) || (NULL == nc)) + return; + + for (no = nc->op_head; no != NULL; no = no->next) + { + GNUNET_CONTAINER_DLL_remove (nc->op_head, nc->op_tail, no); + GNUNET_free (no); + } + + GNUNET_CONTAINER_DLL_remove (client_head, client_tail, nc); + GNUNET_free (nc); +} + +static void handle_start (void *cls, + struct GNUNET_SERVER_Client * client, + const struct GNUNET_MessageHeader * message) +{ + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Client %p connected\n", client); + + struct GNUNET_NAMESTORE_Client * nc = GNUNET_malloc (sizeof (struct GNUNET_NAMESTORE_Client)); + nc->client = client; + GNUNET_SERVER_notification_context_add (snc, client); + GNUNET_CONTAINER_DLL_insert(client_head, client_tail, nc); + + GNUNET_SERVER_receive_done (client, GNUNET_OK); +} + +struct LookupNameContext +{ + struct GNUNET_NAMESTORE_Client *nc; + uint32_t id; + uint32_t record_type; +}; + + + + +static void +handle_lookup_name_it (void *cls, + const struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *zone_key, + struct GNUNET_TIME_Absolute expire, + const char *name, + unsigned int rd_count, + const struct GNUNET_NAMESTORE_RecordData *rd, + const struct GNUNET_CRYPTO_RsaSignature *signature) +{ + /* send response */ + struct LookupNameContext *lnc = cls; + struct LookupNameResponseMessage *lnr_msg; + + struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *zone_key_tmp; + struct GNUNET_NAMESTORE_RecordData * rd_tmp; + char *name_tmp; + struct GNUNET_CRYPTO_RsaSignature *signature_tmp; + + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending `%s' message\n", "NAMESTORE_LOOKUP_NAME_RESPONSE"); + + size_t r_size = 0; + + size_t name_len = 0; + if (NULL != name) + name_len = strlen(name) + 1; + + int copied_elements = 0; + int contains_signature = 0; + int c; + + /* count records to copy */ + if (rd_count != 0) + { + if (lnc->record_type != 0) + { + /* special record type needed */ + for (c = 0; c < rd_count; c ++) + if (rd[c].record_type == lnc->record_type) + copied_elements++; /* found matching record */ + } + else + copied_elements = rd_count; + } + + if ((copied_elements == rd_count) && (signature != NULL)) + contains_signature = GNUNET_YES; + + r_size = sizeof (struct LookupNameResponseMessage) + + sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded) + + name_len + + copied_elements * sizeof (struct GNUNET_NAMESTORE_RecordData) + + contains_signature * sizeof (struct GNUNET_CRYPTO_RsaSignature); + + lnr_msg = GNUNET_malloc (r_size); + + lnr_msg->header.type = ntohs (GNUNET_MESSAGE_TYPE_NAMESTORE_LOOKUP_NAME_RESPONSE); + lnr_msg->header.size = ntohs (r_size); + lnr_msg->op_id = htonl (lnc->id); + lnr_msg->rc_count = htonl (copied_elements); + lnr_msg->name_len = htons (name_len); + lnr_msg->expire = GNUNET_TIME_absolute_hton(expire); + lnr_msg->contains_sig = htons (contains_signature); + + + zone_key_tmp = (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *) &lnr_msg[1]; + name_tmp = (char *) &zone_key_tmp[1]; + rd_tmp = (struct GNUNET_NAMESTORE_RecordData *) &name_tmp[name_len]; + signature_tmp = (struct GNUNET_CRYPTO_RsaSignature *) &rd_tmp[copied_elements]; + + if (zone_key != NULL) + memcpy (zone_key_tmp, zone_key, sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded)); + else + { + struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded dummy; + memset (&dummy, '0', sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded)); + memcpy (zone_key_tmp, &dummy, sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded)); + } + memcpy (name_tmp, name, name_len); + /* copy records */ + copied_elements = 0; + if (rd_count != 0) + { + if (lnc->record_type != 0) + { + /* special record type needed */ + for (c = 0; c < rd_count; c ++) + if (rd[c].record_type == lnc->record_type) + { + /* found matching record */ + memcpy (&rd_tmp[copied_elements], &rd[c], rd_count * sizeof (struct GNUNET_NAMESTORE_RecordData)); + copied_elements++; + } + } + else + memcpy (rd_tmp, rd, rd_count * sizeof (struct GNUNET_NAMESTORE_RecordData)); + } + + if (GNUNET_YES == contains_signature) + memcpy (signature_tmp, signature, sizeof (struct GNUNET_CRYPTO_RsaSignature)); + GNUNET_SERVER_notification_context_unicast (snc, lnc->nc->client, (const struct GNUNET_MessageHeader *) lnr_msg, GNUNET_NO); + + GNUNET_free (lnr_msg); +} + +static void handle_lookup_name (void *cls, + struct GNUNET_SERVER_Client * client, + const struct GNUNET_MessageHeader * message) +{ + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received `%s' message\n", "NAMESTORE_LOOKUP_NAME"); + struct LookupNameContext lnc; + struct GNUNET_NAMESTORE_Client *nc; + GNUNET_HashCode name_hash; + size_t name_len; + char * name; + uint32_t id = 0; + uint32_t type = 0; + + + if (ntohs (message->size) < sizeof (struct LookupNameMessage)) + { + GNUNET_break_op (0); + GNUNET_SERVER_receive_done (client, GNUNET_OK); + return; + } + + nc = client_lookup(client); + if (nc == NULL) + { + GNUNET_break_op (0); + GNUNET_SERVER_receive_done (client, GNUNET_OK); + return; + } + + struct LookupNameMessage * ln_msg = (struct LookupNameMessage *) message; + id = ntohl (ln_msg->op_id); + name_len = ntohl (ln_msg->name_len); + type = ntohl (ln_msg->record_type); + + if ((name_len == 0) || (name_len > 256)) + { + GNUNET_break_op (0); + GNUNET_SERVER_receive_done (client, GNUNET_OK); + return; + } + + name = GNUNET_malloc (name_len); + memcpy (name, &ln_msg[1], name_len); + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Looking up record for name `%s'\n", name); + GNUNET_CRYPTO_hash(name, name_len-1, &name_hash); + GNUNET_free (name); + + /* do the actual lookup */ + lnc.id = id; + lnc.nc = nc; + lnc.record_type = type; + GSN_database->iterate_records(GSN_database->cls, &ln_msg->zone, &ln_msg->zone, 0, &handle_lookup_name_it, &lnc); + + GNUNET_SERVER_receive_done (client, GNUNET_OK); +} + +static void handle_record_put (void *cls, + struct GNUNET_SERVER_Client * client, + const struct GNUNET_MessageHeader * message) +{ + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received `%s' message\n", "NAMESTORE_RECORD_PUT"); + struct GNUNET_NAMESTORE_Client *nc; + struct GNUNET_TIME_Absolute expire; + struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *zone_key; + struct GNUNET_NAMESTORE_RecordData *rd; + struct GNUNET_CRYPTO_RsaSignature *signature; + struct RecordPutResponseMessage rpr_msg; + size_t name_len; + size_t msg_size; + size_t msg_size_exp; + char * name; + char * rd_ser; + uint32_t id = 0; + uint32_t rd_ser_len; + uint32_t rd_count; + int res = GNUNET_SYSERR; + + if (ntohs (message->size) < sizeof (struct RecordPutMessage)) + { + GNUNET_break_op (0); + GNUNET_SERVER_receive_done (client, GNUNET_OK); + return; + } + + nc = client_lookup (client); + if (nc == NULL) + { + GNUNET_break_op (0); + GNUNET_SERVER_receive_done (client, GNUNET_OK); + return; + } + + struct RecordPutMessage * rp_msg = (struct RecordPutMessage *) message; + id = ntohl (rp_msg->op_id); + name_len = ntohs (rp_msg->name_len); + rd_ser_len = ntohs(rp_msg->rd_len); + msg_size = ntohs (message->size); + msg_size_exp = sizeof (struct RecordPutMessage) + sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded) + name_len + rd_ser_len; + + if (msg_size != msg_size_exp) + { + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Expected message %u size but message size is %u \n", msg_size_exp, msg_size); + GNUNET_break_op (0); + GNUNET_SERVER_receive_done (client, GNUNET_OK); + return; + } + + + if ((name_len == 0) || (name_len > 256)) + { + GNUNET_break_op (0); + GNUNET_SERVER_receive_done (client, GNUNET_OK); + return; + } + + zone_key = (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *) &rp_msg[1]; + name = (char *) &zone_key[1]; + expire = GNUNET_TIME_absolute_ntoh(rp_msg->expire); + signature = (struct GNUNET_CRYPTO_RsaSignature *) &rp_msg->signature; + rd_ser = &name[name_len]; + rd_count = GNUNET_NAMESTORE_records_deserialize(&rd, rd_ser, rd_ser_len); + + /* Database operation */ + res = GSN_database->put_records(GSN_database->cls, + zone_key, + expire, + name, + rd_count, rd, + signature); + + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Putting record for name `%s': %s\n", + name, (res == GNUNET_OK) ? "OK" : "FAIL"); + + /* Send response */ + + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending `%s' message\n", "RECORD_PUT_RESPONSE"); + rpr_msg.header.type = htons (GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_PUT_RESPONSE); + rpr_msg.op_id = rp_msg->op_id; + rpr_msg.header.size = htons (sizeof (struct RecordPutResponseMessage)); + if (GNUNET_OK == res) + rpr_msg.op_result = htons (GNUNET_OK); + else + rpr_msg.op_result = htons (GNUNET_NO); + GNUNET_SERVER_notification_context_unicast (snc, nc->client, (const struct GNUNET_MessageHeader *) &rpr_msg, GNUNET_NO); + + GNUNET_SERVER_receive_done (client, GNUNET_OK); +} + + +static void handle_record_create (void *cls, + struct GNUNET_SERVER_Client * client, + const struct GNUNET_MessageHeader * message) +{ + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received `%s' message\n", "NAMESTORE_RECORD_CREATE"); + struct GNUNET_NAMESTORE_Client *nc; + struct RecordCreateResponseMessage rcr_msg; + size_t name_len; + size_t msg_size; + size_t msg_size_exp; + uint32_t id = 0; + + int res = GNUNET_SYSERR; + + if (ntohs (message->size) < sizeof (struct RecordCreateMessage)) + { + GNUNET_break_op (0); + GNUNET_SERVER_receive_done (client, GNUNET_OK); + return; + } + + nc = client_lookup(client); + if (nc == NULL) + { + GNUNET_break_op (0); + GNUNET_SERVER_receive_done (client, GNUNET_OK); + return; + } + + struct RecordCreateMessage * rp_msg = (struct RecordCreateMessage *) message; + id = ntohl (rp_msg->op_id); + name_len = ntohs (rp_msg->name_len); + msg_size = ntohs (message->size); + msg_size_exp = sizeof (struct RecordCreateMessage) + name_len + sizeof (struct GNUNET_NAMESTORE_RecordData); + + if (msg_size != msg_size_exp) + { + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Expected message %u size but message size is %u \n", msg_size_exp, msg_size); + GNUNET_break_op (0); + GNUNET_SERVER_receive_done (client, GNUNET_OK); + return; + } + + + if ((name_len == 0) || (name_len > 256)) + { + GNUNET_break_op (0); + GNUNET_SERVER_receive_done (client, GNUNET_OK); + return; + } + + /* DO WORK HERE */ + + /* Send response */ + + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending `%s' message\n", "RECORD_CREATE_RESPONSE"); + rcr_msg.header.type = htons (GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_CREATE_RESPONSE); + rcr_msg.op_id = rp_msg->op_id; + rcr_msg.header.size = htons (sizeof (struct RecordCreateResponseMessage)); + if (GNUNET_OK == res) + rcr_msg.op_result = htons (GNUNET_OK); + else + rcr_msg.op_result = htons (GNUNET_NO); + GNUNET_SERVER_notification_context_unicast (snc, nc->client, (const struct GNUNET_MessageHeader *) &rcr_msg, GNUNET_NO); + + GNUNET_SERVER_receive_done (client, GNUNET_OK); +} + +static void handle_record_remove (void *cls, + struct GNUNET_SERVER_Client * client, + const struct GNUNET_MessageHeader * message) +{ + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received `%s' message\n", "NAMESTORE_RECORD_REMOVE"); + struct GNUNET_NAMESTORE_Client *nc; + struct RecordRemoveResponseMessage rrr_msg; + size_t name_len; + size_t msg_size; + size_t msg_size_exp; + uint32_t id = 0; + + int res = GNUNET_SYSERR; + + if (ntohs (message->size) < sizeof (struct RecordRemoveMessage)) + { + GNUNET_break_op (0); + GNUNET_SERVER_receive_done (client, GNUNET_OK); + return; + } + + nc = client_lookup(client); + if (nc == NULL) + { + GNUNET_break_op (0); + GNUNET_SERVER_receive_done (client, GNUNET_OK); + return; + } + + struct RecordRemoveMessage * rp_msg = (struct RecordRemoveMessage *) message; + id = ntohl (rp_msg->op_id); + name_len = ntohs (rp_msg->name_len); + msg_size = ntohs (message->size); + msg_size_exp = sizeof (struct RecordRemoveMessage) + name_len + sizeof (struct GNUNET_NAMESTORE_RecordData); + + if (msg_size != msg_size_exp) + { + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Expected message %u size but message size is %u \n", msg_size_exp, msg_size); + GNUNET_break_op (0); + GNUNET_SERVER_receive_done (client, GNUNET_OK); + return; + } + + + if ((name_len == 0) || (name_len > 256)) + { + GNUNET_break_op (0); + GNUNET_SERVER_receive_done (client, GNUNET_OK); + return; + } + + /* DO WORK HERE */ + + /* Send response */ + + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending `%s' message\n", "RECORD_REMOVE_RESPONSE"); + rrr_msg.header.type = htons (GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_REMOVE_RESPONSE); + rrr_msg.op_id = rp_msg->op_id; + rrr_msg.header.size = htons (sizeof (struct RecordRemoveResponseMessage)); + if (GNUNET_OK == res) + rrr_msg.op_result = htons (GNUNET_OK); + else + rrr_msg.op_result = htons (GNUNET_NO); + GNUNET_SERVER_notification_context_unicast (snc, nc->client, (const struct GNUNET_MessageHeader *) &rrr_msg, GNUNET_NO); + + GNUNET_SERVER_receive_done (client, GNUNET_OK); +} + +struct ZoneIterationProcResult +{ + int have_zone_key; + struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded zone_key; + + int have_signature; + struct GNUNET_CRYPTO_RsaSignature signature; + struct GNUNET_TIME_Absolute expire; + + int have_name; + char name[256]; + + unsigned int rd_count; + char *rd_ser; +}; + + +void zone_iteration_proc (void *cls, + const struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *zone_key, + struct GNUNET_TIME_Absolute expire, + const char *name, + unsigned int rd_count, + const struct GNUNET_NAMESTORE_RecordData *rd, + const struct GNUNET_CRYPTO_RsaSignature *signature) +{ + struct ZoneIterationProcResult *zipr = cls; + size_t len; + if (zone_key != NULL) + { + zipr->zone_key = *zone_key; + zipr->have_zone_key = GNUNET_YES; + } + else + zipr->have_zone_key = GNUNET_NO; + + zipr->expire = expire; + + if (name != NULL) + { + memcpy (zipr->name, name, strlen(name) + 1); + zipr->have_name = GNUNET_YES; + } + else + zipr->have_name = GNUNET_NO; + + zipr->rd_count = rd_count; + + if (signature != NULL) + { + zipr->signature = *signature; + zipr->have_signature = GNUNET_YES; + } + else + zipr->have_signature = GNUNET_NO; + + if ((rd_count > 0) && (rd != NULL)) + { + len = GNUNET_NAMESTORE_records_serialize (&zipr->rd_ser, rd_count, rd); + } +} + +static void handle_iteration_start (void *cls, + struct GNUNET_SERVER_Client * client, + const struct GNUNET_MessageHeader * message) +{ + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received `%s' message\n", "ZONE_ITERATION_START"); + + struct ZoneIterationStartMessage * zis_msg = (struct ZoneIterationStartMessage *) message; + struct GNUNET_NAMESTORE_Client *nc; + struct GNUNET_NAMESTORE_ZoneIteration *zi; + struct ZoneIterationResponseMessage zir_msg; + struct ZoneIterationProcResult zipr; + int res; + + nc = client_lookup(client); + if (nc == NULL) + { + GNUNET_break_op (0); + GNUNET_SERVER_receive_done (client, GNUNET_OK); + return; + } + + zi = GNUNET_malloc (sizeof (struct GNUNET_NAMESTORE_ZoneIteration)); + zi->op_id = ntohl (zis_msg->op_id); + zi->offset = 0; + zi->client = nc; + zi->zone = zis_msg->zone; + + GNUNET_CONTAINER_DLL_insert (nc->op_head, nc->op_tail, zi); + + res = GSN_database->iterate_records (GSN_database->cls, &zis_msg->zone, NULL, zi->offset , &zone_iteration_proc, &zipr); + + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending `%s' message\n", "ZONE_ITERATION_RESPONSE"); + zir_msg.header.type = htons (GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_ITERATION_RESPONSE); + zir_msg.op_id = htonl(zi->op_id); + zir_msg.header.size = htons (sizeof (struct ZoneIterationResponseMessage)); + + GNUNET_SERVER_notification_context_unicast (snc, zi->client->client, (const struct GNUNET_MessageHeader *) &zir_msg, GNUNET_NO); + + + GNUNET_SERVER_receive_done (client, GNUNET_OK); +} + +static void handle_iteration_stop (void *cls, + struct GNUNET_SERVER_Client * client, + const struct GNUNET_MessageHeader * message) +{ + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received `%s' message\n", "ZONE_ITERATION_STOP"); + + struct GNUNET_NAMESTORE_Client *nc; + struct GNUNET_NAMESTORE_ZoneIteration *zi; + struct ZoneIterationStopMessage * zis_msg = (struct ZoneIterationStopMessage *) message; + uint32_t id; + + nc = client_lookup(client); + if (nc == NULL) + { + GNUNET_break_op (0); + GNUNET_SERVER_receive_done (client, GNUNET_OK); + return; + } + + id = ntohl (zis_msg->op_id); + for (zi = nc->op_head; zi != NULL; zi = zi->next) + { + if (zi->op_id == id) + break; + } + if (zi == NULL) + { + GNUNET_break_op (0); + GNUNET_SERVER_receive_done (client, GNUNET_OK); + return; + } + + GNUNET_CONTAINER_DLL_remove(nc->op_head, nc->op_tail, zi); + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Stopped zone iteration for zone `%s'\n", GNUNET_h2s (&zi->zone)); + GNUNET_free (zi); + + GNUNET_SERVER_receive_done (client, GNUNET_OK); +} + +static void handle_iteration_next (void *cls, + struct GNUNET_SERVER_Client * client, + const struct GNUNET_MessageHeader * message) +{ + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received `%s' message\n", "ZONE_ITERATION_NEXT"); + + struct GNUNET_NAMESTORE_Client *nc; + struct GNUNET_NAMESTORE_ZoneIteration *zi; + struct ZoneIterationStopMessage * zis_msg = (struct ZoneIterationStopMessage *) message; + uint32_t id; + int res; + + nc = client_lookup(client); + if (nc == NULL) + { + GNUNET_break_op (0); + GNUNET_SERVER_receive_done (client, GNUNET_OK); + return; + } + + id = ntohl (zis_msg->op_id); + for (zi = nc->op_head; zi != NULL; zi = zi->next) + { + if (zi->op_id == id) + break; + } + if (zi == NULL) + { + GNUNET_break_op (0); + GNUNET_SERVER_receive_done (client, GNUNET_OK); + return; + } + + zi->offset++; + res = GSN_database->iterate_records (GSN_database->cls, &zi->zone, NULL, zi->offset , &zone_iteration_proc, zi); +} + + + +/** + * Process template requests. + * + * @param cls closure + * @param server the initialized server + * @param cfg configuration to use + */ +static void +run (void *cls, struct GNUNET_SERVER_Handle *server, + const struct GNUNET_CONFIGURATION_Handle *cfg) +{ + char * database; + + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Starting namestore service\n"); + + static const struct GNUNET_SERVER_MessageHandler handlers[] = { + {&handle_start, NULL, + GNUNET_MESSAGE_TYPE_NAMESTORE_START, sizeof (struct StartMessage)}, + {&handle_lookup_name, NULL, + GNUNET_MESSAGE_TYPE_NAMESTORE_LOOKUP_NAME, 0}, + {&handle_record_put, NULL, + GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_PUT, 0}, + {&handle_record_create, NULL, + GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_CREATE, 0}, + {&handle_record_remove, NULL, + GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_REMOVE, 0}, + {&handle_iteration_start, NULL, + GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_ITERATION_START, sizeof (struct ZoneIterationStartMessage)}, + {&handle_iteration_stop, NULL, + GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_ITERATION_STOP, sizeof (struct ZoneIterationStopMessage)}, + {&handle_iteration_next, NULL, + GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_ITERATION_NEXT, 0}, + {NULL, NULL, 0, 0} + }; + + GSN_cfg = cfg; + + /* Loading database plugin */ + if (GNUNET_OK != + GNUNET_CONFIGURATION_get_value_string (cfg, "namestore", "database", + &database)) + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "No database backend configured\n"); + + GNUNET_asprintf (&db_lib_name, "libgnunet_plugin_namestore_%s", database); + GSN_database = GNUNET_PLUGIN_load (db_lib_name, (void *) GSN_cfg); + if (GSN_database == NULL) + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Could not load database backend `%s'\n", + db_lib_name); + GNUNET_free (database); + + /* Configuring server handles */ + GNUNET_SERVER_add_handlers (server, handlers); + snc = GNUNET_SERVER_notification_context_create (server, 16); + GNUNET_SERVER_disconnect_notify (server, + &client_disconnect_notification, + NULL); + + GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL, &cleanup_task, + NULL); + +} + + +/** + * The main function for the template 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) +{ + return (GNUNET_OK == + GNUNET_SERVICE_run (argc, argv, "namestore", + GNUNET_SERVICE_OPTION_NONE, &run, NULL)) ? 0 : 1; +} + +/* end of gnunet-service-namestore.c */ diff --git a/src/namestore/hostkey b/src/namestore/hostkey Binary files differnew file mode 100644 index 0000000..eac1d1e --- /dev/null +++ b/src/namestore/hostkey diff --git a/src/namestore/namestore.conf.in b/src/namestore/namestore.conf.in new file mode 100644 index 0000000..c9b9984 --- /dev/null +++ b/src/namestore/namestore.conf.in @@ -0,0 +1,30 @@ +[namestore] +AUTOSTART = YES +UNIXPATH = /tmp/gnunet-service-namestore.sock +UNIX_MATCH_UID = YES +UNIX_MATCH_GID = YES +@UNIXONLY@ PORT = 2099 +HOSTNAME = localhost +HOME = $SERVICEHOME +CONFIG = $DEFAULTCONFIG +BINARY = gnunet-service-namestore +ACCEPT_FROM = 127.0.0.1; +ACCEPT_FROM6 = ::1; +DATABASE = sqlite + +[namestore-sqlite] +FILENAME = $SERVICEHOME/namestore/sqlite.db + +[namestore-postgres] +CONFIG = connect_timeout=10; dbname=gnunet + +[namestore-mysql] +DATABASE = gnunet +CONFIG = ~/.my.cnf +# USER = gnunet +# PASSWORD = +# HOST = localhost +# PORT = 3306 + + + diff --git a/src/namestore/namestore.h b/src/namestore/namestore.h new file mode 100644 index 0000000..22fc860 --- /dev/null +++ b/src/namestore/namestore.h @@ -0,0 +1,424 @@ +/* + 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 namestore/namestore.h + * @brief common internal definitions for namestore service + * @author Matthias Wachs + */ +#ifndef NAMESTORE_H +#define NAMESTORE_H + +/* + * Collect message types here, move to protocols later + */ +#define GNUNET_MESSAGE_TYPE_NAMESTORE_LOOKUP_NAME 431 +#define GNUNET_MESSAGE_TYPE_NAMESTORE_LOOKUP_NAME_RESPONSE 432 +#define GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_PUT 433 +#define GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_PUT_RESPONSE 434 +#define GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_CREATE 435 +#define GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_CREATE_RESPONSE 436 +#define GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_REMOVE 437 +#define GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_REMOVE_RESPONSE 438 + +#define GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_ITERATION_START 439 +#define GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_ITERATION_RESPONSE 440 +#define GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_ITERATION_NEXT 441 +#define GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_ITERATION_STOP 442 + +size_t +GNUNET_NAMESTORE_records_serialize (char ** dest, + unsigned int rd_count, + const struct GNUNET_NAMESTORE_RecordData *rd); + +int +GNUNET_NAMESTORE_records_deserialize ( struct GNUNET_NAMESTORE_RecordData **dest, char *src, size_t len); + +/** + * A GNS record serialized for network transmission. + * layout is [struct GNUNET_NAMESTORE_NetworkRecord][char[data_size] data] + */ +struct GNUNET_NAMESTORE_NetworkRecord +{ + /** + * Expiration time for the DNS record. + */ + struct GNUNET_TIME_AbsoluteNBO expiration; + + /** + * Number of bytes in 'data'. + */ + uint32_t data_size; + + /** + * Type of the GNS/DNS record. + */ + uint32_t record_type; + + /** + * Flags for the record. + */ + uint32_t flags; +}; + + + +GNUNET_NETWORK_STRUCT_BEGIN +/** + * Connect to namestore service + */ +struct StartMessage +{ + + /** + * Type will be GNUNET_MESSAGE_TYPE_NAMESTORE_START + */ + struct GNUNET_MessageHeader header; + +}; +GNUNET_NETWORK_STRUCT_END + + +GNUNET_NETWORK_STRUCT_BEGIN +/** + * Generic namestore message with op id + */ +struct GenericMessage +{ + /** + * Type will be GNUNET_MESSAGE_TYPE_NAMESTORE_* + */ + struct GNUNET_MessageHeader header; + + /** + * Operation ID in NBO + */ + uint32_t op_id; +}; +GNUNET_NETWORK_STRUCT_END + + +/** + * Connect to namestore service + */ +GNUNET_NETWORK_STRUCT_BEGIN +struct LookupNameMessage +{ + /** + * Type will be GNUNET_MESSAGE_TYPE_NAMESTORE_LOOKUP_NAME + */ + struct GNUNET_MessageHeader header; + + /** + * Operation ID in NBO + */ + uint32_t op_id; + + /* The zone */ + GNUNET_HashCode zone; + + /* Requested record type */ + uint32_t record_type; + + /* Requested record type */ + uint32_t name_len; +}; +GNUNET_NETWORK_STRUCT_END + + +/** + * Lookup response + * Memory layout: + * [struct LookupNameResponseMessage][struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded][char *name][rc_count * struct GNUNET_NAMESTORE_RecordData][struct GNUNET_CRYPTO_RsaSignature] + */ +GNUNET_NETWORK_STRUCT_BEGIN +struct LookupNameResponseMessage +{ + /** + * Type will be GNUNET_MESSAGE_TYPE_NAMESTORE_LOOKUP_NAME_RESPONSE + */ + struct GNUNET_MessageHeader header; + + /** + * Operation ID in NBO + */ + uint32_t op_id; + + struct GNUNET_TIME_AbsoluteNBO expire; + + uint16_t name_len; + + uint16_t contains_sig; + + /* Requested record type */ + uint32_t rc_count; +}; +GNUNET_NETWORK_STRUCT_END + + +/** + * Put a record to the namestore + * Memory layout: + * [struct RecordPutMessage][struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded][char *name][rc_count * struct GNUNET_NAMESTORE_RecordData] + */ +GNUNET_NETWORK_STRUCT_BEGIN +struct RecordPutMessage +{ + /** + * Type will be GNUNET_MESSAGE_TYPE_NAMESTORE_LOOKUP_RECORD_PUT + */ + struct GNUNET_MessageHeader header; + + /** + * Operation ID in NBO + */ + uint32_t op_id; + + /* Contenct starts here */ + + /* name length */ + uint16_t name_len; + + /* Length of serialized rd data */ + uint16_t rd_len; + + struct GNUNET_TIME_AbsoluteNBO expire; + + struct GNUNET_CRYPTO_RsaSignature signature; +}; +GNUNET_NETWORK_STRUCT_END + +/** + * Put a record to the namestore response + */ +GNUNET_NETWORK_STRUCT_BEGIN +struct RecordPutResponseMessage +{ + /** + * Type will be GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_PUT_RESPONSE + */ + struct GNUNET_MessageHeader header; + + /** + * Operation ID in NBO + */ + uint32_t op_id; + + /* Contenct starts here */ + + /** + * name length: GNUNET_NO (0) on error, GNUNET_OK (1) on success + */ + uint16_t op_result; +}; +GNUNET_NETWORK_STRUCT_END + + +/** + * Put a record to the namestore + * Memory layout: + * [struct RecordPutMessage][struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded][char *name][rc_count * struct GNUNET_NAMESTORE_RecordData] + */ +GNUNET_NETWORK_STRUCT_BEGIN +struct RecordCreateMessage +{ + /** + * Type will be GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_CREATE + */ + struct GNUNET_MessageHeader header; + + /** + * Operation ID in NBO + */ + uint32_t op_id; + + /* Contenct starts here */ + + /* name length */ + uint16_t name_len; + + struct GNUNET_CRYPTO_RsaSignature signature; +}; +GNUNET_NETWORK_STRUCT_END + + +/** + * Create a record to the namestore response + * Memory layout: + */ +GNUNET_NETWORK_STRUCT_BEGIN +struct RecordCreateResponseMessage +{ + /** + * Type will be GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_CREATE_RESPONSE + */ + struct GNUNET_MessageHeader header; + + /** + * Operation ID in NBO + */ + uint32_t op_id; + + /* Contenct starts here */ + + /** + * name length: GNUNET_NO (0) on error, GNUNET_OK (1) on success + */ + uint16_t op_result; +}; +GNUNET_NETWORK_STRUCT_END + +/** + * Remove a record from the namestore + * Memory layout: + * [struct RecordRemoveMessage][char *name][struct GNUNET_NAMESTORE_RecordData] + */ +GNUNET_NETWORK_STRUCT_BEGIN +struct RecordRemoveMessage +{ + /** + * Type will be GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_REMOVE + */ + struct GNUNET_MessageHeader header; + + /** + * Operation ID in NBO + */ + uint32_t op_id; + + /* Contenct starts here */ + + /* name length */ + uint16_t name_len; + + struct GNUNET_CRYPTO_RsaSignature signature; +}; +GNUNET_NETWORK_STRUCT_END + + +/** + * Remove a record from the namestore response + */ +GNUNET_NETWORK_STRUCT_BEGIN +struct RecordRemoveResponseMessage +{ + /** + * Type will be GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_REMOVE_RESPONSE + */ + struct GNUNET_MessageHeader header; + + /** + * Operation ID in NBO + */ + uint32_t op_id; + + /* Contenct starts here */ + + /** + * name length: GNUNET_NO (0) on error, GNUNET_OK (1) on success + */ + uint16_t op_result; +}; +GNUNET_NETWORK_STRUCT_END + + +/** + * Start a zone iteration for the given zone + */ +GNUNET_NETWORK_STRUCT_BEGIN +struct ZoneIterationStartMessage +{ + /** + * Type will be GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_ITERATION_START + */ + struct GNUNET_MessageHeader header; + + /** + * Operation ID in NBO + */ + uint32_t op_id; + + /* Contenct starts here */ + + uint16_t must_have_flags; + uint16_t must_not_have_flags; + + GNUNET_HashCode zone; +}; +GNUNET_NETWORK_STRUCT_END + +/** + * Ask for next result of zone iteration for the given operation + */ +GNUNET_NETWORK_STRUCT_BEGIN +struct ZoneIterationNextMessage +{ + /** + * Type will be GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_ITERATION_NEXT + */ + struct GNUNET_MessageHeader header; + + /** + * Operation ID in NBO + */ + uint32_t op_id; +}; +GNUNET_NETWORK_STRUCT_END + + +/** + * Stop zone iteration for the given operation + */ +GNUNET_NETWORK_STRUCT_BEGIN +struct ZoneIterationStopMessage +{ + /** + * Type will be GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_ITERATION_STOP + */ + struct GNUNET_MessageHeader header; + + /** + * Operation ID in NBO + */ + uint32_t op_id; +}; +GNUNET_NETWORK_STRUCT_END + +/** + * Ask for next result of zone iteration for the given operation + */ +GNUNET_NETWORK_STRUCT_BEGIN +struct ZoneIterationResponseMessage +{ + /** + * Type will be GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_ITERATION_RESPONSE + */ + struct GNUNET_MessageHeader header; + + /** + * Operation ID in NBO + */ + uint32_t op_id; +}; +GNUNET_NETWORK_STRUCT_END + + +/* end of namestore.h */ +#endif diff --git a/src/namestore/namestore_api.c b/src/namestore/namestore_api.c new file mode 100644 index 0000000..1d41399 --- /dev/null +++ b/src/namestore/namestore_api.c @@ -0,0 +1,1194 @@ +/* + 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 namestore/namestore_api.c + * @brief API to access the NAMESTORE service + * @author Martin Schanzenbach + * @author Matthias Wachs + */ + +#include "platform.h" +#include "gnunet_util_lib.h" +#include "gnunet_constants.h" +#include "gnunet_arm_service.h" +#include "gnunet_namestore_service.h" +#include "namestore.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 +{ + struct GNUNET_NAMESTORE_QueueEntry *next; + struct GNUNET_NAMESTORE_QueueEntry *prev; + + struct GNUNET_NAMESTORE_Handle *nsh; + + uint32_t op_id; + + GNUNET_NAMESTORE_ContinuationWithStatus cont; + void *cont_cls; + + GNUNET_NAMESTORE_RecordProcessor proc; + void *proc_cls; + + char *data; /*stub data pointer*/ +}; + + +/** + * Zone iterator + */ +struct GNUNET_NAMESTORE_ZoneIterator +{ + struct GNUNET_NAMESTORE_ZoneIterator *next; + struct GNUNET_NAMESTORE_ZoneIterator *prev; + + uint32_t op_id; + + struct GNUNET_NAMESTORE_Handle *h; + GNUNET_NAMESTORE_RecordProcessor proc; + void* proc_cls; + GNUNET_HashCode zone; + uint32_t no_flags; + uint32_t flags; +}; + + +/** + * Message in linked list we should send to the service. The + * actual binary message follows this struct. + */ +struct PendingMessage +{ + + /** + * Kept in a DLL. + */ + struct PendingMessage *next; + + /** + * Kept in a DLL. + */ + struct PendingMessage *prev; + + /** + * Size of the message. + */ + size_t size; + + /** + * Is this the 'START' message? + */ + int is_init; +}; + + +/** + * 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; + + /** + * Reconnect task + */ + GNUNET_SCHEDULER_TaskIdentifier reconnect_task; + + /** + * Pending messages to send to the service + */ + + struct PendingMessage * pending_head; + struct PendingMessage * pending_tail; + + /** + * Should we reconnect to service due to some serious error? + */ + int reconnect; + + + /** + * Pending namestore queue entries + */ + struct GNUNET_NAMESTORE_QueueEntry * op_head; + struct GNUNET_NAMESTORE_QueueEntry * op_tail; + + uint32_t op_id; + + /** + * Pending namestore zone iterator entries + */ + struct GNUNET_NAMESTORE_ZoneIterator * z_head; + struct GNUNET_NAMESTORE_ZoneIterator * z_tail; +}; + +struct GNUNET_NAMESTORE_SimpleRecord +{ + /** + * DLL + */ + struct GNUNET_NAMESTORE_SimpleRecord *next; + + /** + * DLL + */ + struct GNUNET_NAMESTORE_SimpleRecord *prev; + + const char *name; + const GNUNET_HashCode *zone; + uint32_t record_type; + struct GNUNET_TIME_Absolute expiration; + enum GNUNET_NAMESTORE_RecordFlags flags; + size_t data_size; + const void *data; +}; + + +/** + * Disconnect from service and then reconnect. + * + * @param h our handle + */ +static void +force_reconnect (struct GNUNET_NAMESTORE_Handle *h); + +static void +handle_lookup_name_response (struct GNUNET_NAMESTORE_QueueEntry *qe, + struct LookupNameResponseMessage * msg, + size_t size) +{ + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received `%s' \n", + "LOOKUP_NAME_RESPONSE"); + + struct GNUNET_NAMESTORE_Handle *h = qe->nsh; + struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *zone_key; + char *name; + struct GNUNET_NAMESTORE_RecordData *rd = NULL; + struct GNUNET_CRYPTO_RsaSignature *signature = NULL; + struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded dummy; + struct GNUNET_TIME_Absolute expire; + unsigned int rd_count = 0; + size_t msg_len = 0; + size_t name_len = 0; + int contains_sig = GNUNET_NO; + + rd_count = ntohl (msg->rc_count); + msg_len = ntohs (msg->header.size); + name_len = ntohs (msg->name_len); + contains_sig = ntohs (msg->contains_sig); + expire = GNUNET_TIME_absolute_ntoh(msg->expire); + + if (msg_len != sizeof (struct LookupNameResponseMessage) + + sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded) + + name_len + + rd_count * sizeof (struct GNUNET_NAMESTORE_RecordData) + + contains_sig * sizeof (struct GNUNET_CRYPTO_RsaSignature)) + { + GNUNET_break_op (0); + return; + } + + zone_key = (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *) &msg[1]; + name = (char *) &zone_key[1]; + rd = (struct GNUNET_NAMESTORE_RecordData *) &name[name_len]; + + /* reset values if values not contained */ + if (contains_sig == GNUNET_NO) + signature = NULL; + else + signature = (struct GNUNET_CRYPTO_RsaSignature *) &rd[rd_count]; + if (rd_count == 0) + rd = NULL; + if (name_len == 0) + name = NULL; + + memset (&dummy, '0', sizeof(struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded)); + if (0 == memcmp (zone_key, &dummy, sizeof(struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded))) + zone_key = NULL; + + if (qe->proc != NULL) + { + qe->proc (qe->proc_cls, zone_key, expire, name, rd_count, rd, signature); + } + /* Operation done, remove */ + GNUNET_CONTAINER_DLL_remove(h->op_head, h->op_tail, qe); + GNUNET_free (qe); +} + + +static void +handle_record_put_response (struct GNUNET_NAMESTORE_QueueEntry *qe, + struct RecordPutResponseMessage* msg, + size_t size) +{ + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received `%s' \n", + "RECORD_PUT_RESPONSE"); + + struct GNUNET_NAMESTORE_Handle *h = qe->nsh; + int res = GNUNET_OK; + + if (ntohs (msg->op_result) == GNUNET_OK) + { + res = GNUNET_OK; + if (qe->cont != NULL) + { + qe->cont (qe->cont_cls, res, _("Namestore added record successfully")); + } + + } + else if (ntohs (msg->op_result) == GNUNET_NO) + { + res = GNUNET_SYSERR; + if (qe->cont != NULL) + { + qe->cont (qe->cont_cls, res, _("Namestore failed to add record")); + } + } + else + { + GNUNET_break_op (0); + return; + } + + /* Operation done, remove */ + GNUNET_CONTAINER_DLL_remove(h->op_head, h->op_tail, qe); + + GNUNET_free (qe); +} + + +static void +handle_record_create_response (struct GNUNET_NAMESTORE_QueueEntry *qe, + struct RecordCreateResponseMessage* msg, + size_t size) +{ + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received `%s' \n", + "RECORD_CREATE_RESPONSE"); + + struct GNUNET_NAMESTORE_Handle *h = qe->nsh; + int res = GNUNET_OK; + + if (ntohs (msg->op_result) == GNUNET_OK) + { + res = GNUNET_OK; + if (qe->cont != NULL) + { + qe->cont (qe->cont_cls, res, _("Namestore added record successfully")); + } + + } + else if (ntohs (msg->op_result) == GNUNET_NO) + { + res = GNUNET_SYSERR; + if (qe->cont != NULL) + { + qe->cont (qe->cont_cls, res, _("Namestore failed to add record")); + } + } + else + { + GNUNET_break_op (0); + return; + } + + /* Operation done, remove */ + GNUNET_CONTAINER_DLL_remove(h->op_head, h->op_tail, qe); + + GNUNET_free (qe); +} + + +static void +manage_record_operations (struct GNUNET_NAMESTORE_QueueEntry *qe, + const struct GNUNET_MessageHeader *msg, + int type, size_t size) +{ + + /* handle different message type */ + switch (type) { + case GNUNET_MESSAGE_TYPE_NAMESTORE_LOOKUP_NAME_RESPONSE: + if (size < sizeof (struct LookupNameResponseMessage)) + { + GNUNET_break_op (0); + break; + } + handle_lookup_name_response (qe, (struct LookupNameResponseMessage *) msg, size); + break; + case GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_PUT_RESPONSE: + if (size != sizeof (struct RecordPutResponseMessage)) + { + GNUNET_break_op (0); + break; + } + handle_record_put_response (qe, (struct RecordPutResponseMessage *) msg, size); + break; + case GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_CREATE_RESPONSE: + if (size != sizeof (struct RecordCreateResponseMessage)) + { + GNUNET_break_op (0); + break; + } + handle_record_create_response (qe, (struct RecordCreateResponseMessage *) msg, size); + break; + default: + GNUNET_break_op (0); + break; + } +} + +static void +handle_zone_iteration_response (struct GNUNET_NAMESTORE_ZoneIterator *ze, + struct ZoneIterationResponseMessage *msg, + size_t size) +{ + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received `%s' \n", + "ZONE_ITERATION_RESPONSE"); + + + if (ze->proc != NULL) + { + // FIXME + ze->proc(ze->proc_cls, NULL, GNUNET_TIME_absolute_get_forever(), "dummy", 0, NULL, NULL); + } +} + + +static void +manage_zone_operations (struct GNUNET_NAMESTORE_ZoneIterator *ze, + const struct GNUNET_MessageHeader *msg, + int type, size_t size) +{ + + /* handle different message type */ + switch (type) { + case GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_ITERATION_RESPONSE: + if (size < sizeof (struct ZoneIterationResponseMessage)) + { + GNUNET_break_op (0); + break; + } + handle_zone_iteration_response (ze, (struct ZoneIterationResponseMessage *) msg, size); + break; + default: + GNUNET_break_op (0); + break; + } +} + +/** + * Type of a function to call when we receive a message + * from the service. + * + * @param cls the 'struct GNUNET_NAMESTORE_SchedulingHandle' + * @param msg message received, NULL on timeout or fatal error + */ +static void +process_namestore_message (void *cls, const struct GNUNET_MessageHeader *msg) +{ + struct GNUNET_NAMESTORE_Handle *h = cls; + struct GenericMessage * gm; + struct GNUNET_NAMESTORE_QueueEntry *qe; + struct GNUNET_NAMESTORE_ZoneIterator *ze; + uint16_t size; + uint16_t type; + uint32_t op_id = UINT32_MAX; + + if (NULL == msg) + { + force_reconnect (h); + return; + } + + size = ntohs (msg->size); + type = ntohs (msg->type); + + if (size < sizeof (struct GenericMessage)) + { + GNUNET_break_op (0); + GNUNET_CLIENT_receive (h->client, &process_namestore_message, h, + GNUNET_TIME_UNIT_FOREVER_REL); + return; + } + + gm = (struct GenericMessage *) msg; + op_id = ntohl (gm->op_id); + + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received message type %i size %i op %u\n", type, size, op_id); + + /* Find matching operation */ + if (op_id > h->op_id) + { + /* No matching pending operation found */ + GNUNET_break_op (0); + GNUNET_CLIENT_receive (h->client, &process_namestore_message, h, + GNUNET_TIME_UNIT_FOREVER_REL); + return; + } + + /* Is it a record related operation ? */ + for (qe = h->op_head; qe != NULL; qe = qe->next) + { + if (qe->op_id == op_id) + break; + } + if (qe != NULL) + { + manage_record_operations (qe, msg, type, size); + } + + /* Is it a zone iteration operation ? */ + for (ze = h->z_head; ze != NULL; ze = ze->next) + { + if (ze->op_id == op_id) + break; + } + if (ze != NULL) + { + manage_zone_operations (ze, msg, type, size); + } + + GNUNET_CLIENT_receive (h->client, &process_namestore_message, h, + GNUNET_TIME_UNIT_FOREVER_REL); + + if (GNUNET_YES == h->reconnect) + force_reconnect (h); + +} + + +/** + * Transmit messages from the message queue to the service + * (if there are any, and if we are not already trying). + * + * @param h handle to use + */ +static void +do_transmit (struct GNUNET_NAMESTORE_Handle *h); + + +/** + * We can now transmit a message to NAMESTORE. Do it. + * + * @param cls the 'struct GNUNET_NAMESTORE_Handle' + * @param size number of bytes we can transmit + * @param buf where to copy the messages + * @return number of bytes copied into buf + */ +static size_t +transmit_message_to_namestore (void *cls, size_t size, void *buf) +{ + struct GNUNET_NAMESTORE_Handle *h = cls; + struct PendingMessage *p; + size_t ret; + char *cbuf; + + h->th = NULL; + if ((size == 0) || (buf == NULL)) + { + force_reconnect (h); + return 0; + } + ret = 0; + cbuf = buf; + while ((NULL != (p = h->pending_head)) && (p->size <= size)) + { + memcpy (&cbuf[ret], &p[1], p->size); + ret += p->size; + size -= p->size; + GNUNET_CONTAINER_DLL_remove (h->pending_head, h->pending_tail, p); + if (GNUNET_YES == p->is_init) + GNUNET_CLIENT_receive (h->client, &process_namestore_message, h, + GNUNET_TIME_UNIT_FOREVER_REL); + GNUNET_free (p); + } + do_transmit (h); + return ret; +} + + +/** + * Transmit messages from the message queue to the service + * (if there are any, and if we are not already trying). + * + * @param h handle to use + */ +static void +do_transmit (struct GNUNET_NAMESTORE_Handle *h) +{ + struct PendingMessage *p; + + if (NULL != h->th) + return; + if (NULL == (p = h->pending_head)) + return; + if (NULL == h->client) + return; /* currently reconnecting */ + + h->th = GNUNET_CLIENT_notify_transmit_ready (h->client, p->size, + GNUNET_TIME_UNIT_FOREVER_REL, + GNUNET_NO, &transmit_message_to_namestore, + h); +} + + +/** + * Reconnect to namestore service. + * + * @param h the handle to the namestore service + */ +static void +reconnect (struct GNUNET_NAMESTORE_Handle *h) +{ + struct PendingMessage *p; + struct StartMessage *init; + + GNUNET_assert (NULL == h->client); + h->client = GNUNET_CLIENT_connect ("namestore", h->cfg); + GNUNET_assert (NULL != h->client); + + if ((NULL == (p = h->pending_head)) || (GNUNET_YES != p->is_init)) + { + p = GNUNET_malloc (sizeof (struct PendingMessage) + + sizeof (struct StartMessage)); + p->size = sizeof (struct StartMessage); + p->is_init = GNUNET_YES; + init = (struct StartMessage *) &p[1]; + init->header.type = htons (GNUNET_MESSAGE_TYPE_NAMESTORE_START); + init->header.size = htons (sizeof (struct StartMessage)); + GNUNET_CONTAINER_DLL_insert (h->pending_head, h->pending_tail, p); + } + do_transmit (h); +} + +/** + * Re-establish the connection to the service. + * + * @param cls handle to use to re-connect. + * @param tc scheduler context + */ +static void +reconnect_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) +{ + struct GNUNET_NAMESTORE_Handle *h = cls; + + h->reconnect_task = GNUNET_SCHEDULER_NO_TASK; + reconnect (h); +} + + +/** + * Disconnect from service and then reconnect. + * + * @param h our handle + */ +static void +force_reconnect (struct GNUNET_NAMESTORE_Handle *h) +{ + h->reconnect = GNUNET_NO; + GNUNET_CLIENT_disconnect (h->client, GNUNET_NO); + h->client = NULL; + h->reconnect_task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_SECONDS, + &reconnect_task, + h); +} + +static uint32_t +get_op_id (struct GNUNET_NAMESTORE_Handle *h) +{ + uint32_t op_id = h->op_id; + h->op_id ++; + return op_id; +} + +/** + * 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 *h; + + h = GNUNET_malloc (sizeof (struct GNUNET_NAMESTORE_Handle)); + h->cfg = cfg; + h->reconnect_task = GNUNET_SCHEDULER_add_now (&reconnect_task, h); + h->op_id = 0; + return h; +} + + +/** + * Disconnect from the namestore service (and free associated + * resources). + * + * @param h handle to the namestore + * @param drop set to GNUNET_YES to delete all data in namestore (!) + */ +void +GNUNET_NAMESTORE_disconnect (struct GNUNET_NAMESTORE_Handle *h, int drop) +{ + struct PendingMessage *p; + struct GNUNET_NAMESTORE_QueueEntry *q; + struct GNUNET_NAMESTORE_ZoneIterator *z; + + GNUNET_assert (h != NULL); + + while (NULL != (p = h->pending_head)) + { + GNUNET_CONTAINER_DLL_remove (h->pending_head, h->pending_tail, p); + GNUNET_free (p); + } + + while (NULL != (q = h->op_head)) + { + GNUNET_CONTAINER_DLL_remove (h->op_head, h->op_tail, q); + GNUNET_free (q); + } + + while (NULL != (z = h->z_head)) + { + GNUNET_CONTAINER_DLL_remove (h->z_head, h->z_tail, z); + GNUNET_free (z); + } + + if (NULL != h->client) + { + GNUNET_CLIENT_disconnect (h->client, GNUNET_NO); + h->client = NULL; + } + if (GNUNET_SCHEDULER_NO_TASK != h->reconnect_task) + { + GNUNET_SCHEDULER_cancel (h->reconnect_task); + h->reconnect_task = GNUNET_SCHEDULER_NO_TASK; + } + GNUNET_free(h); + h = NULL; +} + + +/** + * 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. This API is used when we cache signatures from other + * authorities. + * + * @param h handle to the namestore + * @param zone_key public key of the zone + * @param name name that is being mapped (at most 255 characters long) + * @param expire when does the corresponding block in the DHT expire (until + * when should we never do a DHT lookup for the same name again)? + * @param rd_count number of entries in 'rd' array + * @param rd array of records with data to store + * @param signature signature for all the records in the zone under the given name + * @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 *zone_key, + const char *name, + struct GNUNET_TIME_Absolute expire, + 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; + struct PendingMessage *pe; + + /* pointer to elements */ + struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *zone_key_tmp; + char * rd_tmp; + char * rd_ser; + char * name_tmp; + + size_t msg_size = 0; + size_t name_len = strlen(name) + 1; + size_t rd_ser_len = 0; + uint32_t id = 0; + + GNUNET_assert (NULL != h); + id = get_op_id(h); + qe = GNUNET_malloc(sizeof (struct GNUNET_NAMESTORE_QueueEntry)); + qe->nsh = h; + qe->cont = cont; + qe->cont_cls = cont_cls; + qe->op_id = id; + GNUNET_CONTAINER_DLL_insert_tail(h->op_head, h->op_tail, qe); + + /* set msg_size*/ + rd_ser_len = GNUNET_NAMESTORE_records_serialize(&rd_ser, rd_count, rd); + + struct RecordPutMessage * msg; + msg_size = sizeof (struct RecordPutMessage) + sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded) + name_len + rd_ser_len; + + /* create msg here */ + pe = GNUNET_malloc(sizeof (struct PendingMessage) + msg_size); + pe->size = msg_size; + pe->is_init = GNUNET_NO; + msg = (struct RecordPutMessage *) &pe[1]; + zone_key_tmp = (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *) &msg[1]; + name_tmp = (char *) &zone_key_tmp[1]; + rd_tmp = &name_tmp[name_len]; + + msg->header.type = htons (GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_PUT); + msg->header.size = htons (msg_size); + msg->op_id = htonl (id); + memcpy (zone_key_tmp, zone_key, sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded)); + msg->signature = *signature; + msg->name_len = htons (name_len); + memcpy (name_tmp, name, name_len); + msg->expire = GNUNET_TIME_absolute_hton (expire); + msg->rd_len = htons (rd_ser_len); + + memcpy (rd_tmp, rd_ser, rd_ser_len); + GNUNET_free (rd_ser); + + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending `%s' message for name `%s' with size %u\n", "NAMESTORE_RECORD_PUT", name, msg_size); + + GNUNET_CONTAINER_DLL_insert_tail (h->pending_head, h->pending_tail, pe); + do_transmit(h); + + return qe; +} + + +/** + * Check if a signature is valid. This API is used by the GNS Block + * to validate signatures received from the network. + * + * @param public_key public key of the zone + * @param name name that is being mapped (at most 255 characters long) + * @param rd_count number of entries in 'rd' array + * @param rd array of records with data to store + * @param signature signature for all the records in the zone under the given name + * @return GNUNET_OK if the signature is valid + */ +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_SYSERR; +} + +/** + * 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. This API is used by the authority of a zone. + * + * @param h handle to the namestore + * @param pkey private key of the zone + * @param name name that is being mapped (at most 255 characters long) + * @param rd record data to store + * @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_create (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; + struct PendingMessage *pe; + char * name_tmp; + char * rd_tmp; + char * rd_ser; + size_t rd_ser_len = 0; + size_t msg_size = 0; + size_t name_len = 0; + uint32_t id = 0; + + GNUNET_assert (NULL != h); + + id = get_op_id(h); + qe = GNUNET_malloc(sizeof (struct GNUNET_NAMESTORE_QueueEntry)); + qe->nsh = h; + qe->cont = cont; + qe->cont_cls = cont_cls; + qe->op_id = id; + + /* set msg_size*/ + rd_ser_len = GNUNET_NAMESTORE_records_serialize(&rd_ser, 1, rd); + struct RecordCreateMessage * msg; + msg_size = sizeof (struct RecordCreateMessage) + name_len + rd_ser_len; + + /* create msg here */ + pe = GNUNET_malloc(sizeof (struct PendingMessage) + msg_size); + pe->size = msg_size; + pe->is_init = GNUNET_NO; + msg = (struct RecordCreateMessage *) &pe[1]; + + name_tmp = (char *) &msg[1]; + rd_tmp = &name_tmp[name_len]; + + msg->header.type = htons (GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_CREATE); + msg->header.size = htons (msg_size); + msg->op_id = htonl (id); + //msg->signature = *signature; + msg->name_len = htons (name_len); + memcpy (name_tmp, name, name_len); + memcpy (rd_tmp, rd_ser, rd_ser_len); + GNUNET_free (rd_ser); + + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending `%s' message for name `%s' with size %u\n", "NAMESTORE_RECORD_CREATE", name, msg_size); + + GNUNET_CONTAINER_DLL_insert_tail (h->pending_head, h->pending_tail, pe); + do_transmit(h); + 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. + * This API is used by the authority of a zone. + * + * @param h handle to the namestore + * @param pkey private key of the zone + * @param name name that is being mapped (at most 255 characters long) + * @param rd record data + * @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; + struct PendingMessage *pe; + char * rd_tmp; + char * rd_ser; + char * name_tmp; + size_t rd_ser_len = 0; + size_t msg_size = 0; + size_t name_len = 0; + uint32_t id = 0; + + GNUNET_assert (NULL != h); + + id = get_op_id(h); + qe = GNUNET_malloc(sizeof (struct GNUNET_NAMESTORE_QueueEntry)); + qe->nsh = h; + qe->cont = cont; + qe->cont_cls = cont_cls; + qe->op_id = id; + + /* set msg_size*/ + rd_ser_len = GNUNET_NAMESTORE_records_serialize(&rd_ser, 1, rd); + struct RecordRemoveMessage * msg; + msg_size = sizeof (struct RecordRemoveMessage) + name_len + rd_ser_len; + + /* create msg here */ + pe = GNUNET_malloc(sizeof (struct PendingMessage) + msg_size); + pe->size = msg_size; + pe->is_init = GNUNET_NO; + msg = (struct RecordRemoveMessage *) &pe[1]; + + name_tmp = (char *) &msg[1]; + rd_tmp = &name_tmp[name_len]; + + msg->header.type = htons (GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_REMOVE); + msg->header.size = htons (msg_size); + msg->op_id = htonl (id); + //msg->signature = *signature; + msg->name_len = htons (name_len); + memcpy (name_tmp, name, name_len); + memcpy (rd_tmp, rd_ser, rd_ser_len); + GNUNET_free (rd_ser); + + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending `%s' message for name `%s' with size %u\n", "NAMESTORE_RECORD_REMOVE", name, msg_size); + + GNUNET_CONTAINER_DLL_insert_tail (h->pending_head, h->pending_tail, pe); + do_transmit(h); + 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, 0 for all + * @param proc function to call on the matching records, or with + * NULL (rd_count == 0) if there are no matching records + * @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; + struct PendingMessage *pe; + size_t msg_size = 0; + size_t name_len = 0; + uint32_t id = 0; + + GNUNET_assert (NULL != h); + GNUNET_assert (NULL != zone); + GNUNET_assert (NULL != name); + + name_len = strlen (name) + 1; + if ((name_len == 0) || (name_len > 256)) + { + GNUNET_break (0); + return NULL; + } + + id = get_op_id(h); + qe = GNUNET_malloc(sizeof (struct GNUNET_NAMESTORE_QueueEntry)); + qe->nsh = h; + qe->proc = proc; + qe->proc_cls = proc_cls; + qe->op_id = id; + GNUNET_CONTAINER_DLL_insert_tail(h->op_head, h->op_tail, qe); + + /* set msg_size*/ + msg_size = sizeof (struct LookupNameMessage) + name_len; + pe = GNUNET_malloc(sizeof (struct PendingMessage) + msg_size); + + /* create msg here */ + struct LookupNameMessage * msg; + pe->size = msg_size; + pe->is_init = GNUNET_NO; + msg = (struct LookupNameMessage *) &pe[1]; + msg->header.type = htons (GNUNET_MESSAGE_TYPE_NAMESTORE_LOOKUP_NAME); + msg->header.size = htons (msg_size); + msg->op_id = htonl (id); + msg->record_type = htonl (record_type); + msg->zone = *zone; + msg->name_len = htonl (name_len); + memcpy (&msg[1], name, name_len); + + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending `%s' message for name `%s'\n", "NAMESTORE_LOOKUP_NAME", name); + + /* transmit message */ + GNUNET_CONTAINER_DLL_insert_tail (h->pending_head, h->pending_tail, pe); + do_transmit(h); + + return qe; +} + + + +/** + * Starts a new zone iteration (used to periodically PUT all of our + * records into our DHT). This MUST lock the GNUNET_NAMESTORE_Handle + * for any other calls than GNUNET_NAMESTORE_zone_iterator_next and + * GNUNET_NAMESTORE_zone_iteration_stop. "proc" will be called once + * immediately, and then again after + * "GNUNET_NAMESTORE_zone_iterator_next" is invoked. + * + * @param h handle to the namestore + * @param zone zone to access, NULL for all zones + * @param must_have_flags flags that must be set for the record to be returned + * @param must_not_have_flags flags that must NOT be set for the record to be returned + * @param proc function to call on each name from the zone; it + * will be called repeatedly with a value (if available) + * and always once at the end with a name of NULL. + * @param proc_cls closure for proc + * @return an iterator handle to use for iteration + */ +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; + struct PendingMessage *pe; + size_t msg_size = 0; + uint32_t id = 0; + + GNUNET_assert (NULL != h); + GNUNET_assert (NULL != zone); + + id = get_op_id(h); + it = GNUNET_malloc (sizeof (struct GNUNET_NAMESTORE_ZoneIterator)); + it->h = h; + it->proc = proc; + it->proc_cls = proc; + it->op_id = id; + it->zone = *zone; + GNUNET_CONTAINER_DLL_insert_tail(h->z_head, h->z_tail, it); + + /* set msg_size*/ + msg_size = sizeof (struct ZoneIterationStartMessage); + pe = GNUNET_malloc(sizeof (struct PendingMessage) + msg_size); + + /* create msg here */ + struct ZoneIterationStartMessage * msg; + pe->size = msg_size; + pe->is_init = GNUNET_NO; + msg = (struct ZoneIterationStartMessage *) &pe[1]; + msg->header.type = htons (GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_ITERATION_START); + msg->header.size = htons (msg_size); + msg->op_id = htonl (id); + msg->zone = *zone; + msg->must_have_flags = ntohs (must_have_flags); + msg->must_not_have_flags = ntohs (must_not_have_flags); + + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending `%s' message for zone `%s'\n", "ZONE_ITERATION_START", GNUNET_h2s(zone)); + + /* transmit message */ + GNUNET_CONTAINER_DLL_insert_tail (h->pending_head, h->pending_tail, pe); + do_transmit(h); + + return it; +} + + +/** + * Calls the record processor specified in GNUNET_NAMESTORE_zone_iteration_start + * for the next record. + * + * @param it the iterator + */ +void +GNUNET_NAMESTORE_zone_iterator_next (struct GNUNET_NAMESTORE_ZoneIterator *it) +{ + struct GNUNET_NAMESTORE_Handle *h; + struct PendingMessage *pe; + size_t msg_size = 0; + + GNUNET_assert (NULL != it); + h = it->h; + + /* set msg_size*/ + msg_size = sizeof (struct ZoneIterationNextMessage); + pe = GNUNET_malloc(sizeof (struct PendingMessage) + msg_size); + + /* create msg here */ + struct ZoneIterationNextMessage * msg; + pe->size = msg_size; + pe->is_init = GNUNET_NO; + msg = (struct ZoneIterationNextMessage *) &pe[1]; + msg->header.type = htons (GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_ITERATION_NEXT); + msg->header.size = htons (msg_size); + msg->op_id = htonl (it->op_id); + + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending `%s' message for name `%s'\n", "ZONE_ITERATION_NEXT", GNUNET_h2s(&it->zone)); + + /* transmit message */ + GNUNET_CONTAINER_DLL_insert_tail (h->pending_head, h->pending_tail, pe); + do_transmit(h); +} + + +/** + * Stops iteration and releases the namestore handle for further calls. + * + * @param it the iterator + */ +void +GNUNET_NAMESTORE_zone_iteration_stop (struct GNUNET_NAMESTORE_ZoneIterator *it) +{ + GNUNET_assert (NULL != it); + struct PendingMessage *pe; + size_t msg_size = 0; + struct GNUNET_NAMESTORE_Handle *h = it->h; + + /* set msg_size*/ + msg_size = sizeof (struct ZoneIterationStopMessage); + pe = GNUNET_malloc(sizeof (struct PendingMessage) + msg_size); + + /* create msg here */ + struct ZoneIterationStopMessage * msg; + pe->size = msg_size; + pe->is_init = GNUNET_NO; + msg = (struct ZoneIterationStopMessage *) &pe[1]; + msg->header.type = htons (GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_ITERATION_STOP); + msg->header.size = htons (msg_size); + msg->op_id = htonl (it->op_id); + + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending `%s' message for name `%s'\n", "ZONE_ITERATION_STOP", GNUNET_h2s(&it->zone)); + + /* transmit message */ + GNUNET_CONTAINER_DLL_insert_tail (h->pending_head, h->pending_tail, pe); + do_transmit(h); +} + + +/** + * 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) +{ + struct GNUNET_NAMESTORE_Handle *h = qe->nsh; + + GNUNET_assert (qe != NULL); + + GNUNET_CONTAINER_DLL_remove(h->op_head, h->op_tail, qe); + GNUNET_free(qe); + +} + +/* end of namestore_api.c */ diff --git a/src/namestore/namestore_common.c b/src/namestore/namestore_common.c new file mode 100644 index 0000000..37f0eab --- /dev/null +++ b/src/namestore/namestore_common.c @@ -0,0 +1,159 @@ +/* + 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 namestore/namestore_common.c + * @brief API to access the NAMESTORE service + * @author Martin Schanzenbach + * @author Matthias Wachs + */ + +#include "platform.h" +#include "gnunet_util_lib.h" +#include "gnunet_constants.h" +#include "gnunet_arm_service.h" +#include "gnunet_namestore_service.h" +#include "namestore.h" +#define DEBUG_GNS_API GNUNET_EXTRA_LOGGING + +#define LOG(kind,...) GNUNET_log_from (kind, "gns-api",__VA_ARGS__) +/** + * Serialize an array of GNUNET_NAMESTORE_RecordData *rd to transmit over the + * network + * + * @param dest where to write the serialized data + * @param rd_count number of elements in array + * @param rd array + * + * @return number of bytes written to destination dest + */ +size_t +GNUNET_NAMESTORE_records_serialize (char ** dest, + unsigned int rd_count, + const struct GNUNET_NAMESTORE_RecordData *rd) +{ + //size_t len = 0; + struct GNUNET_NAMESTORE_NetworkRecord * nr; + char * d = (*dest); + int c = 0; + int offset; + + + size_t total_len = rd_count * sizeof (struct GNUNET_NAMESTORE_NetworkRecord); + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Struct size: %u\n", total_len); + + /* figure out total len required */ + for (c = 0; c < rd_count; c ++) + { + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Data size record[%i] : %u\n", c, rd[c].data_size); + total_len += rd[c].data_size; + } + + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Serializing %i records with total length of %llu\n", rd_count, total_len); + + (*dest) = GNUNET_malloc (total_len); + d = (*dest); + + /* copy records */ + offset = 0; + + for (c = 0; c < rd_count; c ++) + { + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Serialized record [%i]: data_size %i\n", c,rd[c].data_size); + + nr = (struct GNUNET_NAMESTORE_NetworkRecord *) &d[offset]; + nr->data_size = htonl (rd[c].data_size); + nr->flags = htonl (rd[c].flags); + nr->record_type = htonl (rd[c].record_type); + nr->expiration = GNUNET_TIME_absolute_hton(rd[c].expiration); + + /*put data here */ + offset += sizeof (struct GNUNET_NAMESTORE_NetworkRecord); + memcpy (&d[offset], rd[c].data, rd[c].data_size); + offset += rd[c].data_size; + } + + GNUNET_assert (offset == total_len); + return total_len; +} + + +/** + * Deserialize an array of GNUNET_NAMESTORE_RecordData *rd after transmission + * over the network + * + * @param source where to read the data to deserialize + * @param rd_count number of elements in array + * @param rd array + * + * @return number of elements deserialized + */ +int +GNUNET_NAMESTORE_records_deserialize ( struct GNUNET_NAMESTORE_RecordData **dest, char *src, size_t len) +{ + struct GNUNET_NAMESTORE_NetworkRecord * nr; + struct GNUNET_NAMESTORE_RecordData *d = (*dest); + int elements; + size_t offset; + uint32_t data_size; + int c; + + offset = 0; + elements = 0; + while (offset < len) + { + nr = (struct GNUNET_NAMESTORE_NetworkRecord *) &src[offset]; + offset += sizeof (struct GNUNET_NAMESTORE_NetworkRecord); + + data_size = ntohl (nr->data_size); + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Datasize record[%i]: %u\n", elements, data_size); + offset += data_size; + elements ++; + } + + GNUNET_assert (len == offset); + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Deserializing %i records with total length of %u\n", elements, len); + + (*dest) = GNUNET_malloc (elements * sizeof (struct GNUNET_NAMESTORE_RecordData)); + d = (*dest); + + offset = 0; + for (c = 0; c < elements; c++) + { + nr = (struct GNUNET_NAMESTORE_NetworkRecord *) &src[offset]; + d[c].expiration = GNUNET_TIME_absolute_ntoh(nr->expiration); + d[c].record_type = ntohl (nr->record_type); + d[c].flags = ntohl (nr->flags); + d[c].data_size = ntohl (nr->data_size); + d[c].data = GNUNET_malloc (d[c].data_size); + GNUNET_assert (d[c].data != NULL); + + offset += sizeof (struct GNUNET_NAMESTORE_NetworkRecord); + memcpy((char *) d[c].data, &src[offset], d[c].data_size); + + offset += d[c].data_size; + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Deserialized record[%i] /w data_size %i\n", c, d[c].data_size); + } + GNUNET_assert(offset == len); + + return elements; +} + +/* end of namestore_api.c */ diff --git a/src/namestore/plugin_namestore_sqlite.c b/src/namestore/plugin_namestore_sqlite.c new file mode 100644 index 0000000..c297216 --- /dev/null +++ b/src/namestore/plugin_namestore_sqlite.c @@ -0,0 +1,806 @@ + /* + * This file is part of GNUnet + * (C) 2009, 2011, 2012 Christian Grothoff (and other contributing authors) + * + * GNUnet is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published + * by the Free Software Foundation; either version 3, or (at your + * option) any later version. + * + * GNUnet is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNUnet; see the file COPYING. If not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +/** + * @file namestore/plugin_namestore_sqlite.c + * @brief sqlite-based namestore backend + * @author Christian Grothoff + */ + +#include "platform.h" +#include "gnunet_namestore_plugin.h" +#include <sqlite3.h> + +/** + * After how many ms "busy" should a DB operation fail for good? + * A low value makes sure that we are more responsive to requests + * (especially PUTs). A high value guarantees a higher success + * rate (SELECTs in iterate can take several seconds despite LIMIT=1). + * + * The default value of 1s should ensure that users do not experience + * huge latencies while at the same time allowing operations to succeed + * with reasonable probability. + */ +#define BUSY_TIMEOUT_MS 1000 + + +/** + * Log an error message at log-level 'level' that indicates + * a failure of the command 'cmd' on file 'filename' + * with the message given by strerror(errno). + */ +#define LOG_SQLITE(db, level, cmd) do { GNUNET_log_from (level, "namestore-sqlite", _("`%s' failed at %s:%d with error: %s\n"), cmd, __FILE__, __LINE__, sqlite3_errmsg(db->dbh)); } while(0) + +#define LOG(kind,...) GNUNET_log_from (kind, "namestore-sqlite", __VA_ARGS__) + + +/** + * Context for all functions in this plugin. + */ +struct Plugin +{ + + const struct GNUNET_CONFIGURATION_Handle *cfg; + + /** + * Database filename. + */ + char *fn; + + /** + * Native SQLite database handle. + */ + sqlite3 *dbh; + + /** + * Precompiled SQL for put record + */ + sqlite3_stmt *put_records; + + /** + * Precompiled SQL for remove record + */ + sqlite3_stmt *remove_records; + + /** + * Precompiled SQL for iterate over all records. + */ + sqlite3_stmt *iterate_all; + + /** + * Precompiled SQL for iterate records with same name. + */ + sqlite3_stmt *iterate_by_name; + + /** + * Precompiled SQL for iterate records with same zone. + */ + sqlite3_stmt *iterate_by_zone; + + /** + * Precompiled SQL for iterate records with same name and zone. + */ + sqlite3_stmt *iterate_records; + + /** + * Precompiled SQL for delete zone + */ + sqlite3_stmt *delete_zone; + +}; + + +/** + * Internal format of a record in the BLOB in the database. + */ +struct DbRecord +{ + + /** + * Expiration time for the DNS record. + */ + struct GNUNET_TIME_AbsoluteNBO expiration; + + /** + * Number of bytes in 'data', network byte order. + */ + uint32_t data_size; + + /** + * Type of the GNS/DNS record, network byte order. + */ + uint32_t record_type; + + /** + * Flags for the record, network byte order. + */ + uint32_t flags; + +}; + + +/** + * @brief Prepare a SQL statement + * + * @param dbh handle to the database + * @param zSql SQL statement, UTF-8 encoded + * @param ppStmt set to the prepared statement + * @return 0 on success + */ +static int +sq_prepare (sqlite3 * dbh, const char *zSql, sqlite3_stmt ** ppStmt) +{ + char *dummy; + int result; + + result = + sqlite3_prepare_v2 (dbh, zSql, strlen (zSql), ppStmt, + (const char **) &dummy); + LOG (GNUNET_ERROR_TYPE_DEBUG, + "Prepared `%s' / %p: %d\n", zSql, *ppStmt, result); + return result; +} + + +/** + * Create our database indices. + * + * @param dbh handle to the database + */ +static void +create_indices (sqlite3 * dbh) +{ + /* create indices */ + if ( (SQLITE_OK != + sqlite3_exec (dbh, "CREATE INDEX IF NOT EXISTS ir_zone_name_rv ON ns090records (zone_hash,record_name_hash,rvalue)", + NULL, NULL, NULL)) || + (SQLITE_OK != + sqlite3_exec (dbh, "CREATE INDEX IF NOT EXISTS ir_zone_rv ON ns090records (zone_hash,rvalue)", + NULL, NULL, NULL)) || + (SQLITE_OK != + sqlite3_exec (dbh, "CREATE INDEX IF NOT EXISTS ir_zone ON ns090records (zone_hash)", + NULL, NULL, NULL)) || + (SQLITE_OK != + sqlite3_exec (dbh, "CREATE INDEX IF NOT EXISTS ir_name_rv ON ns090records (record_name_hash,rvalue)", + NULL, NULL, NULL)) || + (SQLITE_OK != + sqlite3_exec (dbh, "CREATE INDEX IF NOT EXISTS ir_rv ON ns090records (rvalue)", + NULL, NULL, NULL)) ) + LOG (GNUNET_ERROR_TYPE_ERROR, + "Failed to create indices: %s\n", sqlite3_errmsg (dbh)); +} + + +#if 0 +#define CHECK(a) GNUNET_break(a) +#define ENULL NULL +#else +#define ENULL &e +#define ENULL_DEFINED 1 +#define CHECK(a) if (! a) { GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "%s\n", e); sqlite3_free(e); } +#endif + + +/** + * Initialize the database connections and associated + * data structures (create tables and indices + * as needed as well). + * + * @param plugin the plugin context (state for this module) + * @return GNUNET_OK on success + */ +static int +database_setup (struct Plugin *plugin) +{ + sqlite3_stmt *stmt; + char *afsdir; +#if ENULL_DEFINED + char *e; +#endif + + if (GNUNET_OK != + GNUNET_CONFIGURATION_get_value_filename (plugin->cfg, "namestore-sqlite", + "FILENAME", &afsdir)) + { + LOG (GNUNET_ERROR_TYPE_ERROR, + _ ("Option `%s' in section `%s' missing in configuration!\n"), + "FILENAME", "namestore-sqlite"); + return GNUNET_SYSERR; + } + if (GNUNET_OK != GNUNET_DISK_file_test (afsdir)) + { + if (GNUNET_OK != GNUNET_DISK_directory_create_for_file (afsdir)) + { + GNUNET_break (0); + GNUNET_free (afsdir); + return GNUNET_SYSERR; + } + } +#ifdef ENABLE_NLS + plugin->fn = + GNUNET_STRINGS_to_utf8 (afsdir, strlen (afsdir), nl_langinfo (CODESET)); +#else + plugin->fn = GNUNET_STRINGS_to_utf8 (afsdir, strlen (afsdir), "UTF-8"); /* good luck */ +#endif + GNUNET_free (afsdir); + + /* Open database and precompile statements */ + if (sqlite3_open (plugin->fn, &plugin->dbh) != SQLITE_OK) + { + LOG (GNUNET_ERROR_TYPE_ERROR, + _("Unable to initialize SQLite: %s.\n"), + sqlite3_errmsg (plugin->dbh)); + return GNUNET_SYSERR; + } + CHECK (SQLITE_OK == + sqlite3_exec (plugin->dbh, "PRAGMA temp_store=MEMORY", NULL, NULL, + ENULL)); + CHECK (SQLITE_OK == + sqlite3_exec (plugin->dbh, "PRAGMA synchronous=NORMAL", NULL, NULL, + ENULL)); + CHECK (SQLITE_OK == + sqlite3_exec (plugin->dbh, "PRAGMA legacy_file_format=OFF", NULL, NULL, + ENULL)); + CHECK (SQLITE_OK == + sqlite3_exec (plugin->dbh, "PRAGMA auto_vacuum=INCREMENTAL", NULL, + NULL, ENULL)); + CHECK (SQLITE_OK == + sqlite3_exec (plugin->dbh, "PRAGMA encoding=\"UTF-8\"", NULL, + NULL, ENULL)); + CHECK (SQLITE_OK == + sqlite3_exec (plugin->dbh, "PRAGMA locking_mode=EXCLUSIVE", NULL, NULL, + ENULL)); + CHECK (SQLITE_OK == + sqlite3_exec (plugin->dbh, "PRAGMA count_changes=OFF", NULL, NULL, + ENULL)); + CHECK (SQLITE_OK == + sqlite3_exec (plugin->dbh, "PRAGMA page_size=4092", NULL, NULL, + ENULL)); + + CHECK (SQLITE_OK == sqlite3_busy_timeout (plugin->dbh, BUSY_TIMEOUT_MS)); + + + /* Create tables */ + CHECK (SQLITE_OK == + sq_prepare (plugin->dbh, + "SELECT 1 FROM sqlite_master WHERE tbl_name = 'ns090records'", + &stmt)); + if ((sqlite3_step (stmt) == SQLITE_DONE) && + (sqlite3_exec + (plugin->dbh, + "CREATE TABLE ns090records (" + " zone_key BLOB NOT NULL DEFAULT ''," + " zone_hash BLOB NOT NULL DEFAULT ''," + " record_count INT NOT NULL DEFAULT 0," + " record_data BLOB NOT NULL DEFAULT ''," + " block_expiration_time INT8 NOT NULL DEFAULT 0," + " signature BLOB NOT NULL DEFAULT ''," + " record_name TEXT NOT NULL DEFAULT ''," + " record_name_hash BLOB NOT NULL DEFAULT ''," + " rvalue INT8 NOT NULL DEFAULT ''" + ")", + NULL, NULL, NULL) != SQLITE_OK)) + { + LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_ERROR, "sqlite3_exec"); + sqlite3_finalize (stmt); + return GNUNET_SYSERR; + } + sqlite3_finalize (stmt); + + create_indices (plugin->dbh); + +#define ALL "zone_key, record_name, record_count, record_data, block_expiration_time, signature" + if ((sq_prepare + (plugin->dbh, + "INSERT INTO ns090records (" ALL ", zone_hash, record_name_hash, rvalue) VALUES " + "(?, ?, ?, ?, ?, ?, ?, ?, ?)", + &plugin->put_records) != SQLITE_OK) || + (sq_prepare + (plugin->dbh, + "DELETE FROM ns090records WHERE zone_hash=? AND record_name_hash=?", + &plugin->remove_records) != SQLITE_OK) || + (sq_prepare + (plugin->dbh, + "SELECT " ALL + " FROM ns090records WHERE zone_hash=? AND record_name_hash=? ORDER BY rvalue LIMIT 1 OFFSET ?", + &plugin->iterate_records) != SQLITE_OK) || + (sq_prepare + (plugin->dbh, + "SELECT " ALL + " FROM ns090records WHERE zone_hash=? ORDER BY rvalue LIMIT 1 OFFSET ?", + &plugin->iterate_by_zone) != SQLITE_OK) || + (sq_prepare + (plugin->dbh, + "SELECT " ALL + " FROM ns090records WHERE record_name_hash=? ORDER BY rvalue LIMIT 1 OFFSET ?", + &plugin->iterate_by_name) != SQLITE_OK) || + (sq_prepare + (plugin->dbh, + "SELECT " ALL + " FROM ns090records ORDER BY rvalue LIMIT 1 OFFSET ?", + &plugin->iterate_all) != SQLITE_OK) || + (sq_prepare + (plugin->dbh, + "DELETE FROM ns090records WHERE zone_hash=?", + &plugin->delete_zone) != SQLITE_OK) ) + { + LOG_SQLITE (plugin,GNUNET_ERROR_TYPE_ERROR, "precompiling"); + return GNUNET_SYSERR; + } +#undef ALL + return GNUNET_OK; +} + + +/** + * Shutdown database connection and associate data + * structures. + * @param plugin the plugin context (state for this module) + */ +static void +database_shutdown (struct Plugin *plugin) +{ + int result; + sqlite3_stmt *stmt; + + if (NULL != plugin->put_records) + sqlite3_finalize (plugin->put_records); + if (NULL != plugin->remove_records) + sqlite3_finalize (plugin->remove_records); + if (NULL != plugin->iterate_records) + sqlite3_finalize (plugin->iterate_records); + if (NULL != plugin->iterate_records) + sqlite3_finalize (plugin->iterate_by_zone); + if (NULL != plugin->iterate_records) + sqlite3_finalize (plugin->iterate_by_name); + if (NULL != plugin->iterate_records) + sqlite3_finalize (plugin->iterate_all); + if (NULL != plugin->delete_zone) + sqlite3_finalize (plugin->delete_zone); + result = sqlite3_close (plugin->dbh); + if (result == SQLITE_BUSY) + { + LOG (GNUNET_ERROR_TYPE_WARNING, + _("Tried to close sqlite without finalizing all prepared statements.\n")); + stmt = sqlite3_next_stmt (plugin->dbh, NULL); + while (stmt != NULL) + { + GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, "sqlite", + "Closing statement %p\n", stmt); + result = sqlite3_finalize (stmt); + if (result != SQLITE_OK) + GNUNET_log_from (GNUNET_ERROR_TYPE_WARNING, "sqlite", + "Failed to close statement %p: %d\n", stmt, result); + stmt = sqlite3_next_stmt (plugin->dbh, NULL); + } + result = sqlite3_close (plugin->dbh); + } + if (SQLITE_OK != result) + LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_ERROR, "sqlite3_close"); + + GNUNET_free_non_null (plugin->fn); +} + + +/** + * Removes any existing record in the given zone with the same name. + * + * @param cls closure (internal context for the plugin) + * @param zone hash of the public key of the zone + * @param name name to remove (at most 255 characters long) + * @return GNUNET_OK on success + */ +static int +namestore_sqlite_remove_records (void *cls, + const GNUNET_HashCode *zone, + const char *name) +{ + struct Plugin *plugin = cls; + GNUNET_HashCode nh; + size_t name_len; + int n; + + name_len = strlen (name); + GNUNET_CRYPTO_hash (name, name_len, &nh); + + if ((SQLITE_OK != sqlite3_bind_blob (plugin->remove_records, 1, zone, sizeof (GNUNET_HashCode), SQLITE_STATIC)) || + (SQLITE_OK != sqlite3_bind_blob (plugin->remove_records, 2, &nh, sizeof (GNUNET_HashCode), SQLITE_STATIC))) + { + LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, + "sqlite3_bind_XXXX"); + if (SQLITE_OK != sqlite3_reset (plugin->remove_records)) + LOG_SQLITE (plugin, + GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, + "sqlite3_reset"); + return GNUNET_SYSERR; + } + n = sqlite3_step (plugin->remove_records); + if (SQLITE_OK != sqlite3_reset (plugin->remove_records)) + LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, + "sqlite3_reset"); + switch (n) + { + case SQLITE_DONE: + GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, "sqlite", "Record removed\n"); + return GNUNET_OK; + case SQLITE_BUSY: + LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_WARNING | GNUNET_ERROR_TYPE_BULK, + "sqlite3_step"); + return GNUNET_NO; + default: + LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, + "sqlite3_step"); + return GNUNET_SYSERR; + } +} + + +/** + * Store a record in the datastore. Removes any existing record in the + * same zone with the same name. + * + * @param cls closure (internal context for the plugin) + * @param zone_key public key of the zone + * @param expire when does the corresponding block in the DHT expire (until + * when should we never do a DHT lookup for the same name again)? + * @param name name that is being mapped (at most 255 characters long) + * @param rd_count number of entries in 'rd' array + * @param rd array of records with data to store + * @param signature signature of the record block, NULL if signature is unavailable (i.e. + * because the user queried for a particular record type only) + * @return GNUNET_OK on success, else GNUNET_SYSERR + */ +static int +namestore_sqlite_put_records (void *cls, + const struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *zone_key, + struct GNUNET_TIME_Absolute expire, + const char *name, + unsigned int rd_count, + const struct GNUNET_NAMESTORE_RecordData *rd, + const struct GNUNET_CRYPTO_RsaSignature *signature) +{ + struct Plugin *plugin = cls; + int n; + GNUNET_HashCode zone; + GNUNET_HashCode nh; + size_t name_len; + uint64_t rvalue; + size_t data_size; + size_t off; + unsigned int i; + + GNUNET_CRYPTO_hash (zone_key, sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded), &zone); + (void) namestore_sqlite_remove_records (plugin, &zone, name); + name_len = strlen (name); + GNUNET_CRYPTO_hash (name, name_len, &nh); + rvalue = GNUNET_CRYPTO_random_u64 (GNUNET_CRYPTO_QUALITY_WEAK, UINT64_MAX); + data_size = rd_count * sizeof (struct DbRecord); + for (i=0;i<rd_count;i++) + data_size += rd[i].data_size; + if (data_size > 64 * 65536) + { + GNUNET_break (0); + return GNUNET_SYSERR; + } + { + char data[data_size]; + struct DbRecord *rec; + + rec = (struct DbRecord *) data; + off = rd_count * sizeof (struct DbRecord); + for (i=0;i<rd_count;i++) + { + rec[i].expiration = GNUNET_TIME_absolute_hton (rd[i].expiration); + rec[i].data_size = htonl ((uint32_t) rd[i].data_size); + rec[i].record_type = htonl (rd[i].record_type); + rec[i].flags = htonl (rd[i].flags); + memcpy (&data[off], + rd[i].data, + rd[i].data_size); + off += rd[i].data_size; + } + if ((SQLITE_OK != sqlite3_bind_blob (plugin->put_records, 1, zone_key, sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded), SQLITE_STATIC)) || + (SQLITE_OK != sqlite3_bind_text (plugin->put_records, 2, name, -1, SQLITE_STATIC)) || + (SQLITE_OK != sqlite3_bind_int (plugin->put_records, 3, rd_count)) || + (SQLITE_OK != sqlite3_bind_blob (plugin->put_records, 4, data, data_size, SQLITE_STATIC)) || + (SQLITE_OK != sqlite3_bind_int64 (plugin->put_records, 5, expire.abs_value)) || + (SQLITE_OK != sqlite3_bind_blob (plugin->put_records, 6, signature, sizeof (struct GNUNET_CRYPTO_RsaSignature), SQLITE_STATIC)) || + (SQLITE_OK != sqlite3_bind_blob (plugin->put_records, 7, &zone, sizeof (GNUNET_HashCode), SQLITE_STATIC)) || + (SQLITE_OK != sqlite3_bind_blob (plugin->put_records, 8, &nh, sizeof (GNUNET_HashCode), SQLITE_STATIC)) || + (SQLITE_OK != sqlite3_bind_int64 (plugin->put_records, 9, rvalue)) ) + { + LOG_SQLITE (plugin, + GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, + "sqlite3_bind_XXXX"); + if (SQLITE_OK != sqlite3_reset (plugin->put_records)) + LOG_SQLITE (plugin, + GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, + "sqlite3_reset"); + return GNUNET_SYSERR; + + } + n = sqlite3_step (plugin->put_records); + if (SQLITE_OK != sqlite3_reset (plugin->put_records)) + LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, + "sqlite3_reset"); + } + switch (n) + { + case SQLITE_DONE: + GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, "sqlite", "Record stored\n"); + return GNUNET_OK; + case SQLITE_BUSY: + LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_WARNING | GNUNET_ERROR_TYPE_BULK, + "sqlite3_step"); + return GNUNET_NO; + default: + LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, + "sqlite3_step"); + return GNUNET_SYSERR; + } +} + + +/** + * Iterate over the results for a particular key and zone in the + * datastore. Will return at most one result to the iterator. + * + * @param cls closure (internal context for the plugin) + * @param zone hash of public key of the zone, NULL to iterate over all zones + * @param name_hash hash of name, NULL to iterate over all records of the zone + * @param offset offset in the list of all matching records + * @param iter function to call with the result + * @param iter_cls closure for iter + * @return GNUNET_OK on success, GNUNET_NO if there were no results, GNUNET_SYSERR on error + */ +static int +namestore_sqlite_iterate_records (void *cls, + const GNUNET_HashCode *zone, + const GNUNET_HashCode *name_hash, + uint64_t offset, + GNUNET_NAMESTORE_RecordIterator iter, void *iter_cls) +{ + struct Plugin *plugin = cls; + sqlite3_stmt *stmt; + unsigned int boff; + int ret; + int sret; + + if (NULL == zone) + if (NULL == name_hash) + stmt = plugin->iterate_all; + else + stmt = plugin->iterate_by_name; + else + if (NULL == name_hash) + stmt = plugin->iterate_by_zone; + else + stmt = plugin->iterate_records; + + boff = 0; + if ( (NULL != zone) && + (SQLITE_OK != sqlite3_bind_blob (stmt, ++boff, + zone, sizeof (GNUNET_HashCode), + SQLITE_STATIC)) ) + { + LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, + "sqlite3_bind_XXXX"); + if (SQLITE_OK != sqlite3_reset (stmt)) + LOG_SQLITE (plugin, + GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, + "sqlite3_reset"); + return GNUNET_SYSERR; + } + if ( (NULL != name_hash) && + (SQLITE_OK != sqlite3_bind_blob (stmt, ++boff, + name_hash, sizeof (GNUNET_HashCode), + SQLITE_STATIC)) ) + { + LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, + "sqlite3_bind_XXXX"); + if (SQLITE_OK != sqlite3_reset (stmt)) + LOG_SQLITE (plugin, + GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, + "sqlite3_reset"); + return GNUNET_SYSERR; + } + + if (SQLITE_OK != sqlite3_bind_int64 (stmt, ++boff, + offset)) + { + LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, + "sqlite3_bind_XXXX"); + if (SQLITE_OK != sqlite3_reset (stmt)) + LOG_SQLITE (plugin, + GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, + "sqlite3_reset"); + return GNUNET_SYSERR; + } + ret = GNUNET_NO; + if (SQLITE_ROW == (sret = sqlite3_step (stmt))) + { + unsigned int record_count; + size_t data_size; + const struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *zone_key; + const struct GNUNET_CRYPTO_RsaSignature *sig; + struct GNUNET_TIME_Absolute expiration; + const char *data; + const char *name; + + ret = GNUNET_YES; + zone_key = sqlite3_column_blob (stmt, 0); + name = (const char*) sqlite3_column_text (stmt, 1); + record_count = sqlite3_column_int (stmt, 2); + data_size = sqlite3_column_bytes (stmt, 3); + data = sqlite3_column_blob (stmt, 3); + expiration.abs_value = (uint64_t) sqlite3_column_int64 (stmt, 4); + sig = sqlite3_column_blob (stmt, 5); + + if ( (sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded) != sqlite3_column_bytes (stmt, 0)) || + (sizeof (struct GNUNET_CRYPTO_RsaSignature) != sqlite3_column_bytes (stmt, 5)) || + (sizeof (struct DbRecord) * record_count > data_size) ) + { + GNUNET_break (0); + ret = GNUNET_SYSERR; + } + else + { + const struct DbRecord *db = (const struct DbRecord*) data; + struct GNUNET_NAMESTORE_RecordData rd[record_count]; + unsigned int i; + size_t off; + + off = record_count * sizeof (struct DbRecord); + for (i=0;i<record_count;i++) + { + if (off + ntohl (db[i].data_size) > data_size) + { + GNUNET_break (0); + ret = GNUNET_SYSERR; + record_count = i; + break; + } + rd[i].expiration = GNUNET_TIME_absolute_ntoh (db[i].expiration); + rd[i].data_size = ntohl (db[i].data_size); + rd[i].data = &data[off]; + rd[i].record_type = ntohl (db[i].record_type); + rd[i].flags = ntohl (db[i].flags); + off += rd[i].data_size; + } + iter (iter_cls, zone_key, expiration, name, + record_count, rd, sig); + } + } + else + { + if (SQLITE_DONE != sret) + LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_ERROR, "sqlite_step"); + iter (iter_cls, NULL, GNUNET_TIME_UNIT_ZERO_ABS, NULL, 0, NULL, NULL); + } + if (SQLITE_OK != sqlite3_reset (stmt)) + LOG_SQLITE (plugin, + GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, + "sqlite3_reset"); + return ret; +} + + +/** + * Delete an entire zone (all records). Not used in normal operation. + * + * @param cls closure (internal context for the plugin) + * @param zone zone to delete + */ +static void +namestore_sqlite_delete_zone (void *cls, + const GNUNET_HashCode *zone) +{ + struct Plugin *plugin = cls; + sqlite3_stmt *stmt = plugin->delete_zone; + int n; + + if (SQLITE_OK != sqlite3_bind_blob (stmt, 1, zone, sizeof (GNUNET_HashCode), SQLITE_STATIC)) + { + LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, + "sqlite3_bind_XXXX"); + if (SQLITE_OK != sqlite3_reset (stmt)) + LOG_SQLITE (plugin, + GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, + "sqlite3_reset"); + return; + } + n = sqlite3_step (stmt); + if (SQLITE_OK != sqlite3_reset (stmt)) + LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, + "sqlite3_reset"); + switch (n) + { + case SQLITE_DONE: + GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, "sqlite", "Values deleted\n"); + break; + case SQLITE_BUSY: + LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_WARNING | GNUNET_ERROR_TYPE_BULK, + "sqlite3_step"); + break; + default: + LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, + "sqlite3_step"); + break; + } +} + + +/** + * Entry point for the plugin. + * + * @param cls the "struct GNUNET_NAMESTORE_PluginEnvironment*" + * @return NULL on error, othrewise the plugin context + */ +void * +libgnunet_plugin_namestore_sqlite_init (void *cls) +{ + static struct Plugin plugin; + const struct GNUNET_CONFIGURATION_Handle *cfg = cls; + struct GNUNET_NAMESTORE_PluginFunctions *api; + + if (NULL != plugin.cfg) + return NULL; /* can only initialize once! */ + memset (&plugin, 0, sizeof (struct Plugin)); + plugin.cfg = cfg; + if (GNUNET_OK != database_setup (&plugin)) + { + database_shutdown (&plugin); + return NULL; + } + api = GNUNET_malloc (sizeof (struct GNUNET_NAMESTORE_PluginFunctions)); + api->cls = &plugin; + api->put_records = &namestore_sqlite_put_records; + api->remove_records = &namestore_sqlite_remove_records; + api->iterate_records = &namestore_sqlite_iterate_records; + api->delete_zone = &namestore_sqlite_delete_zone; + LOG (GNUNET_ERROR_TYPE_INFO, + _("Sqlite database running\n")); + return api; +} + + +/** + * Exit point from the plugin. + * + * @param cls the plugin context (as returned by "init") + * @return always NULL + */ +void * +libgnunet_plugin_namestore_sqlite_done (void *cls) +{ + struct GNUNET_NAMESTORE_PluginFunctions *api = cls; + struct Plugin *plugin = api->cls; + + LOG (GNUNET_ERROR_TYPE_DEBUG, + "sqlite plugin is done\n"); + database_shutdown (plugin); + plugin->cfg = NULL; + GNUNET_free (api); + LOG (GNUNET_ERROR_TYPE_DEBUG, + "sqlite plugin is finished\n"); + return NULL; +} + +/* end of plugin_namestore_sqlite.c */ diff --git a/src/namestore/test_namestore_api.c b/src/namestore/test_namestore_api.c new file mode 100644 index 0000000..ebd8be3 --- /dev/null +++ b/src/namestore/test_namestore_api.c @@ -0,0 +1,213 @@ +/* + 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 namestore/test_namestore_api.c + * @brief testcase for namestore_api.c + */ +#include "platform.h" +#include "gnunet_common.h" +#include "gnunet_namestore_service.h" + +#define VERBOSE GNUNET_NO + +#define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 10) + +static struct GNUNET_NAMESTORE_Handle * nsh; + +static GNUNET_SCHEDULER_TaskIdentifier endbadly_task; +static struct GNUNET_OS_Process *arm; + +static struct GNUNET_CRYPTO_RsaPrivateKey * privkey; +static struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded pubkey; +static GNUNET_HashCode zone; + +static int res; + +#define TEST_RECORD_TYPE 1234 +#define TEST_RECORD_DATALEN 123 +#define TEST_RECORD_DATA 'a' + + +static void +start_arm (const char *cfgname) +{ + arm = GNUNET_OS_start_process (GNUNET_YES, NULL, NULL, "gnunet-service-arm", + "gnunet-service-arm", "-c", cfgname, +#if VERBOSE_PEERS + "-L", "DEBUG", +#else + "-L", "ERROR", +#endif + NULL); +} + +static void +stop_arm () +{ + if (NULL != arm) + { + if (0 != GNUNET_OS_process_kill (arm, SIGTERM)) + GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "kill"); + GNUNET_OS_process_wait (arm); + GNUNET_OS_process_close (arm); + arm = NULL; + } +} + +/** + * Re-establish the connection to the service. + * + * @param cls handle to use to re-connect. + * @param tc scheduler context + */ +static void +endbadly (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) +{ + if (nsh != NULL) + GNUNET_NAMESTORE_disconnect (nsh, GNUNET_YES); + nsh = NULL; + + if (privkey != NULL) + GNUNET_CRYPTO_rsa_key_free (privkey); + privkey = NULL; + + if (NULL != arm) + stop_arm(); + + res = 1; +} + + +static void +end (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) +{ + if (endbadly_task != GNUNET_SCHEDULER_NO_TASK) + { + GNUNET_SCHEDULER_cancel (endbadly_task); + endbadly_task = GNUNET_SCHEDULER_NO_TASK; + } + + if (privkey != NULL) + GNUNET_CRYPTO_rsa_key_free (privkey); + privkey = NULL; + + if (nsh != NULL) + GNUNET_NAMESTORE_disconnect (nsh, GNUNET_YES); + nsh = NULL; + + + if (NULL != arm) + stop_arm(); + + res = 0; +} + + +void name_lookup_proc (void *cls, + const struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *zone_key, + struct GNUNET_TIME_Absolute expire, + const char *name, + unsigned int rd_count, + const struct GNUNET_NAMESTORE_RecordData *rd, + const struct GNUNET_CRYPTO_RsaSignature *signature) +{ + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Namestore lookup result %p `%s' %i %p %p\n", zone_key, name, rd_count, rd, signature); + res = 0; + GNUNET_SCHEDULER_add_now(&end, NULL); +} + +void put_cont (void *cls, int32_t success, const char *emsg) +{ + char * name = cls; + + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Name store added record for `%s': %s\n", name, (success == GNUNET_OK) ? "SUCCESS" : "FAIL"); + + GNUNET_NAMESTORE_lookup_record (nsh, &zone, name, 0, &name_lookup_proc, NULL); +} + +static void +run (void *cls, char *const *args, const char *cfgfile, + const struct GNUNET_CONFIGURATION_Handle *cfg) +{ + endbadly_task = GNUNET_SCHEDULER_add_delayed(TIMEOUT,endbadly, NULL); + + privkey = GNUNET_CRYPTO_rsa_key_create_from_file("hostkey"); + GNUNET_assert (privkey != NULL); + GNUNET_CRYPTO_rsa_key_get_public(privkey, &pubkey); + + GNUNET_CRYPTO_hash_create_random (GNUNET_CRYPTO_QUALITY_WEAK, &zone); + + + struct GNUNET_CRYPTO_RsaSignature signature; + struct GNUNET_NAMESTORE_RecordData rd; + + rd.expiration = GNUNET_TIME_absolute_get(); + rd.record_type = TEST_RECORD_TYPE; + rd.data_size = TEST_RECORD_DATALEN; + rd.data = GNUNET_malloc(TEST_RECORD_DATALEN); + memset ((char *) rd.data, 'a', TEST_RECORD_DATALEN); + char * name = "dummy.dummy.gnunet"; + + start_arm (cfgfile); + GNUNET_assert (arm != NULL); + + nsh = GNUNET_NAMESTORE_connect (cfg); + GNUNET_break (NULL != nsh); + + GNUNET_NAMESTORE_record_put (nsh, &pubkey, name, + GNUNET_TIME_absolute_get_forever(), + 1, &rd, &signature, put_cont, name); + + GNUNET_free ((void *)rd.data); + +} + +static int +check () +{ + static char *const argv[] = { "test-namestore-api", + "-c", + "test_namestore_api.conf", +#if VERBOSE + "-L", "DEBUG", +#endif + NULL + }; + static struct GNUNET_GETOPT_CommandLineOption options[] = { + GNUNET_GETOPT_OPTION_END + }; + + res = 1; + GNUNET_PROGRAM_run ((sizeof (argv) / sizeof (char *)) - 1, argv, "test-namestore-api", + "nohelp", options, &run, &res); + return res; +} + +int +main (int argc, char *argv[]) +{ + int ret; + + ret = check (); + + return ret; +} + +/* end of test_namestore_api.c */ diff --git a/src/namestore/test_namestore_api.conf b/src/namestore/test_namestore_api.conf new file mode 100644 index 0000000..1b83e8f --- /dev/null +++ b/src/namestore/test_namestore_api.conf @@ -0,0 +1,34 @@ +[arm] +PORT = 12000 +DEFAULTSERVICES = namestore +UNIXPATH = /tmp/gnunet-p1-service-arm.sock + +[namestore] +#PREFIX = valgrind --leak-check=full +AUTOSTART = YES +UNIXPATH = /tmp/gnunet-service-namestore.sock +UNIX_MATCH_UID = YES +UNIX_MATCH_GID = YES +# PORT = 2099 +HOSTNAME = localhost +HOME = $SERVICEHOME +CONFIG = $DEFAULTCONFIG +BINARY = gnunet-service-namestore +ACCEPT_FROM = 127.0.0.1; +ACCEPT_FROM6 = ::1; +DATABASE = sqlite + +[namestore-sqlite] +FILENAME = $SERVICEHOME/namestore/sqlite.db + +[namestore-postgres] +CONFIG = connect_timeout=10; dbname=gnunet + +[namestore-mysql] +DATABASE = gnunet +CONFIG = ~/.my.cnf +# USER = gnunet +# PASSWORD = +# HOST = localhost +# PORT = 3306 + diff --git a/src/namestore/test_namestore_api_zone_iteration.c b/src/namestore/test_namestore_api_zone_iteration.c new file mode 100644 index 0000000..c0ef8c8 --- /dev/null +++ b/src/namestore/test_namestore_api_zone_iteration.c @@ -0,0 +1,219 @@ +/* + 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 namestore/test_namestore_api_zone_iteration.c + * @brief testcase for namestore_api.c zone iteration functionality + */ +#include "platform.h" +#include "gnunet_common.h" +#include "gnunet_namestore_service.h" + +#define VERBOSE GNUNET_NO + +#define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 10) + +static struct GNUNET_NAMESTORE_Handle * nsh; + +static GNUNET_SCHEDULER_TaskIdentifier endbadly_task; +static GNUNET_SCHEDULER_TaskIdentifier stopiteration_task; +static struct GNUNET_OS_Process *arm; + +static struct GNUNET_CRYPTO_RsaPrivateKey * privkey; +static struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded pubkey; +static GNUNET_HashCode zone; + +static struct GNUNET_NAMESTORE_ZoneIterator *zi; +static int res; + +static void +start_arm (const char *cfgname) +{ + arm = GNUNET_OS_start_process (GNUNET_YES, NULL, NULL, "gnunet-service-arm", + "gnunet-service-arm", "-c", cfgname, +#if VERBOSE_PEERS + "-L", "DEBUG", +#else + "-L", "ERROR", +#endif + NULL); +} + +static void +stop_arm () +{ + if (NULL != arm) + { + if (0 != GNUNET_OS_process_kill (arm, SIGTERM)) + GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "kill"); + GNUNET_OS_process_wait (arm); + GNUNET_OS_process_close (arm); + arm = NULL; + } +} + +/** + * Re-establish the connection to the service. + * + * @param cls handle to use to re-connect. + * @param tc scheduler context + */ +static void +endbadly (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) +{ + if (stopiteration_task != GNUNET_SCHEDULER_NO_TASK) + { + GNUNET_SCHEDULER_cancel (stopiteration_task); + stopiteration_task = GNUNET_SCHEDULER_NO_TASK; + } + + if (nsh != NULL) + GNUNET_NAMESTORE_disconnect (nsh, GNUNET_YES); + nsh = NULL; + + if (privkey != NULL) + GNUNET_CRYPTO_rsa_key_free (privkey); + privkey = NULL; + + if (NULL != arm) + stop_arm(); + + res = 1; +} + + +static void +end (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) +{ + if (stopiteration_task != GNUNET_SCHEDULER_NO_TASK) + { + GNUNET_SCHEDULER_cancel (stopiteration_task); + stopiteration_task = GNUNET_SCHEDULER_NO_TASK; + } + + if (endbadly_task != GNUNET_SCHEDULER_NO_TASK) + { + GNUNET_SCHEDULER_cancel (endbadly_task); + endbadly_task = GNUNET_SCHEDULER_NO_TASK; + } + + + if (privkey != NULL) + GNUNET_CRYPTO_rsa_key_free (privkey); + privkey = NULL; + + if (nsh != NULL) + GNUNET_NAMESTORE_disconnect (nsh, GNUNET_YES); + nsh = NULL; + + + if (NULL != arm) + stop_arm(); + + res = 0; +} + +static void +stop_iteration (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) +{ + stopiteration_task = GNUNET_SCHEDULER_NO_TASK; + + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Stopping iteration for zone `%s'\n", GNUNET_h2s (&zone)); + GNUNET_NAMESTORE_zone_iteration_stop (zi); + + GNUNET_SCHEDULER_add_now (&end, NULL); +} + +void zone_proc (void *cls, + const struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *zone_key, + struct GNUNET_TIME_Absolute expire, + const char *name, + unsigned int rd_count, + const struct GNUNET_NAMESTORE_RecordData *rd, + const struct GNUNET_CRYPTO_RsaSignature *signature) +{ + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Callback for zone `%s'\n", GNUNET_h2s (&zone)); + + stopiteration_task = GNUNET_SCHEDULER_add_now (&stop_iteration, NULL); +} + +static void +run (void *cls, char *const *args, const char *cfgfile, + const struct GNUNET_CONFIGURATION_Handle *cfg) +{ + endbadly_task = GNUNET_SCHEDULER_add_delayed(TIMEOUT,&endbadly, NULL); + + privkey = GNUNET_CRYPTO_rsa_key_create_from_file("hostkey"); + GNUNET_assert (privkey != NULL); + GNUNET_CRYPTO_rsa_key_get_public(privkey, &pubkey); + + GNUNET_CRYPTO_hash_create_random (GNUNET_CRYPTO_QUALITY_WEAK, &zone); + + start_arm (cfgfile); + GNUNET_assert (arm != NULL); + + nsh = GNUNET_NAMESTORE_connect (cfg); + GNUNET_break (NULL != nsh); + + zi = GNUNET_NAMESTORE_zone_iteration_start(nsh, + &zone, + GNUNET_NAMESTORE_RF_NONE, + GNUNET_NAMESTORE_RF_NONE, + zone_proc, + &zone); + if (zi == NULL) + { + GNUNET_break (0); + GNUNET_SCHEDULER_cancel (endbadly_task); + endbadly_task = GNUNET_SCHEDULER_add_now (&endbadly, NULL); + } +} + +static int +check () +{ + static char *const argv[] = { "test_namestore_api_zone_iteration", + "-c", + "test_namestore_api.conf", +#if VERBOSE + "-L", "DEBUG", +#endif + NULL + }; + static struct GNUNET_GETOPT_CommandLineOption options[] = { + GNUNET_GETOPT_OPTION_END + }; + + res = 1; + GNUNET_PROGRAM_run ((sizeof (argv) / sizeof (char *)) - 1, argv, "test_namestore_api_zone_iteration", + "nohelp", options, &run, &res); + return res; +} + +int +main (int argc, char *argv[]) +{ + int ret; + + ret = check (); + + return ret; +} + +/* end of test_namestore_api_zone_iteration.c */ diff --git a/src/namestore/test_namestore_record_serialization.c b/src/namestore/test_namestore_record_serialization.c new file mode 100644 index 0000000..5ea345b --- /dev/null +++ b/src/namestore/test_namestore_record_serialization.c @@ -0,0 +1,157 @@ +/* + 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 namestore/test_namestore_record_serialization.c + * @brief testcase for test_namestore_record_serialization.c + */ +#include "platform.h" +#include "gnunet_common.h" +#include "gnunet_namestore_service.h" +#include "namestore.h" + +#define VERBOSE GNUNET_NO + +#define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 10) + +static int res; + +static void +run (void *cls, char *const *args, const char *cfgfile, + const struct GNUNET_CONFIGURATION_Handle *cfg) +{ + char * dest = NULL; + size_t len; + int c; + int elem = 0; + + int rd_count = 3; + size_t data_len; + struct GNUNET_NAMESTORE_RecordData src[rd_count]; + struct GNUNET_NAMESTORE_RecordData *dst = NULL; + + memset(src, '\0', rd_count * sizeof (struct GNUNET_NAMESTORE_RecordData)); + + data_len = 0; + for (c = 0; c < rd_count; c++) + { + src[c].record_type = c+1; + src[c].data_size = data_len; + src[c].data = GNUNET_malloc (data_len); + + /* Setting data to data_len * record_type */ + memset ((char *) src[c].data, 'a', data_len); + data_len += 10; + } + res = 0; + + len = GNUNET_NAMESTORE_records_serialize (&dest, rd_count, src); + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Serialized data len: %u\n",len); + + GNUNET_assert (dest != NULL); + + elem = GNUNET_NAMESTORE_records_deserialize(&dst, dest, len); + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Deserialized elements: %u\n",elem); + + GNUNET_assert (elem == rd_count); + GNUNET_assert (dst != NULL); + + for (c = 0; c < elem; c++) + { + if (src[c].data_size != dst[c].data_size) + { + GNUNET_break (0); + res = 1; + } + if (GNUNET_TIME_absolute_get_difference(src[c].expiration, dst[c].expiration).rel_value != GNUNET_TIME_relative_get_zero().rel_value) + { + GNUNET_break (0); + res = 1; + } + if (src[c].flags != dst[c].flags) + { + GNUNET_break (0); + res = 1; + } + if (src[c].record_type != dst[c].record_type) + { + GNUNET_break (0); + res = 1; + } + + size_t data_size = src[c].data_size; + char data[data_size]; + memset (data, 'a', data_size); + if (0 != memcmp (data, dst[c].data, data_size)) + { + GNUNET_break (0); + res = 1; + } + if (0 != memcmp (data, src[c].data, data_size)) + { + GNUNET_break (0); + res = 1; + } + if (0 != memcmp (src[c].data, dst[c].data, src[c].data_size)) + { + GNUNET_break (0); + res = 1; + } + + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Element [%i]: EQUAL\n", c); + /* clean up */ + GNUNET_free((char *) dst[c].data); + GNUNET_free((char *) src[c].data); + } + GNUNET_free (dest); + GNUNET_free (dst); +} + +static int +check () +{ + static char *const argv[] = { "test_namestore_record_serialization", + "-c", + "test_namestore_api.conf", +#if VERBOSE + "-L", "DEBUG", +#endif + NULL + }; + static struct GNUNET_GETOPT_CommandLineOption options[] = { + GNUNET_GETOPT_OPTION_END + }; + + res = 1; + GNUNET_PROGRAM_run ((sizeof (argv) / sizeof (char *)) - 1, argv, "test_namestore_record_serialization", + "nohelp", options, &run, &res); + return res; +} + +int +main (int argc, char *argv[]) +{ + int ret; + + ret = check (); + + return ret; +} + +/* end of test_namestore_record_serialization.c */ diff --git a/src/namestore/test_plugin_namestore.c b/src/namestore/test_plugin_namestore.c new file mode 100644 index 0000000..0b0008f --- /dev/null +++ b/src/namestore/test_plugin_namestore.c @@ -0,0 +1,248 @@ +/* + This file is part of GNUnet. + (C) 2012 Christian Grothoff (and other contributing authors) + + GNUnet is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 3, or (at your + option) any later version. + + GNUnet is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with GNUnet; see the file COPYING. If not, write to the + Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ +/* + * @file namestore/test_plugin_namestore.c + * @brief Test for the namestore plugins + * @author Christian Grothoff + */ +#include "platform.h" +#include "gnunet_util_lib.h" +#include "gnunet_namestore_plugin.h" + +#define VERBOSE GNUNET_NO + +#define ASSERT(x) do { if (! (x)) { printf("Error at %s:%d\n", __FILE__, __LINE__); goto FAILURE;} } while (0) + +static int ok; + +/** + * Name of plugin under test. + */ +static const char *plugin_name; + + +/** + * Function called when the service shuts down. Unloads our namestore + * plugin. + * + * @param api api to unload + */ +static void +unload_plugin (struct GNUNET_NAMESTORE_PluginFunctions *api) +{ + char *libname; + + GNUNET_asprintf (&libname, "libgnunet_plugin_namestore_%s", plugin_name); + GNUNET_break (NULL == GNUNET_PLUGIN_unload (libname, api)); + GNUNET_free (libname); +} + + +/** + * Load the namestore plugin. + * + * @param cfg configuration to pass + * @return NULL on error + */ +static struct GNUNET_NAMESTORE_PluginFunctions * +load_plugin (const struct GNUNET_CONFIGURATION_Handle *cfg) +{ + struct GNUNET_NAMESTORE_PluginFunctions *ret; + char *libname; + + GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("Loading `%s' namestore plugin\n"), + plugin_name); + GNUNET_asprintf (&libname, "libgnunet_plugin_namestore_%s", plugin_name); + if (NULL == (ret = GNUNET_PLUGIN_load (libname, (void*) cfg))) + { + FPRINTF (stderr, "Failed to load plugin `%s'!\n", plugin_name); + return NULL; + } + GNUNET_free (libname); + return ret; +} + + +/** + * Function called by for each matching record. + * + * @param cls closure + * @param zone_key public key of the zone + * @param expire when does the corresponding block in the DHT expire (until + * when should we never do a DHT lookup for the same name again)? + * @param name name that is being mapped (at most 255 characters long) + * @param rd_count number of entries in 'rd' array + * @param rd array of records with data to store + * @param signature signature of the record block, NULL if signature is unavailable (i.e. + * because the user queried for a particular record type only) + */ +static void +test_record (void *cls, + const struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *zone_key, + struct GNUNET_TIME_Absolute expire, + const char *name, + unsigned int rd_count, + const struct GNUNET_NAMESTORE_RecordData *rd, + const struct GNUNET_CRYPTO_RsaSignature *signature) +{ + int *idp = cls; + int id = *idp; + struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded tzone_key; + char tname[64]; + unsigned int trd_count = 1 + (id % 1024); + struct GNUNET_CRYPTO_RsaSignature tsignature; + unsigned int i; + + GNUNET_snprintf (tname, sizeof (tname), + "a%u", (unsigned int ) id); + for (i=0;i<trd_count;i++) + { + GNUNET_assert (rd[i].data_size == id % 10); + GNUNET_assert (0 == memcmp ("Hello World", rd[i].data, id % 10)); + GNUNET_assert (rd[i].record_type == 1 + (id % 13)); + GNUNET_assert (rd[i].flags == (id % 7)); + } + memset (&tzone_key, (id % 241), sizeof (tzone_key)); + memset (&tsignature, (id % 243), sizeof (tsignature)); + GNUNET_assert (0 == strcmp (name, tname)); + GNUNET_assert (0 == memcmp (&tzone_key, zone_key, sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded))); + GNUNET_assert (0 == memcmp (&tsignature, signature, sizeof (struct GNUNET_CRYPTO_RsaSignature))); +} + + +static void +get_record (struct GNUNET_NAMESTORE_PluginFunctions *nsp, int id) +{ + GNUNET_assert (1 == nsp->iterate_records (nsp->cls, + NULL, NULL, 0, + &test_record, &id)); +} + + +static void +put_record (struct GNUNET_NAMESTORE_PluginFunctions *nsp, int id) +{ + struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded zone_key; + struct GNUNET_TIME_Absolute expire; + char name[64]; + unsigned int rd_count = 1 + (id % 1024); + struct GNUNET_NAMESTORE_RecordData rd[rd_count]; + struct GNUNET_CRYPTO_RsaSignature signature; + unsigned int i; + + GNUNET_snprintf (name, sizeof (name), + "a%u", (unsigned int ) id); + expire = GNUNET_TIME_relative_to_absolute (GNUNET_TIME_UNIT_MINUTES); + for (i=0;i<rd_count;i++) + { + rd[i].data = "Hello World"; + rd[i].data_size = id % 10; + rd[i].expiration = GNUNET_TIME_relative_to_absolute (GNUNET_TIME_UNIT_MINUTES); + rd[i].record_type = 1 + (id % 13); + rd[i].flags = (id % 7); + } + memset (&zone_key, (id % 241), sizeof (zone_key)); + memset (&signature, (id % 243), sizeof (signature)); + GNUNET_assert (GNUNET_OK == nsp->put_records (nsp->cls, + &zone_key, + expire, + name, + rd_count, + rd, + &signature)); +} + + +static void +run (void *cls, char *const *args, const char *cfgfile, + const struct GNUNET_CONFIGURATION_Handle *cfg) +{ + struct GNUNET_NAMESTORE_PluginFunctions *nsp; + struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded zone_key; + GNUNET_HashCode zone; + + ok = 0; + nsp = load_plugin (cfg); + if (NULL == nsp) + { + FPRINTF (stderr, + "%s", + "Failed to initialize namestore. Database likely not setup, skipping test.\n"); + return; + } + put_record (nsp, 1); + get_record (nsp, 1); + + memset (&zone_key, 1, sizeof (zone_key)); + GNUNET_CRYPTO_hash (&zone_key, sizeof (zone_key), &zone); + nsp->delete_zone (nsp->cls, &zone); + unload_plugin (nsp); +} + + +int +main (int argc, char *argv[]) +{ + char *pos; + char cfg_name[128]; + + char *const xargv[] = { + "test-plugin-namestore", + "-c", + cfg_name, +#if VERBOSE + "-L", "DEBUG", +#endif + NULL + }; + struct GNUNET_GETOPT_CommandLineOption options[] = { + GNUNET_GETOPT_OPTION_END + }; + + GNUNET_DISK_directory_remove ("/tmp/gnunet-test-plugin-namestore-sqlite"); + GNUNET_log_setup ("test-plugin-namestore", +#if VERBOSE + "DEBUG", +#else + "WARNING", +#endif + NULL); + /* determine name of plugin to use */ + plugin_name = argv[0]; + while (NULL != (pos = strstr (plugin_name, "_"))) + plugin_name = pos + 1; + if (NULL != (pos = strstr (plugin_name, "."))) + pos[0] = 0; + else + pos = (char *) plugin_name; + + GNUNET_snprintf (cfg_name, sizeof (cfg_name), "test_plugin_namestore_%s.conf", + plugin_name); + if (pos != plugin_name) + pos[0] = '.'; + GNUNET_PROGRAM_run ((sizeof (xargv) / sizeof (char *)) - 1, xargv, + "test-plugin-namestore", "nohelp", options, &run, NULL); + if (ok != 0) + FPRINTF (stderr, "Missed some testcases: %d\n", ok); + GNUNET_DISK_directory_remove ("/tmp/gnunet-test-plugin-namestore-sqlite"); + return ok; +} + +/* end of test_plugin_namestore.c */ diff --git a/src/namestore/test_plugin_namestore_sqlite.conf b/src/namestore/test_plugin_namestore_sqlite.conf new file mode 100644 index 0000000..57b170f --- /dev/null +++ b/src/namestore/test_plugin_namestore_sqlite.conf @@ -0,0 +1,2 @@ +[namestore-sqlite] +FILENAME = /tmp/gnunet-test-plugin-namestore-sqlite/sqlite.db |