aboutsummaryrefslogtreecommitdiff
path: root/src/namestore
diff options
context:
space:
mode:
authorBertrand Marc <beberking@gmail.com>2012-05-02 21:43:37 +0200
committerBertrand Marc <beberking@gmail.com>2012-05-02 21:43:37 +0200
commit2b81464a43485fcc8ce079fafdee7b7a171835f4 (patch)
tree394774c0f735199b57d51a2d3840356317853fe1 /src/namestore
Imported Upstream version 0.9.2upstream/0.9.2
Diffstat (limited to 'src/namestore')
-rw-r--r--src/namestore/Makefile.am105
-rw-r--r--src/namestore/Makefile.in918
-rw-r--r--src/namestore/gnunet-service-namestore.c845
-rw-r--r--src/namestore/hostkeybin0 -> 913 bytes
-rw-r--r--src/namestore/namestore.conf.in30
-rw-r--r--src/namestore/namestore.h424
-rw-r--r--src/namestore/namestore_api.c1194
-rw-r--r--src/namestore/namestore_common.c159
-rw-r--r--src/namestore/plugin_namestore_sqlite.c806
-rw-r--r--src/namestore/test_namestore_api.c213
-rw-r--r--src/namestore/test_namestore_api.conf34
-rw-r--r--src/namestore/test_namestore_api_zone_iteration.c219
-rw-r--r--src/namestore/test_namestore_record_serialization.c157
-rw-r--r--src/namestore/test_plugin_namestore.c248
-rw-r--r--src/namestore/test_plugin_namestore_sqlite.conf2
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
new file mode 100644
index 0000000..eac1d1e
--- /dev/null
+++ b/src/namestore/hostkey
Binary files differ
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