diff --git a/ChangeLog b/ChangeLog
index 4ed6576e7e8a5967e1a514b115395e9c2da78644..7b4dbad3784d1b7bec56fc64a87c4f8705f549ed 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,111 @@
+Sun, 6 Sep 2020 13:33:31 +0200 (fa067384b)
+GNUnet 0.13.3 - Martin Schanzenbach
+
+Fri, 4 Sep 2020 20:12:00 +0200 (35d7c1f88)
+fix: depend on libsodium >=1.0.17. Fixes #6506 - Martin Schanzenbach
+
+Fri, 4 Sep 2020 04:07:46 +0200 (538277ed8)
+reclaim: fix cli parameter name for credential ID - Martin Schanzenbach
+
+Wed, 2 Sep 2020 19:26:37 +0200 (3ec73fc68)
+gnunet-qr/uri: Fix exit code handling; fix memory corruption - Martin Schanzenbach
+
+Fri, 28 Aug 2020 12:26:52 +0200 (bbf9540c9)
+fix order of namespaces in plugin_rest_identity GNUNET_REST_namespace_match() always matched to the first namespace for GET - jospaeth
+
+Wed, 26 Aug 2020 14:49:02 -0400 (49d74db2e)
+use (and "GNUnet-ify") libyuarel as a basepoint for uri parsing - Jonathan Buchanan
+
+Sun, 23 Aug 2020 16:52:26 +0200 (ef86866ce)
+add function GNUNET_CURL_extend_headers() - Christian Grothoff
+
+Wed, 19 Aug 2020 23:53:02 +0200 (a57d476ab)
+reclaim: Attestations now called credentials. Credentials are presented to third parties as presentations. - Martin Schanzenbach
+
+Wed, 19 Aug 2020 13:17:01 +0200 (6531e0387)
+break out chapters on SETI and SETUI from SET chapter - Christian Grothoff
+
+Wed, 19 Aug 2020 11:05:13 +0200 (6dabecce0)
+change scalarproduct to use seti service in lieu of deprecated set service - Christian Grothoff
+
+Wed, 19 Aug 2020 10:59:27 +0200 (2d010ea15)
+change revocation logic to use setu service in lieu of deprecated set service - Christian Grothoff
+
+Tue, 18 Aug 2020 13:35:24 +0200 (2cd052cb8)
+Update reclaimID handbook entry - Martin Schanzenbach
+
+Tue, 18 Aug 2020 00:09:59 +0200 (2bce42e5b)
+fix: build on openbsd - Martin Schanzenbach
+
+Mon, 17 Aug 2020 14:45:46 +0200 (6f2ee9eb3)
+clean up GNUNET_CRYPTO_pow_hash API - Christian Grothoff
+
+Sun, 16 Aug 2020 20:46:39 +0200 (be0475f2a)
+split of set union from set service (preliminary) - Christian Grothoff
+
+Wed, 12 Aug 2020 09:36:33 +0200 (99f820453)
+fix: GNUNET_is_zero(ptr) should return enum GNUNET_GenericReturnValue. Fixes #6475. - Martin Schanzenbach
+
+Tue, 11 Aug 2020 11:35:06 +0200 (286759692)
+fix: mysql version detection - Martin Schanzenbach
+
+Thu, 6 Aug 2020 08:45:40 +0200 (1d4f5263a)
+reclaim: Refactoring and more standards compliance with respect to scopes - Martin Schanzenbach
+
+Wed, 5 Aug 2020 11:35:05 +0200 (6e764f4ab)
+reclaim: Make SPAs work with public clients. No longer encrypt code. - Martin Schanzenbach
+
+Tue, 4 Aug 2020 21:08:22 +0200 (ade9b5e52)
+reclaim: fix #6463 - Martin Schanzenbach
+
+Tue, 4 Aug 2020 19:40:23 +0200 (815ded19f)
+rest: fix #6462 - Martin Schanzenbach
+
+Tue, 4 Aug 2020 10:09:45 +0200 (080519e98)
+reclaim: do not store access token instead piggyback ticket - Martin Schanzenbach
+
+Mon, 3 Aug 2020 19:37:23 +0200 (8c86c4472)
+reclaim: support client credentials in POST body for token request - Martin Schanzenbach
+
+Sat, 1 Aug 2020 16:22:38 +0200 (e44686f08)
+fix: reclaim urlenc / revert accidental change - Martin Schanzenbach
+
+Sat, 1 Aug 2020 16:07:08 +0200 (754d8c1b4)
+util: add percent/url encoding - Martin Schanzenbach
+
+Thu, 30 Jul 2020 16:12:22 +0530 (8d312646c)
+fix SIGSEGV in GNUNET_buffer_write_data_encoded - Florian Dold
+
+Thu, 30 Jul 2020 15:15:59 +0530 (d335baac8)
+implement GNUNET_buffer_write_data_encoded - Florian Dold
+
+Wed, 22 Jul 2020 21:47:42 +0200 (8703a0516)
+ensure psql fails hard if there is an error in the SQL (fixes #6437) - Christian Grothoff
+
+Sat, 18 Jul 2020 00:44:39 +0200 (7f4ddbcab)
+merge flags into enum for GNUNET_DISK_pipe() API, fixing #6188 - Christian Grothoff
+
+Fri, 17 Jul 2020 22:35:36 +0200 (28ab2c446)
+avoid boolean flag in GNUNET_OS_start_process() API (fixes #6188) - Christian Grothoff
+
+Fri, 17 Jul 2020 14:26:45 +0200 (0c9911d73)
+TNG: Implemented 5530: add replay protection to TCP communicator. Added monotime value checks - t3sserakt
+
+Thu, 16 Jul 2020 20:36:12 +0200 (bbe0a0501)
+avoid boolean argument in GNUNET_CURL_job_add(), see #6188 - Christian Grothoff
+
+Thu, 16 Jul 2020 17:40:14 +0200 (ee1fbffa1)
+support context-wide client authentication - Christian Grothoff
+
+Thu, 16 Jul 2020 17:24:30 +0200 (23820348b)
+docs: fixed example for pinning a friends public key - rexxnor
+
+Wed, 15 Jul 2020 17:21:39 +0200 (9bb2c1e31)
+Load GNSRECORD plugins within GNUnet's context - Christian Grothoff
+
+Fri, 3 Jul 2020 22:37:42 +0200 (0f2ac01f3)
+Add function to return GNUnet's default configuration - Christian Grothoff
+
 Thu, 9 Jul 2020 09:09:50 +0200 (5a0df5e18)
 fix: raise ATS quotas to 10 MiB #6426 - Martin Schanzenbach
 
diff --git a/README b/README
index d95022de256f708f3317dc03cf44f40b8bb39b96..e6ba9c07e63ec3ee862cc41841a18902f917c2be 100644
--- a/README
+++ b/README
@@ -96,7 +96,7 @@ These are the direct dependencies for running GNUnet:
 - which                             (contrib/apparmor(?), gnunet-bugreport,
                                      and possibly more)
 - zlib
-- libsodium          >= 1.0.11      (for elliptic curve cryptography)
+- libsodium          >= 1.0.17      (for elliptic curve cryptography)
 
 These are the dependencies for GNUnet's testsuite:
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
diff --git a/bootstrap b/bootstrap
new file mode 100755
index 0000000000000000000000000000000000000000..8fc4c44261d780c3367a675d6c54fdc5620c6f3b
--- /dev/null
+++ b/bootstrap
@@ -0,0 +1,121 @@
+#!/bin/sh
+#
+# We should use /usr/bin/env sh, but some systems are notoriously picky.
+# In fact we could ommit this line if some automations wouldn't rely on
+# running this file via ./bootstrap.
+#
+# This file is in the public domain.
+# SPDX-License-Identifier: 0BSD
+#
+# We can't set -eu because we encounter warnings which
+# result in stops, whereas the warnings can for now be
+# safely ignored.
+# set -eu
+
+cleanup()
+{
+    echo "Removing folder 'libltdl'..."
+    rm -rf libltdl
+}
+
+errmsg=''
+
+# Check if shell supports builtin 'type'.
+if test -z "$errmsg"; then
+    if ! (eval 'type type') >/dev/null 2>&1
+    then
+        errmsg='Shell does not support type builtin'
+        exit 1
+    fi
+fi
+
+# This is more portable than `which' but comes with
+# the caveat of not(?) properly working on busybox's ash:
+existence()
+{
+    type "$1" >/dev/null 2>&1
+}
+
+check_uncrustify()
+{
+    if existence uncrustify; then
+        echo "Installing uncrustify hook and configuration"
+        ln -fs contrib/build-common/conf/uncrustify.cfg uncrustify.cfg 2> /dev/null
+        ln -fs contrib/build-common/conf/uncrustify_precommit .git/hooks/pre-commit 2> /dev/null
+    else
+        echo "Uncrustify not detected, hook not installed."
+        echo "Please install uncrustify if you plan on doing development"
+    fi
+}
+
+# yapf can be a suffixed binary, don't change the essential logic
+# of this if you change it.
+check_yapf()
+{
+    if existence yapf || \
+       existence yapf3.0 || \
+       existence yapf3.1 || \
+       existence yapf3.2 || \
+       existence yapf3.3 || \
+       existence yapf3.4 || \
+       existence yapf3.5 || \
+       existence yapf3.6 || \
+       existence yapf3.7 || \
+       existence yapf3.8 || \
+       existence yapf3.9 || \
+       existence yapf4.0; then
+        echo "Installing yapf symlink"
+        ln -fs contrib/build-common/conf/.style.yapf .style.yapf 2> /dev/null
+    else
+        echo "yapf not detected, please install yapf if you plan on contributing python code"
+    fi
+}
+
+check_libtool()
+{
+    echo "checking for libtoolize / libtool... "
+
+    if existence libtool || \
+       existence libtoolize || \
+       existence glibtoolize || \
+       existence slibtool; then
+        autoreconf -if || exit 1
+        . "bin/pogen.sh" || exit 1
+    else
+        echo "*** No libtoolize (libtool) or libtool found, please install it ***" >&2;
+        exit 1
+    fi
+}
+
+submodules()
+{
+    # Try to update the submodule. Since bootstrap
+    # is also invoked by distributors, we must
+    # ignore any failing of this function as we
+    # could have no outgoing network connection
+    # in a restricted environment.
+    if ! git --version >/dev/null; then
+        echo "git not installed, skipping submodule update"
+    else
+        git submodule update --init || exit 1
+        git submodule update --recursive || exit 1
+        git submodule sync || exit 1
+    fi
+}
+
+init_buildcommon_include()
+{
+    cp contrib/build-common/Makefile.inc contrib/Makefile.inc || exit 1
+}
+
+main()
+{
+    cleanup
+    submodules
+    init_buildcommon_include
+    check_uncrustify
+    check_yapf
+    check_libtool
+}
+
+main "$@"
diff --git a/configure.ac b/configure.ac
index 39e7ffa7ed252f430e5eb8ceab75cd17b86a8564..3cf7e6cb682db4b04d8a31398bc03d9a4cff7f44 100644
--- a/configure.ac
+++ b/configure.ac
@@ -21,7 +21,7 @@
 #
 AC_PREREQ(2.61)
 # Checks for programs.
-AC_INIT([gnunet], [0.13.1], [bug-gnunet@gnu.org])
+AC_INIT([gnunet], [0.13.3], [bug-gnunet@gnu.org])
 AC_CONFIG_AUX_DIR([build-aux])
 
 # check for legacy option that is no longer supported (#5627) and fail hard
@@ -142,9 +142,11 @@ AS_CASE(["$host_os"],
      UNIXONLY="#"
   ],
   [*openbsd*],[
-     LIBS=`echo $LIBS | sed -e "s/-ldl//"`
+     # We need to explicitly link libc
+     LDFLAGS="$LDFLAGS -Wl,-lc"
+     # We also need to enable PIC
+     CFLAGS="-fPIC $CFLAGS"
      build_target="openbsd"
-     use_openbsd_libtool=true
      LIBPREFIX=
      DLLDIR=lib
      UNIXONLY="#"
@@ -1034,9 +1036,10 @@ AC_CHECK_LIB([kvm],[kvm_open])
 AC_CHECK_LIB([kstat],[kstat_open])
 
 libsodium=0
-# test for libsodium
+# test for libsodium >=1.017 (introduction of
+# crypto_scalarmult_ed25519_base_noclamp API)
 AC_CHECK_HEADER([sodium.h],
-                [AC_CHECK_LIB([sodium], [crypto_pwhash_argon2id],
+                [AC_CHECK_LIB([sodium], [crypto_scalarmult_ed25519_base_noclamp],
                               [libsodium=1])])
 
 AS_IF([test x$libsodium = x0],
@@ -1404,12 +1407,11 @@ AS_IF([test "$mysql" = "true" -a "x$enable_mysql_version_check" = "xyes"],
   AC_MSG_CHECKING(mysql version)
   AC_COMPILE_IFELSE([AC_LANG_PROGRAM(
     [[
-      #include <mysql/mysql.h>]],
+      #include <mysql/mysql_version.h>]],
     [[
       #if (MYSQL_VERSION_ID < 40100)
       #error needs at least version >= 4.1
       #endif
-      int main () { return 0; }
     ]])
     ],
     [mysql=true],
@@ -1423,6 +1425,21 @@ AS_IF([test "$mysql" = "true" -a "x$enable_mysql_version_check" = "xyes"],
     mysqlfail=false
     AC_MSG_RESULT(ok)
    ])
+  AC_COMPILE_IFELSE([AC_LANG_PROGRAM(
+    [[
+      #include <mysql/mysql_version.h>]],
+    [[
+      #if (MYSQL_VERSION_ID < 80000)
+      #error needs at least version >= 4.1
+      #endif
+    ]])
+    ],
+    [mysql8=true],
+    [mysql8=false])
+  AS_IF([test x$mysql8 = xtrue],
+   [
+    AC_DEFINE([HAVE_MYSQL8],[1],[Have mysql8])
+   ],[])
 ])
 
 AM_CONDITIONAL(HAVE_MYSQL, test x$mysql = xtrue)
@@ -1923,6 +1940,10 @@ src/scalarproduct/Makefile
 src/scalarproduct/scalarproduct.conf
 src/set/Makefile
 src/set/set.conf
+src/seti/Makefile
+src/seti/seti.conf
+src/setu/Makefile
+src/setu/setu.conf
 src/sq/Makefile
 src/statistics/Makefile
 src/statistics/statistics.conf
diff --git a/contrib/.gitignore b/contrib/.gitignore
new file mode 100644
index 0000000000000000000000000000000000000000..01b6efa058ff77732b4a29d76be06a1fbe12a989
--- /dev/null
+++ b/contrib/.gitignore
@@ -0,0 +1,9 @@
+gnunet_janitor.py
+gnunet_pyexpect.py
+pydiffer.py
+terminate.py
+gnunet_pyexpect.py
+gnunet_pyexpect.pyc
+pydiffer.pyc
+test_gnunet_prefix
+timeout_watchdog
diff --git a/contrib/A-Z.ecc b/contrib/A-Z.ecc
new file mode 100644
index 0000000000000000000000000000000000000000..828cdc6a4b1432e5f9b353c11ac2e35bebec6d72
Binary files /dev/null and b/contrib/A-Z.ecc differ
diff --git a/contrib/apparmor/abstractions/gnunet-common b/contrib/apparmor/abstractions/gnunet-common
new file mode 100644
index 0000000000000000000000000000000000000000..3bf6806f59ab7fcfa50ecd01100d10c2fe20dc85
--- /dev/null
+++ b/contrib/apparmor/abstractions/gnunet-common
@@ -0,0 +1,12 @@
+# This files contains common permissions for gnunet
+
+  #GNUnet configuration file
+  @{GNUNET_PREFIX}/share/gnunet/config.d/       r,
+  @{GNUNET_PREFIX}/share/gnunet/config.d/*.conf r,
+  
+  /etc/gnunet.conf 		 	   r,
+  @{HOME}/.config/gnunet.conf 	   r,
+  owner @{GNUNET_USER}/.config/gnunet.conf r,
+
+  #GNUnet librairies
+  @{GNUNET_PREFIX}/lib/libgnunet*.so.* 	  mr,
diff --git a/contrib/apparmor/abstractions/gnunet-db b/contrib/apparmor/abstractions/gnunet-db
new file mode 100644
index 0000000000000000000000000000000000000000..73b869dca3e705a418435c41d8ec2f8c7c424c33
--- /dev/null
+++ b/contrib/apparmor/abstractions/gnunet-db
@@ -0,0 +1,8 @@
+# gnunet-db
+@{GNUNET_USER}/.local/share/gnunet/namestore/ ra,
+@{GNUNET_USER}/.local/share/gnunet/namestore/sqlite.db rwk,
+@{GNUNET_USER}/.local/share/gnunet/namestore/sqlite.db-journal rw,
+
+@{HOME}/.local/share/gnunet/namestore/ r,
+@{HOME}/.local/share/gnunet/namestore/sqlite.db rwk,
+@{HOME}/.local/share/gnunet/namestore/sqlite.db-journal rw,
diff --git a/contrib/apparmor/abstractions/gnunet-gtk b/contrib/apparmor/abstractions/gnunet-gtk
new file mode 100644
index 0000000000000000000000000000000000000000..bf47adc0cc82c80b615a07873e1b38743b8da621
--- /dev/null
+++ b/contrib/apparmor/abstractions/gnunet-gtk
@@ -0,0 +1,10 @@
+# gnunet-gtk
+
+  #include <abstractions/gnunet-common>
+ 
+  @{PROC}/@{pid}/cmdline 	  r,
+
+  /usr/share/gtk-*/settings.ini r,
+
+  @{GNUNET_PREFIX}/share/gnunet-gtk/config.d/ 			r,
+  @{GNUNET_PREFIX}/share/gnunet-gtk/config.d/gnunet-*-gtk.conf 	r,
diff --git a/contrib/apparmor/abstractions/gnunet-sgid b/contrib/apparmor/abstractions/gnunet-sgid
new file mode 100644
index 0000000000000000000000000000000000000000..b1a7655b14856cb2ce0ab63e177b156fd08a934b
--- /dev/null
+++ b/contrib/apparmor/abstractions/gnunet-sgid
@@ -0,0 +1 @@
+# gnunet-sgid
diff --git a/contrib/apparmor/abstractions/gnunet-suid b/contrib/apparmor/abstractions/gnunet-suid
new file mode 100644
index 0000000000000000000000000000000000000000..a9310734c0259a534986d47395f2ff2b4461b3ac
--- /dev/null
+++ b/contrib/apparmor/abstractions/gnunet-suid
@@ -0,0 +1,15 @@
+# gnunet-suid
+
+  /etc/ld.so.cache					mr,
+  /lib{,32,64}/ld{,32,64}-*.so 				mrix,
+  /lib{,32,64}/**/ld{,32,64}-*.so 			mrix,
+  /lib/@{multiarch}/ld{,32,64}-*.so 			mrix,
+  /lib/tls/i686/{cmov,nosegneg}/ld-*.so                 mrix,
+  /lib/i386-linux-gnu/tls/i686/{cmov,nosegneg}/ld-*.so  mrix,
+  /opt/*-linux-uclibc/lib/ld-uClibc*so*                 mrix,
+
+  @{LIBPRE}@{LIBDIRS}/** 				   r,
+  @{LIBPRE}@{LIBDIRS}/@{LIBS}.so* 			   mr,
+  @{LIBPRE}@{LIBDIRS}/**/@{LIBS}.so* 			   mr,
+  /lib/tls/i686/{cmov,nosegneg}/@{LIBS}.so* 		   mr,
+  /lib/i386-linux-gnu/tls/i686/{cmov,nosegneg}/@{LIBS}.so* mr,
diff --git a/contrib/apparmor/abstractions/gnunet-test b/contrib/apparmor/abstractions/gnunet-test
new file mode 100644
index 0000000000000000000000000000000000000000..8daf3ea9c9a11b75272b172d8b18c3faf8f88700
--- /dev/null
+++ b/contrib/apparmor/abstractions/gnunet-test
@@ -0,0 +1,13 @@
+
+  #testbed (if the /tmp directory is used)
+  /tmp/testbed*/	rw,
+  /tmp/testbed*/**	rwk,
+
+  #testbed helper
+  /tmp/testbed-helper*/ rw,
+  
+  #gnunet-testing
+  /tmp/gnunet-testing*  rw,
+  /tmp/gnunet_service_test*/ rw,
+  /tmp/gnunet_service_test*/** rw,
+  
diff --git a/contrib/apparmor/gnunet-arm b/contrib/apparmor/gnunet-arm
new file mode 100644
index 0000000000000000000000000000000000000000..8e2fdd426b533d83b13db773e0a94ebff35a1320
--- /dev/null
+++ b/contrib/apparmor/gnunet-arm
@@ -0,0 +1,21 @@
+#Last Modified: Fri Jul  3 14:48:33 2015
+#include <tunables/global>
+#include <tunables/gnunet>
+
+profile @{GNUNET_PREFIX}/bin/gnunet-arm {
+  #include <abstractions/base>
+  #include <abstractions/gnunet-common>
+
+  @{GNUNET_PREFIX}/bin/gnunet-arm mr,
+
+  @{GNUNET_PREFIX}/lib/libgnunetarm.so.* mr,
+
+  #GNUnet service
+  @{GNUNET_PREFIX}/lib/gnunet/libexec/gnunet-service-arm Px ,
+
+  /tmp/gnunet-*-runtime/ rw,
+  /tmp/gnunet-*-runtime/gnunet-service-arm.sock rw,
+  
+  # Site-specific additions and overrides. See local/README for details.
+  #include <local/gnunet>
+}
diff --git a/contrib/apparmor/gnunet-ats b/contrib/apparmor/gnunet-ats
new file mode 100644
index 0000000000000000000000000000000000000000..2c69b4ec0111e9f1b0b7f110aa92c25df3cabdc5
--- /dev/null
+++ b/contrib/apparmor/gnunet-ats
@@ -0,0 +1,15 @@
+# Last Modified: Wed Aug  5 15:08:43 2015
+#include <tunables/global>
+#include <tunables/gnunet>
+
+profile @{GNUNET_PREFIX}/bin/gnunet-ats {
+  #include <abstractions/base>
+  #include <abstractions/gnunet-common>
+
+  @{HOME}/.config/gnunet.conf r,
+
+  @{GNUNET_PREFIX}/bin/gnunet-ats mr,
+  
+  # Site-specific additions and overrides. See local/README for details.
+  #include <local/gnunet>
+}
diff --git a/contrib/apparmor/gnunet-auto-share b/contrib/apparmor/gnunet-auto-share
new file mode 100644
index 0000000000000000000000000000000000000000..0206acf39bcb04b785da79e423ccead6269fa148
--- /dev/null
+++ b/contrib/apparmor/gnunet-auto-share
@@ -0,0 +1,27 @@
+# Last Modified: Thu Aug  6 11:44:37 2015
+#include <tunables/global>
+#include <tunables/gnunet>
+
+profile @{GNUNET_PREFIX}/bin/gnunet-auto-share {
+  #include <abstractions/base>
+  #include <abstractions/gnunet-common>
+
+  @{HOME}/.config/gnunet.conf r,
+
+  #Directory access(?)
+  @{HOME}/gnunet-fs/ r,
+  @{HOME}/gnunet-fs/.auto-share rw,
+
+  @{GNUNET_PREFIX}/bin/gnunet-auto-share mr,
+
+  @{GNUNET_PREFIX}/bin/gnunet-publish Px,
+
+  @{GNUNET_PREFIX}/lib/libgnunetutil.so.* mr,
+
+  @{GNUNET_PREFIX}/share/gnunet/config.d/ r,
+  @{GNUNET_PREFIX}/share/gnunet/config.d/*.conf r,
+  
+  # Site-specific additions and overrides. See local/README for details.
+  #include <local/gnunet>
+
+}
diff --git a/contrib/apparmor/gnunet-bcd b/contrib/apparmor/gnunet-bcd
new file mode 100644
index 0000000000000000000000000000000000000000..2173e03b5dcbe9a926e789048a79559775357c98
--- /dev/null
+++ b/contrib/apparmor/gnunet-bcd
@@ -0,0 +1,14 @@
+# Last Modified: Thu Aug  6 11:50:51 2015
+#include <tunables/global>
+#include <tunables/gnunet>
+
+profile @{GNUNET_PREFIX}/bin/gnunet-bcd {
+  #include <abstractions/base>
+  #include <abstractions/gnunet-common>
+  
+  @{GNUNET_PREFIX}/bin/gnunet-bcd mr,
+  
+  # Site-specific additions and overrides. See local/README for details.
+  #include <local/gnunet>
+
+}
diff --git a/contrib/apparmor/gnunet-cadet b/contrib/apparmor/gnunet-cadet
new file mode 100644
index 0000000000000000000000000000000000000000..ef82d742a36c3c5fa7c7d0023d1a516869e47de6
--- /dev/null
+++ b/contrib/apparmor/gnunet-cadet
@@ -0,0 +1,13 @@
+# Last Modified: Thu Aug  6 11:59:53 2015
+#include <tunables/global>
+#include <tunables/gnunet>
+
+profile @{GNUNET_PREFIX}/bin/gnunet-cadet {
+  #include <abstractions/base>
+  #include <abstractions/gnunet-common>
+
+  @{GNUNET_PREFIX}/bin/gnunet-cadet mr,
+  
+  # Site-specific additions and overrides. See local/README for details.
+  #include <local/gnunet>
+}
diff --git a/contrib/apparmor/gnunet-config b/contrib/apparmor/gnunet-config
new file mode 100644
index 0000000000000000000000000000000000000000..28aef4259e628eadd6a77f07aebd6d0d7c55679c
--- /dev/null
+++ b/contrib/apparmor/gnunet-config
@@ -0,0 +1,13 @@
+# Last Modified: Fri Aug  7 15:36:02 2015
+#include <tunables/global>
+#include <tunables/gnunet>
+
+profile @{GNUNET_PREFIX}/bin/gnunet-config {
+  #include <abstractions/base>
+  #include <abstractions/gnunet-common>
+
+  @{GNUNET_PREFIX}/bin/gnunet-config mr,
+
+  # Site-specific additions and overrides. See local/README for details.
+  #include <local/gnunet>
+}
diff --git a/contrib/apparmor/gnunet-conversation b/contrib/apparmor/gnunet-conversation
new file mode 100644
index 0000000000000000000000000000000000000000..7c14fc382619f705b84b6f9084bffc3145f11fda
--- /dev/null
+++ b/contrib/apparmor/gnunet-conversation
@@ -0,0 +1,13 @@
+# Last Modified: Fri Aug  7 15:41:05 2015
+#include <tunables/global>
+#include <tunables/gnunet>
+
+profile @{GNUNET_PREFIX}/bin/gnunet-conversation {
+  #include <abstractions/base>
+  #include <abstractions/gnunet-common>
+
+  @{GNUNET_PREFIX}/bin/gnunet-conversation mr,
+
+  # Site-specific additions and overrides. See local/README for details.
+  #include <local/gnunet>
+}
diff --git a/contrib/apparmor/gnunet-conversation-gtk b/contrib/apparmor/gnunet-conversation-gtk
new file mode 100644
index 0000000000000000000000000000000000000000..676cb198dbaa98bc36a4d5fcf06ccac1026e755f
--- /dev/null
+++ b/contrib/apparmor/gnunet-conversation-gtk
@@ -0,0 +1,26 @@
+# Last Modified: Tue Aug  4 16:59:51 2015
+#include <tunables/global>
+#include <tunables/gnunet>
+
+profile @{GNUNET_PREFIX}/bin/gnunet-conversation-gtk {
+  #include <abstractions/kde>
+  #include <abstractions/gnome>
+  #include <abstractions/gnunet-gtk>
+
+  @{GNUNET_PREFIX}/bin/gnunet-conversation-gtk mr,
+
+  @{GNUNET_PREFIX}/lib/gnunet/ r,
+# @{GNUNET_PREFIX}/lib/gnunet/libgnunet_plugin_gnsrecord_conversation.la r,
+  @{GNUNET_PREFIX}/lib/gnunet/libgnunet_plugin_gnsrecord_conversation.so mr,
+# @{GNUNET_PREFIX}/lib/gnunet/libgnunet_plugin_gnsrecord_dns.la r,
+  @{GNUNET_PREFIX}/lib/gnunet/libgnunet_plugin_gnsrecord_dns.so mr,
+# @{GNUNET_PREFIX}/lib/gnunet/libgnunet_plugin_gnsrecord_gns.la r,
+  @{GNUNET_PREFIX}/lib/gnunet/libgnunet_plugin_gnsrecord_gns.so mr,
+
+  @{GNUNET_PREFIX}/share/gnunet-gtk/gnunet_conversation_gtk_main_window.glade r,
+
+  @{HOME}/.local/share/gnunet/private_key.ecc rk,
+  
+  # Site-specific additions and overrides. See local/README for details.
+  #include <local/gnunet>
+}
diff --git a/contrib/apparmor/gnunet-conversation-test b/contrib/apparmor/gnunet-conversation-test
new file mode 100644
index 0000000000000000000000000000000000000000..7eefec2ce3728feb98b0c6caffa3dc13d0d3887b
--- /dev/null
+++ b/contrib/apparmor/gnunet-conversation-test
@@ -0,0 +1,16 @@
+# Last Modified: Fri Aug  7 16:02:29 2015
+#include <tunables/global>
+#include <tunables/gnunet>
+
+profile @{GNUNET_PREFIX}/bin/gnunet-conversation-test {
+  #include <abstractions/base>
+  #include <abstractions/gnunet-common>
+
+  @{GNUNET_PREFIX}/bin/gnunet-conversation-test mr,
+
+  @{GNUNET_PREFIX}/lib/gnunet/libexec/gnunet-helper-audio-playback Px,
+  @{GNUNET_PREFIX}/lib/gnunet/libexec/gnunet-helper-audio-record Px,
+
+  # Site-specific additions and overrides. See local/README for details.
+  #include <local/gnunet>
+}
diff --git a/contrib/apparmor/gnunet-core b/contrib/apparmor/gnunet-core
new file mode 100644
index 0000000000000000000000000000000000000000..83b1f3f83bf675d0bb9727102c486cb3e005c311
--- /dev/null
+++ b/contrib/apparmor/gnunet-core
@@ -0,0 +1,13 @@
+# Last Modified: Fri Aug  7 16:12:14 2015
+#include <tunables/global>
+#include <tunables/gnunet>
+
+profile @{GNUNET_PREFIX}/bin/gnunet-core {
+  #include <abstractions/base>
+  #include <abstractions/gnunet-common>
+
+  @{GNUNET_PREFIX}/bin/gnunet-core mr,
+
+  # Site-specific additions and overrides. See local/README for details.
+  #include <local/gnunet>
+}
diff --git a/contrib/apparmor/gnunet-daemon-exit b/contrib/apparmor/gnunet-daemon-exit
new file mode 100644
index 0000000000000000000000000000000000000000..3c5b995571d238e42c9ecba35fc8a34a4d14c96c
--- /dev/null
+++ b/contrib/apparmor/gnunet-daemon-exit
@@ -0,0 +1,13 @@
+# Last Modified: Mon Jul 27 15:57:50 2015
+#include <tunables/global>
+#include <tunables/gnunet>
+
+profile @{GNUNET_PREFIX}/lib/gnunet/libexec/gnunet-daemon-exit {
+  #include <abstractions/base>
+  #include <abstractions/gnunet-common>
+
+  @{GNUNET_PREFIX}/lib/gnunet/libexec/gnunet-daemon-exit mr,
+  
+  # Site-specific additions and overrides. See local/README for details.
+  #include <local/gnunet>
+}
diff --git a/contrib/apparmor/gnunet-daemon-hostlist b/contrib/apparmor/gnunet-daemon-hostlist
new file mode 100644
index 0000000000000000000000000000000000000000..4e21b1b30547fbed875745bdba913b2ed04bb593
--- /dev/null
+++ b/contrib/apparmor/gnunet-daemon-hostlist
@@ -0,0 +1,19 @@
+# Last Modified: Fri Jul 10 10:43:55 2015
+#include <tunables/global>
+#include <tunables/gnunet>
+
+profile @{GNUNET_PREFIX}/lib/gnunet/libexec/gnunet-daemon-hostlist {
+  #include <abstractions/base>
+  #include <abstractions/gnunet-common>
+
+  /etc/gai.conf r,
+  /etc/host.conf r,
+  /etc/hosts r,
+  /etc/nsswitch.conf r,
+  /etc/resolv.conf r,
+
+  @{GNUNET_PREFIX}/lib/gnunet/libexec/gnunet-daemon-hostlist mr,
+  
+  # Site-specific additions and overrides. See local/README for details.
+  #include <local/gnunet>
+}
diff --git a/contrib/apparmor/gnunet-daemon-latency-logger b/contrib/apparmor/gnunet-daemon-latency-logger
new file mode 100644
index 0000000000000000000000000000000000000000..531516f1deb6746d291b4c6f7df6fd44af50fd82
--- /dev/null
+++ b/contrib/apparmor/gnunet-daemon-latency-logger
@@ -0,0 +1,13 @@
+# Last Modified: Mon Jul 27 16:25:08 2015
+#include <tunables/global>
+#include <tunables/gnunet>
+
+profile @{GNUNET_PREFIX}/lib/gnunet/libexec/gnunet-daemon-latency-logger {
+  #include <abstractions/base>
+  #include <abstractions/gnunet-common>
+
+  @{GNUNET_PREFIX}/lib/gnunet/libexec/gnunet-daemon-latency-logger mr,
+  
+  # Site-specific additions and overrides. See local/README for details.
+  #include <local/gnunet>
+}
diff --git a/contrib/apparmor/gnunet-daemon-pt b/contrib/apparmor/gnunet-daemon-pt
new file mode 100644
index 0000000000000000000000000000000000000000..b30160c1a594424a8889544567fd8e416a0aea1b
--- /dev/null
+++ b/contrib/apparmor/gnunet-daemon-pt
@@ -0,0 +1,13 @@
+# Last Modified: Mon Jul 20 17:48:20 2015
+#include <tunables/global>
+#include <tunables/gnunet>
+
+profile @{GNUNET_PREFIX}/lib/gnunet/libexec/gnunet-daemon-pt {
+  #include <abstractions/base>
+  #include <abstractions/gnunet-common>
+
+  @{GNUNET_PREFIX}/lib/gnunet/libexec/gnunet-daemon-pt mr,
+  
+  # Site-specific additions and overrides. See local/README for details.
+  #include <local/gnunet>
+}
diff --git a/contrib/apparmor/gnunet-daemon-regexprofiler b/contrib/apparmor/gnunet-daemon-regexprofiler
new file mode 100644
index 0000000000000000000000000000000000000000..c47533bd001db8929829097191d0fa23e65b5e71
--- /dev/null
+++ b/contrib/apparmor/gnunet-daemon-regexprofiler
@@ -0,0 +1,13 @@
+# Last Modified: Tue Jul 28 11:42:58 2015
+#include <tunables/global>
+#include <tunables/gnunet>
+
+profile @{GNUNET_PREFIX}/lib/gnunet/libexec/gnunet-daemon-regexprofiler {
+  #include <abstractions/base>
+  #include <abstractions/gnunet-common>
+
+  @{GNUNET_PREFIX}/lib/gnunet/libexec/gnunet-daemon-regexprofiler mr,
+  
+  # Site-specific additions and overrides. See local/README for details.
+  #include <local/gnunet>
+}
diff --git a/contrib/apparmor/gnunet-daemon-testbed-blacklist b/contrib/apparmor/gnunet-daemon-testbed-blacklist
new file mode 100644
index 0000000000000000000000000000000000000000..2f01531f8e0c72bfbf1c382fd5e5fb34910b94fc
--- /dev/null
+++ b/contrib/apparmor/gnunet-daemon-testbed-blacklist
@@ -0,0 +1,13 @@
+# Last Modified: Tue Jul 28 11:42:58 2015
+#include <tunables/global>
+#include <tunables/gnunet>
+
+profile @{GNUNET_PREFIX}/lib/gnunet/libexec/gnunet-daemon-testbed-blacklist {
+  #include <abstractions/base>
+  #include <abstractions/gnunet-common>
+
+  @{GNUNET_PREFIX}/lib/gnunet/libexec/gnunet-daemon-testbed-blacklist mr,
+  
+  # Site-specific additions and overrides. See local/README for details.
+  #include <local/gnunet>
+}
diff --git a/contrib/apparmor/gnunet-daemon-testbed-underlay b/contrib/apparmor/gnunet-daemon-testbed-underlay
new file mode 100644
index 0000000000000000000000000000000000000000..f9423ac7f141cd9efabe730238fe801ff99d472a
--- /dev/null
+++ b/contrib/apparmor/gnunet-daemon-testbed-underlay
@@ -0,0 +1,13 @@
+# Last Modified: Mon Jul 27 16:37:03 2015
+#include <tunables/global>
+#include <tunables/gnunet>
+
+profile @{GNUNET_PREFIX}/lib/gnunet/libexec/gnunet-daemon-testbed-underlay {
+  #include <abstractions/base>
+  #include <abstractions/gnunet-common>
+
+  @{GNUNET_PREFIX}/lib/gnunet/libexec/gnunet-daemon-testbed-underlay mr,
+  
+  # Site-specific additions and overrides. See local/README for details.
+  #include <local/gnunet>
+}
diff --git a/contrib/apparmor/gnunet-daemon-topology b/contrib/apparmor/gnunet-daemon-topology
new file mode 100644
index 0000000000000000000000000000000000000000..777baa4f3919ebae473e4b820fb8655eb16962a4
--- /dev/null
+++ b/contrib/apparmor/gnunet-daemon-topology
@@ -0,0 +1,13 @@
+# Last Modified: Fri Jul  3 17:37:12 2015
+#include <tunables/global>
+#include <tunables/gnunet>
+
+profile @{GNUNET_PREFIX}/lib/gnunet/libexec/gnunet-daemon-topology {
+  #include <abstractions/base>
+  #include <abstractions/gnunet-common>
+
+  @{GNUNET_PREFIX}/lib/gnunet/libexec/gnunet-daemon-topology mr,
+  
+  # Site-specific additions and overrides. See local/README for details.
+  #include <local/gnunet>
+}
diff --git a/contrib/apparmor/gnunet-datastore b/contrib/apparmor/gnunet-datastore
new file mode 100644
index 0000000000000000000000000000000000000000..2ade374b6eb33712ec63ba3b9d21458d3204971e
--- /dev/null
+++ b/contrib/apparmor/gnunet-datastore
@@ -0,0 +1,13 @@
+# Last Modified: Fri Aug  7 16:29:48 2015
+#include <tunables/global>
+#include <tunables/gnunet>
+
+profile @{GNUNET_PREFIX}/bin/gnunet-datastore {
+  #include <abstractions/base>
+  #include <abstractions/gnunet-common>
+
+  @{GNUNET_PREFIX}/bin/gnunet-datastore mr,
+
+  # Site-specific additions and overrides. See local/README for details.
+  #include <local/gnunet>
+}
diff --git a/contrib/apparmor/gnunet-directory b/contrib/apparmor/gnunet-directory
new file mode 100644
index 0000000000000000000000000000000000000000..caad23e7f568f31fc7e3575fba2c950202c6ba4c
--- /dev/null
+++ b/contrib/apparmor/gnunet-directory
@@ -0,0 +1,16 @@
+# Last Modified: Fri Aug  7 16:34:37 2015
+#include <tunables/global>
+#include <tunables/gnunet>
+
+profile @{GNUNET_PREFIX}/bin/gnunet-directory {
+  #include <abstractions/base>
+  #include <abstractions/gnunet-common>
+
+  @{GNUNET_PREFIX}/bin/gnunet-directory mr,
+
+  # Access to directory ?
+
+
+  # Site-specific additions and overrides. See local/README for details.
+  #include <local/gnunet>
+}
diff --git a/contrib/apparmor/gnunet-dns2gns b/contrib/apparmor/gnunet-dns2gns
new file mode 100644
index 0000000000000000000000000000000000000000..6720c102ecdac4ad8fc8b20b920aad64649fb58e
--- /dev/null
+++ b/contrib/apparmor/gnunet-dns2gns
@@ -0,0 +1,13 @@
+# Last Modified: Tue Jul 21 16:45:05 2015
+#include <tunables/global>
+#include <tunables/gnunet>
+
+profile @{GNUNET_PREFIX}/lib/gnunet/libexec/gnunet-dns2gns {
+  #include <abstractions/base>
+  #include <abstractions/gnunet-common>
+
+  @{GNUNET_PREFIX}/lib/gnunet/libexec/gnunet-dns2gns mr,
+  
+  # Site-specific additions and overrides. See local/README for details.
+  #include <local/gnunet>
+}
diff --git a/contrib/apparmor/gnunet-download b/contrib/apparmor/gnunet-download
new file mode 100644
index 0000000000000000000000000000000000000000..bcc2128575e86d28a7126e142f790454e72f157f
--- /dev/null
+++ b/contrib/apparmor/gnunet-download
@@ -0,0 +1,13 @@
+# Last Modified: Fri Aug  7 16:42:43 2015
+#include <tunables/global>
+#include <tunables/gnunet>
+
+profile @{GNUNET_PREFIX}/bin/gnunet-download {
+  #include <abstractions/base>
+  #include <abstractions/gnunet-common>
+
+  @{GNUNET_PREFIX}/bin/gnunet-download mr,
+
+  # Site-specific additions and overrides. See local/README for details.
+  #include <local/gnunet>
+}
diff --git a/contrib/apparmor/gnunet-download-manager.scm b/contrib/apparmor/gnunet-download-manager.scm
new file mode 100644
index 0000000000000000000000000000000000000000..a1e8c07ddf31e9cab514d095aa93d684c6ddc4ed
--- /dev/null
+++ b/contrib/apparmor/gnunet-download-manager.scm
@@ -0,0 +1,25 @@
+# vim:syntax=apparmor
+# Last Modified: Tue Aug 11 11:17:17 2015
+#include <tunables/global>
+#include <tunables/gnunet>
+
+profile @{GNUNET_PREFIX}/bin/gnunet-download-manager.scm {
+  #include <abstractions/base>
+  #include <abstractions/bash>
+
+  /dev/tty rw,
+
+  @{HOME}/.cache/guile/ccache/*-LE-*@{GNUNET_PREFIX}/bin/gnunet-download-manager.scm.go.* rw,
+
+  @{PROC}/@{pid}/statm r,
+
+  /usr/bin/bash ix,
+  /usr/bin/guile rix,
+
+  @{GNUNET_PREFIX}/bin/gnunet-download-manager.scm r,
+
+  /usr/share/guile/**/*.scm r,
+
+  # Site-specific additions and overrides. See local/README for details.
+  #include <local/gnunet>
+}
diff --git a/contrib/apparmor/gnunet-ecc b/contrib/apparmor/gnunet-ecc
new file mode 100644
index 0000000000000000000000000000000000000000..67e2ac4e03a9f1bd4403390fb53126bb60471c3f
--- /dev/null
+++ b/contrib/apparmor/gnunet-ecc
@@ -0,0 +1,15 @@
+# Last Modified: Fri Aug  7 16:54:41 2015
+#include <tunables/global>
+#include <tunables/gnunet>
+
+profile @{GNUNET_PREFIX}/bin/gnunet-ecc {
+  #include <abstractions/base>
+  #include <abstractions/gnunet-common>
+
+  @{GNUNET_PREFIX}/bin/gnunet-ecc mr,
+
+  #Access to filename?
+
+  # Site-specific additions and overrides. See local/README for details.
+  #include <local/gnunet>
+}
diff --git a/contrib/apparmor/gnunet-fs b/contrib/apparmor/gnunet-fs
new file mode 100644
index 0000000000000000000000000000000000000000..4637b251b269742909a55871a94684d7f5e12c99
--- /dev/null
+++ b/contrib/apparmor/gnunet-fs
@@ -0,0 +1,13 @@
+# Last Modified: Fri Aug  7 17:09:21 2015
+#include <tunables/global>
+#include <tunables/gnunet>
+
+profile @{GNUNET_PREFIX}/bin/gnunet-fs {
+  #include <abstractions/base>
+  #include <abstractions/gnunet-common>
+
+  @{GNUNET_PREFIX}/bin/gnunet-fs mr,
+
+  # Site-specific additions and overrides. See local/README for details.
+  #include <local/gnunet>
+}
diff --git a/contrib/apparmor/gnunet-fs-gtk b/contrib/apparmor/gnunet-fs-gtk
new file mode 100644
index 0000000000000000000000000000000000000000..0ffb0b38b5c31df04f7570303fff1555441460ab
--- /dev/null
+++ b/contrib/apparmor/gnunet-fs-gtk
@@ -0,0 +1,43 @@
+# Last Modified: Wed Aug  5 10:53:37 2015
+#include <tunables/global>
+#include <tunables/gnunet>
+
+profile @{GNUNET_PREFIX}/bin/gnunet-fs-gtk {
+  #include <abstractions/gnome>
+  #include <abstractions/kde>
+  #include <abstractions/dconf>
+  #include <abstractions/gnunet-gtk>
+  #include <abstractions/user-download>
+
+#  /dev/shm/LE-* rw,  
+
+  owner @{HOME}/.config/gtk-*/bookmarks r,
+  owner @{HOME}/.local/share/gnunet/fs/persistence/gnunet-fs-gtk/download-child/* rw,
+  owner @{HOME}/.local/share/gnunet/fs/persistence/gnunet-fs-gtk/download/ r,
+  owner @{HOME}/.local/share/gnunet/fs/persistence/gnunet-fs-gtk/download/* rw,
+  owner @{HOME}/.local/share/gnunet/fs/persistence/gnunet-fs-gtk/search/ r,
+  owner @{HOME}/.local/share/gnunet/fs/persistence/gnunet-fs-gtk/search/** rw,
+  owner @{HOME}/.local/share/gnunet/fs/persistence/gnunet-fs-gtk/publish-file/ ra,
+  owner @{HOME}/.local/share/gnunet/fs/persistence/gnunet-fs-gtk/publish-file/* rw,
+  owner @{HOME}/.local/share/gnunet/fs/persistence/gnunet-fs-gtk/publish/ ra,
+  owner @{HOME}/.local/share/gnunet/fs/persistence/gnunet-fs-gtk/publish/* rw,
+  
+  #Acces to files to share ? (lets create a gnunet directory in home)
+  owner @{HOME}/gnunet-fs/ r,
+
+  @{GNUNET_PREFIX}/bin/gnunet-fs-gtk mr,
+
+  @{GNUNET_PREFIX}/share/gnunet-gtk/* r,
+
+  /usr/share/glib-*/schemas/gschemas.compiled r,
+
+  #abstractions/dconf but we need write right here 
+  /run/user/*/dconf/user rw,
+ 
+  @{HOME}/.cache/thumbnails/normal/*.png r,
+
+  @{GNUNET_PREFIX}/lib/gnunet/libexec/gnunet-helper-fs-publish Px,
+  
+  # Site-specific additions and overrides. See local/README for details.
+  #include <local/gnunet>
+}
diff --git a/contrib/apparmor/gnunet-gns b/contrib/apparmor/gnunet-gns
new file mode 100644
index 0000000000000000000000000000000000000000..1b63d2506a45c1ffd4ad8643a40d0df41581ad66
--- /dev/null
+++ b/contrib/apparmor/gnunet-gns
@@ -0,0 +1,21 @@
+# Last Modified: Fri Aug  7 17:41:19 2015
+#include <tunables/global>
+#include <tunables/gnunet>
+
+profile /usr/local/bin/gnunet-gns {
+  #include <abstractions/base>
+  #include <abstractions/gnunet-common>
+
+  /usr/local/bin/gnunet-gns mr,
+
+  /usr/local/lib/gnunet/ r,
+# /usr/local/lib/gnunet/libgnunet_plugin_gnsrecord_conversation.la r,
+  /usr/local/lib/gnunet/libgnunet_plugin_gnsrecord_conversation.so mr,
+# /usr/local/lib/gnunet/libgnunet_plugin_gnsrecord_dns.la r,
+  /usr/local/lib/gnunet/libgnunet_plugin_gnsrecord_dns.so mr,
+# /usr/local/lib/gnunet/libgnunet_plugin_gnsrecord_gns.la r,
+  /usr/local/lib/gnunet/libgnunet_plugin_gnsrecord_gns.so mr,
+
+  # Site-specific additions and overrides. See local/README for details.
+  #include <local/gnunet>
+}
diff --git a/contrib/apparmor/gnunet-gns-import.sh b/contrib/apparmor/gnunet-gns-import.sh
new file mode 100644
index 0000000000000000000000000000000000000000..631717ccf4a6b992f034dd8e5db78eebbbd06121
--- /dev/null
+++ b/contrib/apparmor/gnunet-gns-import.sh
@@ -0,0 +1,22 @@
+# Last Modified: Tue Aug 11 10:19:01 2015
+#include <tunables/global>
+#include <tunables/gnunet>
+
+profile @{GNUNET_PREFIX}/bin/gnunet-gns-import.sh {
+  #include <abstractions/base>
+  #include <abstractions/bash>
+  #include <abstractions/gnunet-common>
+
+  /dev/tty rw,
+  /usr/bin/bash ix,
+  /usr/bin/gawk rix,
+  /usr/bin/grep rix,
+  /usr/bin/which rix,
+  @{GNUNET_PREFIX}/bin/gnunet-arm Px,
+  @{GNUNET_PREFIX}/bin/gnunet-config rPx,
+  @{GNUNET_PREFIX}/bin/gnunet-gns-import.sh r,
+  @{GNUNET_PREFIX}/bin/gnunet-identity Px,
+
+  # Site-specific additions and overrides. See local/README for details.
+  #include <local/gnunet>
+}
diff --git a/contrib/apparmor/gnunet-gns-proxy b/contrib/apparmor/gnunet-gns-proxy
new file mode 100644
index 0000000000000000000000000000000000000000..99a306434ccee123ec4c2e8486561f96645ded73
--- /dev/null
+++ b/contrib/apparmor/gnunet-gns-proxy
@@ -0,0 +1,17 @@
+# Last Modified: Tue Jul 21 16:35:07 2015
+#include <tunables/global>
+#include <tunables/gnunet>
+
+profile @{GNUNET_PREFIX}/lib/gnunet/libexec/gnunet-gns-proxy {
+  #include <abstractions/base>
+  #include <abstractions/gnunet-common>
+
+  /etc/ssl/openssl.cnf r,
+
+  @{HOME}/.local/share/gnunet/gns/gns_ca_cert.pem r,
+
+  @{GNUNET_PREFIX}/lib/gnunet/libexec/gnunet-gns-proxy mr,
+  
+  # Site-specific additions and overrides. See local/README for details.
+  #include <local/gnunet>
+}
diff --git a/contrib/apparmor/gnunet-gns-proxy-setup-ca b/contrib/apparmor/gnunet-gns-proxy-setup-ca
new file mode 100644
index 0000000000000000000000000000000000000000..cbb3fa19176c302c61be47e11735ac7b42898f15
--- /dev/null
+++ b/contrib/apparmor/gnunet-gns-proxy-setup-ca
@@ -0,0 +1,40 @@
+# Last Modified: Tue Aug 11 11:40:50 2015
+#include <tunables/global>
+#include <tunables/gnunet>
+
+profile @{GNUNET_PREFIX}/bin/gnunet-gns-proxy-setup-ca {
+  #include <abstractions/base>
+  #include <abstractions/bash>
+  #include <abstractions/user-tmp>
+  #include <abstractions/openssl>
+
+  /dev/tty rw,
+  /etc/passwd r,
+  /home/*/.local/share/gnunet/gns/ r,
+  /home/*/.local/share/gnunet/gns/gns_ca_cert.pem rw,
+  /home/*/.mozilla/firefox/ r,
+  /home/*/.mozilla/firefox/kw6js9xl.default/cert8.db rw,
+  /home/*/.mozilla/firefox/kw6js9xl.default/key3.db rw,
+  /home/*/.mozilla/firefox/kw6js9xl.default/secmod.db r,
+  /home/*/.pki/nssdb/cert8.db rw,
+  /home/*/.pki/nssdb/key3.db rw,
+  /home/*/.pki/nssdb/secmod.db r,
+  /home/*/.rnd rw,
+
+  /usr/bin/bash ix,
+  /usr/bin/cat rix,
+  /usr/bin/certtool r,
+  /usr/bin/certutil rix,
+  /usr/bin/dirname rix,
+  /usr/bin/mkdir rix,
+  /usr/bin/mktemp rix,
+  /usr/bin/openssl rix,
+  /usr/bin/rm rix,
+  /usr/bin/which rix,
+
+  @{GNUNET_PREFIX}/bin/gnunet-config Px,
+  @{GNUNET_PREFIX}/bin/gnunet-gns-proxy-setup-ca r,
+
+  # Site-specific additions and overrides. See local/README for details.
+  #include <local/gnunet>
+}
diff --git a/contrib/apparmor/gnunet-gtk b/contrib/apparmor/gnunet-gtk
new file mode 100644
index 0000000000000000000000000000000000000000..336748215be1e9c05a8442dacdbad9f970082b2a
--- /dev/null
+++ b/contrib/apparmor/gnunet-gtk
@@ -0,0 +1,26 @@
+# Last Modified: Wed Aug  5 11:25:26 2015
+#include <tunables/global>
+#include <tunables/gnunet>
+
+profile @{GNUNET_PREFIX}/bin/gnunet-gtk {
+  #include <abstractions/gnome>
+  #include <abstractions/gnunet-gtk>
+  #include <abstractions/kde>
+
+  @{GNUNET_PREFIX}/bin/gnunet-gtk mr,
+
+  #GNUnet gtk binaries
+  @{GNUNET_PREFIX}/bin/gnunet-conversation-gtk Px,
+  @{GNUNET_PREFIX}/bin/gnunet-fs-gtk Px,
+  @{GNUNET_PREFIX}/bin/gnunet-identity-gtk Px,
+  @{GNUNET_PREFIX}/bin/gnunet-namestore-gtk Px,
+  @{GNUNET_PREFIX}/bin/gnunet-peerinfo-gtk Px,
+  @{GNUNET_PREFIX}/bin/gnunet-statistics-gtk Px,
+
+  @{GNUNET_PREFIX}/share/gnunet-gtk/*.png r,
+  @{GNUNET_PREFIX}/share/gnunet-gtk/gnunet_gtk.glade r,
+  
+  # Site-specific additions and overrides. See local/README for details.
+  #include <local/gnunet>
+
+}
diff --git a/contrib/apparmor/gnunet-helper-audio-playback b/contrib/apparmor/gnunet-helper-audio-playback
new file mode 100644
index 0000000000000000000000000000000000000000..67d3ba3715c280bfb20e3fcc142bc554b2d3e330
--- /dev/null
+++ b/contrib/apparmor/gnunet-helper-audio-playback
@@ -0,0 +1,17 @@
+# Last Modified: Tue Jul 28 11:46:24 2015
+#include <tunables/global>
+#include <tunables/gnunet>
+
+profile @{GNUNET_PREFIX}/lib/gnunet/libexec/gnunet-helper-audio-playback {
+  #include <abstractions/base>
+  #include <abstractions/gnunet-common>
+  #include <abstractions/audio>
+
+  @{GNUNET_PREFIX}/lib/gnunet/libexec/gnunet-helper-audio-playback mr,
+  
+  /etc/machine-id r,
+  owner @{HOME}/.Xauthority r,
+
+  # Site-specific additions and overrides. See local/README for details.
+  #include <local/gnunet>
+}
diff --git a/contrib/apparmor/gnunet-helper-audio-record b/contrib/apparmor/gnunet-helper-audio-record
new file mode 100644
index 0000000000000000000000000000000000000000..afed73ffbb531b30da33f400783c81ee22df5be4
--- /dev/null
+++ b/contrib/apparmor/gnunet-helper-audio-record
@@ -0,0 +1,17 @@
+# Last Modified: Tue Jul 28 11:42:58 2015
+#include <tunables/global>
+#include <tunables/gnunet>
+
+profile @{GNUNET_PREFIX}/lib/gnunet/libexec/gnunet-helper-audio-record {
+  #include <abstractions/base>
+  #include <abstractions/gnunet-common>
+  #include <abstractions/audio>
+
+  @{GNUNET_PREFIX}/lib/gnunet/libexec/gnunet-helper-audio-record mr,
+ 
+  /etc/machine-id r,
+  owner @{HOME}/.Xauthority r,
+
+  # Site-specific additions and overrides. See local/README for details.
+  #include <local/gnunet>
+}
diff --git a/contrib/apparmor/gnunet-helper-dns b/contrib/apparmor/gnunet-helper-dns
new file mode 100644
index 0000000000000000000000000000000000000000..b5e2195857f81495d401542524c8dd67af251d06
--- /dev/null
+++ b/contrib/apparmor/gnunet-helper-dns
@@ -0,0 +1,48 @@
+# Last Modified: Mon Jul 27 15:24:34 2015
+#include <tunables/global>
+#include <tunables/gnunet>
+
+profile @{GNUNET_PREFIX}/lib/gnunet/libexec/gnunet-helper-dns {
+  #include <abstractions/gnunet-suid>
+
+  #Capability
+  capability net_admin,
+  capability net_raw,
+  capability setuid,
+
+  /dev/net/tun rw,
+  /dev/null rw,
+
+  /etc/gai.conf r,
+  /etc/group r,
+  /etc/iproute2/rt_tables r,
+  /etc/nsswitch.conf r,
+  /etc/protocols r,
+
+  @{PROC}/@{pid}/net/ip_tables_names r,
+  @{PROC}/sys/net/ipv4/conf/all/rp_filter rw,
+  @{PROC}/sys/net/ipv4/conf/default/rp_filter rw,
+
+  /usr/bin/ip rix,
+  /usr/bin/sysctl rix,
+  /usr/bin/xtables-multi rix,
+
+  #Librairies
+  /usr/lib/iptables/libxt_MARK.so mr,
+  /usr/lib/iptables/libxt_owner.so mr,
+  /usr/lib/iptables/libxt_standard.so mr,
+  /usr/lib/iptables/libxt_udp.so mr,
+  /usr/lib/ld-*.so r,
+  /usr/lib/libip4tc.so.* mr,
+  /usr/lib/libip6tc.so.* mr,
+  /usr/lib/libnss_files-*.so mr,
+
+  /usr/lib/libxtables.so.* mr,
+
+  /usr/lib/locale/locale-archive r,
+
+  @{GNUNET_PREFIX}/lib/gnunet/libexec/gnunet-helper-dns mr,
+  
+  # Site-specific additions and overrides. See local/README for details.
+  #include <local/gnunet>
+}
diff --git a/contrib/apparmor/gnunet-helper-exit b/contrib/apparmor/gnunet-helper-exit
new file mode 100644
index 0000000000000000000000000000000000000000..f69e34d0c90c1f5ea2a592d12dc1638c29db387a
--- /dev/null
+++ b/contrib/apparmor/gnunet-helper-exit
@@ -0,0 +1,14 @@
+# Last Modified: Tue Jul 28 11:44:00 2015
+#include <tunables/global>
+#include <tunables/gnunet>
+
+profile @{GNUNET_PREFIX}/lib/gnunet/libexec/gnunet-helper-exit {
+  #include <abstractions/gnunet-suid>
+
+  capability setuid,
+
+  @{GNUNET_PREFIX}/lib/gnunet/libexec/gnunet-helper-exit mr,
+  
+  # Site-specific additions and overrides. See local/README for details.
+  #include <local/gnunet-suid>
+}
diff --git a/contrib/apparmor/gnunet-helper-fs-publish b/contrib/apparmor/gnunet-helper-fs-publish
new file mode 100644
index 0000000000000000000000000000000000000000..9d437194c0509da4c5005350d3998db86029e326
--- /dev/null
+++ b/contrib/apparmor/gnunet-helper-fs-publish
@@ -0,0 +1,18 @@
+# Last Modified: Tue Jul 28 11:42:58 2015
+#include <tunables/global>
+#include <tunables/gnunet>
+
+profile @{GNUNET_PREFIX}/lib/gnunet/libexec/gnunet-helper-fs-publish {
+  #include <abstractions/base>
+  #include <abstractions/gnunet-common>
+  #include <abstractions/user-download>
+
+  /dev/shm/LE-* r,
+
+  /usr/share/file/misc/magic.mgc r,
+
+  @{GNUNET_PREFIX}/lib/gnunet/libexec/gnunet-helper-fs-publish mr,
+  
+  # Site-specific additions and overrides. See local/README for details.
+  #include <local/gnunet>
+}
diff --git a/contrib/apparmor/gnunet-helper-nat-client b/contrib/apparmor/gnunet-helper-nat-client
new file mode 100644
index 0000000000000000000000000000000000000000..ead52a5f1a1d6edbf556a7ca9dd6030eb926987e
--- /dev/null
+++ b/contrib/apparmor/gnunet-helper-nat-client
@@ -0,0 +1,14 @@
+# Last Modified: Tue Jul 28 11:44:00 2015
+#include <tunables/global>
+#include <tunables/gnunet>
+
+profile @{GNUNET_PREFIX}/lib/gnunet/libexec/gnunet-helper-nat-client {
+  #include <abstractions/gnunet-suid>
+
+  capability setuid,
+
+  @{GNUNET_PREFIX}/lib/gnunet/libexec/gnunet-helper-nat-client mr,
+  
+  # Site-specific additions and overrides. See local/README for details.
+  #include <local/gnunet-suid>
+}
diff --git a/contrib/apparmor/gnunet-helper-nat-server b/contrib/apparmor/gnunet-helper-nat-server
new file mode 100644
index 0000000000000000000000000000000000000000..d458f467fe438f3fbc600838d85d12c27ff2608d
--- /dev/null
+++ b/contrib/apparmor/gnunet-helper-nat-server
@@ -0,0 +1,15 @@
+# Last Modified: Tue Jul 28 11:44:00 2015
+#include <tunables/global>
+#include <tunables/gnunet>
+
+profile @{GNUNET_PREFIX}/lib/gnunet/libexec/gnunet-helper-nat-server {
+  #include <abstractions/gnunet-suid>
+
+  capability setuid,
+
+  @{GNUNET_PREFIX}/lib/gnunet/libexec/gnunet-helper-nat-server mr,
+  
+  # Site-specific additions and overrides. See local/README for details.
+  #include <local/gnunet-suid>
+
+}
diff --git a/contrib/apparmor/gnunet-helper-testbed b/contrib/apparmor/gnunet-helper-testbed
new file mode 100644
index 0000000000000000000000000000000000000000..b7b41f688820fa8b688699ed58cd8e69e6779e3e
--- /dev/null
+++ b/contrib/apparmor/gnunet-helper-testbed
@@ -0,0 +1,21 @@
+# Last Modified: Mon Jul 27 11:02:37 2015
+#include <tunables/global>
+#include <tunables/gnunet>
+
+profile @{GNUNET_PREFIX}/lib/gnunet/libexec/gnunet-helper-testbed {
+  #include <abstractions/base>
+  #include <abstractions/gnunet-common>
+  #include <abstractions/gnunet-test>
+
+  /etc/gai.conf r,
+
+  @{GNUNET_PREFIX}/lib/gnunet/libexec/ r,
+  @{GNUNET_PREFIX}/lib/gnunet/libexec/gnunet-helper-testbed mr,
+  #@{GNUNET_PREFIX}/lib/gnunet/libexec/gnunet-service-arm r,
+  @{GNUNET_PREFIX}/lib/gnunet/libexec/gnunet-service-testbed Px,
+
+  @{GNUNET_PREFIX}/share/gnunet/testing_hostkeys.ecc r,
+  
+  # Site-specific additions and overrides. See local/README for details.
+  #include <local/gnunet>
+}
diff --git a/contrib/apparmor/gnunet-helper-transport-bluetooth b/contrib/apparmor/gnunet-helper-transport-bluetooth
new file mode 100644
index 0000000000000000000000000000000000000000..b13ccb2690017d1b5efe941bce26e52906f35750
--- /dev/null
+++ b/contrib/apparmor/gnunet-helper-transport-bluetooth
@@ -0,0 +1,18 @@
+# Last Modified: Tue Jul 28 11:44:00 2015
+#include <tunables/global>
+#include <tunables/gnunet>
+
+# Add extra libs for this helper(libthread and libbluetooth)
+@{LIBS}+=libpthread libbluetooth
+
+profile @{GNUNET_PREFIX}/lib/gnunet/libexec/gnunet-helper-transport-bluetooth {
+  #include <abstractions/gnunet-suid>
+
+  capability setuid,
+
+  @{GNUNET_PREFIX}/lib/gnunet/libexec/gnunet-helper-transport-bluetooth mr,
+  
+  # Site-specific additions and overrides. See local/README for details.
+  #include <local/gnunet-suid>
+
+}
diff --git a/contrib/apparmor/gnunet-helper-transport-wlan b/contrib/apparmor/gnunet-helper-transport-wlan
new file mode 100644
index 0000000000000000000000000000000000000000..296b0c9789a5d1fc9698501ff7bf17a7c3bd0967
--- /dev/null
+++ b/contrib/apparmor/gnunet-helper-transport-wlan
@@ -0,0 +1,15 @@
+# Last Modified: Tue Jul 28 11:44:00 2015
+#include <tunables/global>
+#include <tunables/gnunet>
+
+profile @{GNUNET_PREFIX}/lib/gnunet/libexec/gnunet-helper-transport-wlan {
+  #include <abstractions/gnunet-suid>
+
+  capability setuid,
+
+  @{GNUNET_PREFIX}/lib/gnunet/libexec/gnunet-helper-transport-wlan mr,
+  
+  # Site-specific additions and overrides. See local/README for details.
+  #include <local/gnunet-suid>
+
+}
diff --git a/contrib/apparmor/gnunet-helper-transport-wlan-dummy b/contrib/apparmor/gnunet-helper-transport-wlan-dummy
new file mode 100644
index 0000000000000000000000000000000000000000..1c05144175b5ef1585c98b7e9c2e5d82ea5d8074
--- /dev/null
+++ b/contrib/apparmor/gnunet-helper-transport-wlan-dummy
@@ -0,0 +1,13 @@
+# Last Modified: Tue Jul 28 11:36:52 2015
+#include <tunables/global>
+#include <tunables/gnunet> 
+
+profile @{GNUNET_PREFIX}/lib/gnunet/libexec/gnunet-helper-transport-wlan-dummy {
+  #include <abstractions/gnunet-suid>
+
+  @{GNUNET_PREFIX}/lib/gnunet/libexec/gnunet-helper-transport-wlan-dummy mr,
+  
+  # Site-specific additions and overrides. See local/README for details.
+  #include <local/gnunet>
+
+}
diff --git a/contrib/apparmor/gnunet-helper-vpn b/contrib/apparmor/gnunet-helper-vpn
new file mode 100644
index 0000000000000000000000000000000000000000..8631b1b7c725cbde7527356497637d4522402d77
--- /dev/null
+++ b/contrib/apparmor/gnunet-helper-vpn
@@ -0,0 +1,18 @@
+# Last Modified: Mon Jul 27 11:06:22 2015
+#include <tunables/global>
+#include <tunables/gnunet> 
+
+profile @{GNUNET_PREFIX}/lib/gnunet/libexec/gnunet-helper-vpn {
+  #include <abstractions/gnunet-suid>
+
+  #Capability
+  capability net_admin,
+  capability setuid,
+
+  /dev/net/tun rw,
+
+  @{GNUNET_PREFIX}/lib/gnunet/libexec/gnunet-helper-vpn mr,
+  
+  # Site-specific additions and overrides. See local/README for details.
+  #include <local/gnunet>
+}
diff --git a/contrib/apparmor/gnunet-identity b/contrib/apparmor/gnunet-identity
new file mode 100644
index 0000000000000000000000000000000000000000..3aa76cc6ec70d281be10c8ec6a96856c8be87d4e
--- /dev/null
+++ b/contrib/apparmor/gnunet-identity
@@ -0,0 +1,15 @@
+# Last Modified: Fri Aug  7 17:48:29 2015
+#include <tunables/global>
+#include <tunables/gnunet>
+
+profile @{GNUNET_PREFIX}/bin/gnunet-identity {
+  #include <abstractions/base>
+  #include <abstractions/gnunet-common>
+
+  @{HOME}/.local/share/gnunet/identity/egos/* rw,
+
+  @{GNUNET_PREFIX}/bin/gnunet-identity mr,
+
+  # Site-specific additions and overrides. See local/README for details.
+  #include <local/gnunet>
+}
diff --git a/contrib/apparmor/gnunet-identity-gtk b/contrib/apparmor/gnunet-identity-gtk
new file mode 100644
index 0000000000000000000000000000000000000000..e7abb87950365211055dc5776a50e0cfbead8815
--- /dev/null
+++ b/contrib/apparmor/gnunet-identity-gtk
@@ -0,0 +1,16 @@
+# Last Modified: Wed Aug  5 11:24:55 2015
+#include <tunables/global>
+#include <tunables/gnunet>
+
+profile @{GNUNET_PREFIX}/bin/gnunet-identity-gtk {
+  #include <abstractions/gnome>
+  #include <abstractions/gnunet-gtk>
+  #include <abstractions/kde>
+
+  @{GNUNET_PREFIX}/bin/gnunet-identity-gtk mr,
+
+  @{GNUNET_PREFIX}/share/gnunet-gtk/gnunet_identity_gtk_main_window.glade r,
+  
+  # Site-specific additions and overrides. See local/README for details.
+  #include <local/gnunet>
+}
diff --git a/contrib/apparmor/gnunet-namecache b/contrib/apparmor/gnunet-namecache
new file mode 100644
index 0000000000000000000000000000000000000000..f7eca409149b7ba94b30867612014bd5140825ee
--- /dev/null
+++ b/contrib/apparmor/gnunet-namecache
@@ -0,0 +1,13 @@
+# Last Modified: Fri Aug  7 18:07:23 2015
+#include <tunables/global>
+#include <tunables/gnunet>
+
+profile @{GNUNET_PREFIX}/bin/gnunet-namecache {
+  #include <abstractions/base>
+  #include <abstractions/gnunet-common>
+
+  @{GNUNET_PREFIX}/bin/gnunet-namecache mr,
+
+  # Site-specific additions and overrides. See local/README for details.
+  #include <local/gnunet>
+}
diff --git a/contrib/apparmor/gnunet-namestore b/contrib/apparmor/gnunet-namestore
new file mode 100644
index 0000000000000000000000000000000000000000..c97fad77d889c66be87a09d56aae4037f30812b5
--- /dev/null
+++ b/contrib/apparmor/gnunet-namestore
@@ -0,0 +1,21 @@
+# Last Modified: Mon Aug 10 11:05:21 2015
+#include <tunables/global>
+#include <tunables/gnunet>
+
+profile @{GNUNET_PREFIX}/bin/gnunet-namestore {
+  #include <abstractions/base>
+  #include <abstractions/gnunet-common>
+
+  @{GNUNET_PREFIX}/bin/gnunet-namestore mr,
+
+  #GNUnet plugin
+# @{GNUNET_PREFIX}/lib/gnunet/libgnunet_plugin_gnsrecord_conversation.la r,
+  @{GNUNET_PREFIX}/lib/gnunet/libgnunet_plugin_gnsrecord_conversation.so mr,
+# @{GNUNET_PREFIX}/lib/gnunet/libgnunet_plugin_gnsrecord_dns.la r,
+  @{GNUNET_PREFIX}/lib/gnunet/libgnunet_plugin_gnsrecord_dns.so mr,
+# @{GNUNET_PREFIX}/lib/gnunet/libgnunet_plugin_gnsrecord_gns.la r,
+  @{GNUNET_PREFIX}/lib/gnunet/libgnunet_plugin_gnsrecord_gns.so mr,
+
+  # Site-specific additions and overrides. See local/README for details.
+  #include <local/gnunet>
+}
diff --git a/contrib/apparmor/gnunet-namestore-fcfsd b/contrib/apparmor/gnunet-namestore-fcfsd
new file mode 100644
index 0000000000000000000000000000000000000000..8ac09e69b314a7672145716ab6a6ec8f92cea184
--- /dev/null
+++ b/contrib/apparmor/gnunet-namestore-fcfsd
@@ -0,0 +1,13 @@
+# Last Modified: Tue Jul 21 17:25:12 2015
+#include <tunables/global>
+#include <tunables/gnunet>
+
+profile @{GNUNET_PREFIX}/lib/gnunet/libexec/gnunet-namestore-fcfsd {
+  #include <abstractions/base>
+  #include <abstractions/gnunet-common>
+
+  @{GNUNET_PREFIX}/lib/gnunet/libexec/gnunet-namestore-fcfsd mr,
+  
+  # Site-specific additions and overrides. See local/README for details.
+  #include <local/gnunet>
+}
diff --git a/contrib/apparmor/gnunet-namestore-gtk b/contrib/apparmor/gnunet-namestore-gtk
new file mode 100644
index 0000000000000000000000000000000000000000..fb3256ca95fbdc8d5df3874ffeab972338f335ae
--- /dev/null
+++ b/contrib/apparmor/gnunet-namestore-gtk
@@ -0,0 +1,27 @@
+# Last Modified: Wed Aug  5 11:24:52 2015
+#include <tunables/global>
+#include <tunables/gnunet>
+
+profile @{GNUNET_PREFIX}/bin/gnunet-namestore-gtk {
+  #include <abstractions/gnome>
+  #include <abstractions/gnunet-gtk>
+  #include <abstractions/kde>
+
+  @{GNUNET_PREFIX}/bin/gnunet-namestore-gtk mr,
+
+  @{GNUNET_PREFIX}/lib/gnunet/ r,
+
+  #GNUnet plugin
+# @{GNUNET_PREFIX}/lib/gnunet/libgnunet_plugin_gnsrecord_conversation.la r,
+  @{GNUNET_PREFIX}/lib/gnunet/libgnunet_plugin_gnsrecord_conversation.so mr,
+# @{GNUNET_PREFIX}/lib/gnunet/libgnunet_plugin_gnsrecord_dns.la r,
+  @{GNUNET_PREFIX}/lib/gnunet/libgnunet_plugin_gnsrecord_dns.so mr,
+# @{GNUNET_PREFIX}/lib/gnunet/libgnunet_plugin_gnsrecord_gns.la r,
+  @{GNUNET_PREFIX}/lib/gnunet/libgnunet_plugin_gnsrecord_gns.so mr,
+
+  @{GNUNET_PREFIX}/share/gnunet-gtk/gnunet_namestore_gtk_main_window.glade r,
+  @{GNUNET_PREFIX}/share/gnunet-gtk/qr_dummy.png r,
+  
+  # Site-specific additions and overrides. See local/README for details.
+  #include <local/gnunet>
+}
diff --git a/contrib/apparmor/gnunet-nat-server b/contrib/apparmor/gnunet-nat-server
new file mode 100644
index 0000000000000000000000000000000000000000..9884383a2a8715d8bf0cc984d27a32a6ab751459
--- /dev/null
+++ b/contrib/apparmor/gnunet-nat-server
@@ -0,0 +1,13 @@
+# Last Modified: Mon Aug 10 11:34:29 2015
+#include <tunables/global>
+#include <tunables/gnunet>
+
+profile @{GNUNET_PREFIX}/bin/gnunet-nat-server {
+  #include <abstractions/base>
+  #include <abstractions/gnunet-common>
+
+  @{GNUNET_PREFIX}/bin/gnunet-nat-server mr,
+
+  # Site-specific additions and overrides. See local/README for details.
+  #include <local/gnunet>
+}
diff --git a/contrib/apparmor/gnunet-nse b/contrib/apparmor/gnunet-nse
new file mode 100644
index 0000000000000000000000000000000000000000..74c0d9420d4c16c1c6aa2d6280f9a9140b9c8825
--- /dev/null
+++ b/contrib/apparmor/gnunet-nse
@@ -0,0 +1,13 @@
+# Last Modified: Mon Aug 10 11:38:47 2015
+#include <tunables/global>
+#include <tunables/gnunet>
+
+profile @{GNUNET_PREFIX}/bin/gnunet-nse {
+  #include <abstractions/base>
+  #include <abstractions/gnunet-common>
+
+  @{GNUNET_PREFIX}/bin/gnunet-nse mr,
+
+  # Site-specific additions and overrides. See local/README for details.
+  #include <local/gnunet>
+}
diff --git a/contrib/apparmor/gnunet-peerinfo b/contrib/apparmor/gnunet-peerinfo
new file mode 100644
index 0000000000000000000000000000000000000000..0c30d38af26070c40304d791c1164335ea4f1209
--- /dev/null
+++ b/contrib/apparmor/gnunet-peerinfo
@@ -0,0 +1,19 @@
+# Last Modified: Mon Aug 10 11:46:50 2015
+#include <tunables/global>
+#include <tunables/gnunet>
+
+profile @{GNUNET_PREFIX}/bin/gnunet-peerinfo {
+  #include <abstractions/base>
+  #include <abstractions/gnunet-common>
+
+  @{GNUNET_PREFIX}/bin/gnunet-peerinfo mr,
+
+  #GNUnet plugin
+# @{GNUNET_PREFIX}/lib/gnunet/libgnunet_plugin_transport_tcp.la r,
+  @{GNUNET_PREFIX}/lib/gnunet/libgnunet_plugin_transport_tcp.so mr,
+# @{GNUNET_PREFIX}/lib/gnunet/libgnunet_plugin_transport_udp.la r,
+  @{GNUNET_PREFIX}/lib/gnunet/libgnunet_plugin_transport_udp.so mr,
+
+  # Site-specific additions and overrides. See local/README for details.
+  #include <local/gnunet>
+}
diff --git a/contrib/apparmor/gnunet-peerinfo-gtk b/contrib/apparmor/gnunet-peerinfo-gtk
new file mode 100644
index 0000000000000000000000000000000000000000..e1e0271d89b9b5f0e27174c37e314798a69a9148
--- /dev/null
+++ b/contrib/apparmor/gnunet-peerinfo-gtk
@@ -0,0 +1,17 @@
+# Last Modified: Tue Aug 11 16:20:57 2015
+#include <tunables/global>
+#include <tunables/gnunet>
+
+profile @{GNUNET_PREFIX}/bin/gnunet-peerinfo-gtk {
+  #include <abstractions/gnome>
+  #include <abstractions/gnunet-gtk>
+  #include <abstractions/kde>
+
+  @{GNUNET_PREFIX}/bin/gnunet-peerinfo-gtk mr,
+
+  @{GNUNET_PREFIX}/share/gnunet-gtk/* r,
+  @{GNUNET_PREFIX}/share/gnunet-gtk/flags/*.png r,
+
+  # Site-specific additions and overrides. See local/README for details.
+  #include <local/gnunet>
+}
diff --git a/contrib/apparmor/gnunet-peerstore b/contrib/apparmor/gnunet-peerstore
new file mode 100644
index 0000000000000000000000000000000000000000..944f1bed263c7389b7b398552e84d94effcd7c6a
--- /dev/null
+++ b/contrib/apparmor/gnunet-peerstore
@@ -0,0 +1,13 @@
+# Last Modified: Mon Aug 10 12:03:53 2015
+#include <tunables/global>
+#include <tunables/gnunet>
+
+profile @{GNUNET_PREFIX}/bin/gnunet-peerstore {
+  #include <abstractions/base>
+  #include <abstractions/gnunet-common>
+
+  @{GNUNET_PREFIX}/bin/gnunet-peerstore mr,
+
+  # Site-specific additions and overrides. See local/README for details.
+  #include <local/gnunet>
+}
diff --git a/contrib/apparmor/gnunet-publish b/contrib/apparmor/gnunet-publish
new file mode 100644
index 0000000000000000000000000000000000000000..105ff18618c03214c670143968f64bb9e7995e1c
--- /dev/null
+++ b/contrib/apparmor/gnunet-publish
@@ -0,0 +1,16 @@
+# Last Modified: Thu Aug  6 12:00:00 2015
+#include <tunables/global>
+#include <tunables/gnunet>
+
+profile @{GNUNET_PREFIX}/bin/gnunet-publish {
+  #include <abstractions/base>
+  #include <abstractions/gnunet-common>
+  #include <abstractions/user-download>
+
+  @{GNUNET_PREFIX}/bin/gnunet-publish mr,
+
+  @{GNUNET_PREFIX}/lib/gnunet/libexec/gnunet-helper-fs-publish Px,
+  
+  # Site-specific additions and overrides. See local/README for details.
+  #include <local/gnunet>
+}
diff --git a/contrib/apparmor/gnunet-qr b/contrib/apparmor/gnunet-qr
new file mode 100644
index 0000000000000000000000000000000000000000..b893faf98690f39caf4727bb1e01987dbd836c5d
--- /dev/null
+++ b/contrib/apparmor/gnunet-qr
@@ -0,0 +1,15 @@
+# Last Modified: Tue Aug 11 16:14:05 2015
+#include <tunables/global>
+#include <tunables/gnunet>
+
+profile @{GNUNET_PREFIX}/bin/gnunet-qr {
+  #include <abstractions/base>
+  #include <abstractions/python>
+  #include <abstractions/gnunet-common>
+
+  /usr/bin/python3.4 ix,
+  @{GNUNET_PREFIX}/bin/gnunet-qr r,
+
+  # Site-specific additions and overrides. See local/README for details.
+  #include <local/gnunet>
+}
diff --git a/contrib/apparmor/gnunet-resolver b/contrib/apparmor/gnunet-resolver
new file mode 100644
index 0000000000000000000000000000000000000000..e5455b257b5b89f350074fc335309e7aea2a712c
--- /dev/null
+++ b/contrib/apparmor/gnunet-resolver
@@ -0,0 +1,13 @@
+# Last Modified: Mon Aug 10 12:21:50 2015
+#include <tunables/global>
+#include <tunables/gnunet>
+
+profile @{GNUNET_PREFIX}/bin/gnunet-resolver {
+  #include <abstractions/base>
+  #include <abstractions/gnunet-common>
+
+  @{GNUNET_PREFIX}/bin/gnunet-resolver mr,
+
+  # Site-specific additions and overrides. See local/README for details.
+  #include <local/gnunet>
+}
diff --git a/contrib/apparmor/gnunet-revocation b/contrib/apparmor/gnunet-revocation
new file mode 100644
index 0000000000000000000000000000000000000000..8cab61f4f3b7a1f4ee559085639bfb7efa12f3fc
--- /dev/null
+++ b/contrib/apparmor/gnunet-revocation
@@ -0,0 +1,13 @@
+# Last Modified: Mon Aug 10 15:03:13 2015
+#include <tunables/global>
+#include <tunables/gnunet>
+
+profile @{GNUNET_PREFIX}/bin/gnunet-revocation {
+  #include <abstractions/base>
+  #include <abstractions/gnunet-common>
+
+  @{GNUNET_PREFIX}/bin/gnunet-revocation mr,
+
+  # Site-specific additions and overrides. See local/README for details.
+  #include <local/gnunet>
+}
diff --git a/contrib/apparmor/gnunet-scalarproduct b/contrib/apparmor/gnunet-scalarproduct
new file mode 100644
index 0000000000000000000000000000000000000000..acf564a8cb0ab7c2ac8f2bb7141c7a242ab251d8
--- /dev/null
+++ b/contrib/apparmor/gnunet-scalarproduct
@@ -0,0 +1,13 @@
+# Last Modified: Mon Aug 10 15:13:42 2015
+#include <tunables/global>
+#include <tunables/gnunet>
+
+profile @{GNUNET_PREFIX}/bin/gnunet-scalarproduct {
+  #include <abstractions/base>
+  #include <abstractions/gnunet-common>
+
+  @{GNUNET_PREFIX}/bin/gnunet-scalarproduct mr,
+
+  # Site-specific additions and overrides. See local/README for details.
+  #include <local/gnunet>
+}
diff --git a/contrib/apparmor/gnunet-scrypt b/contrib/apparmor/gnunet-scrypt
new file mode 100644
index 0000000000000000000000000000000000000000..a184bf0a371e2b3a57bd9e5c2edbb07c68a8f4ee
--- /dev/null
+++ b/contrib/apparmor/gnunet-scrypt
@@ -0,0 +1,19 @@
+# Last Modified: Mon Aug 10 15:36:34 2015
+#include <tunables/global>
+#include <tunables/gnunet>
+
+profile @{GNUNET_PREFIX}/bin/gnunet-scrypt {
+  #include <abstractions/base>
+  #include <abstractions/gnunet-common>
+
+  @{HOME}/.local/share/gnunet/nse/proof.dat rw,
+  @{HOME}/.local/share/gnunet/private_key.ecc rk,
+
+  @{GNUNET_PREFIX}/bin/gnunet-scrypt mr,
+
+  @{GNUNET_USER}/.local/share/gnunet/nse/proof.dat rw,
+  @{GNUNET_USER}/.local/share/gnunet/private_key.ecc rk,
+
+  # Site-specific additions and overrides. See local/README for details.
+  #include <local/gnunet>
+}
diff --git a/contrib/apparmor/gnunet-search b/contrib/apparmor/gnunet-search
new file mode 100644
index 0000000000000000000000000000000000000000..b23f91e5532eb9fa4793c57cd414e69ee1985a59
--- /dev/null
+++ b/contrib/apparmor/gnunet-search
@@ -0,0 +1,13 @@
+# Last Modified: Mon Aug 10 15:59:45 2015
+#include <tunables/global>
+#include <tunables/gnunet>
+
+profile @{GNUNET_PREFIX}/bin/gnunet-search {
+  #include <abstractions/base>
+  #include <abstractions/gnunet-common>
+
+  @{GNUNET_PREFIX}/bin/gnunet-search mr,
+
+  # Site-specific additions and overrides. See local/README for details.
+  #include <local/gnunet>
+}
diff --git a/contrib/apparmor/gnunet-service-arm b/contrib/apparmor/gnunet-service-arm
new file mode 100644
index 0000000000000000000000000000000000000000..546e6332e8110fb455a1e44da77e8e237b6ae4e4
--- /dev/null
+++ b/contrib/apparmor/gnunet-service-arm
@@ -0,0 +1,42 @@
+# Last Modified: Thu Jul  9 10:27:23 2015
+#include <tunables/global>
+#include <tunables/gnunet>
+
+profile @{GNUNET_PREFIX}/lib/gnunet/libexec/gnunet-service-arm {
+  #include <abstractions/base>
+  #include <abstractions/gnunet-common> 
+
+  /tmp/gnunet-*-runtime/ rw,
+# /tmp/gnunet-*-runtime/gnunet-service-arm.sock rw,
+# /tmp/gnunet-*-runtime/gnunet-service-namestore.sock r,
+# /tmp/gnunet-*-runtime/gnunet-service-identity.sock r,
+# /tmp/gnunet-*-runtime/gnunet-service-gns.sock r,
+  
+  /tmp/gnunet-*-runtime/gnunet-service-*.sock rw,
+
+  @{GNUNET_PREFIX}/lib/gnunet/libexec/gnunet-service-arm mr,
+
+  @{GNUNET_PREFIX}/lib/gnunet/ r,
+
+  @{GNUNET_PREFIX}/lib/gnunet/libexec/ r,
+
+  #GNUnet daemon
+  @{GNUNET_PREFIX}/lib/gnunet/libexec/gnunet-daemon-exit Px,
+  @{GNUNET_PREFIX}/lib/gnunet/libexec/gnunet-daemon-hostlist Px,
+  @{GNUNET_PREFIX}/lib/gnunet/libexec/gnunet-daemon-latency-logger Px,
+  @{GNUNET_PREFIX}/lib/gnunet/libexec/gnunet-daemon-testbed-underlay Px,
+  @{GNUNET_PREFIX}/lib/gnunet/libexec/gnunet-daemon-topology Px,
+  @{GNUNET_PREFIX}/lib/gnunet/libexec/gnunet-daemon-pt Px,
+
+  @{GNUNET_PREFIX}/lib/gnunet/libexec/gnunet-dns2gns Px,
+
+  @{GNUNET_PREFIX}/lib/gnunet/libexec/gnunet-gns-proxy Px,
+
+  @{GNUNET_PREFIX}/lib/gnunet/libexec/gnunet-namestore-fcfsd Px,
+
+  #GNUnet service
+  @{GNUNET_PREFIX}/lib/gnunet/libexec/gnunet-service-* Px,
+  
+  # Site-specific additions and overrides. See local/README for details.
+  #include <local/gnunet>
+}
diff --git a/contrib/apparmor/gnunet-service-ats b/contrib/apparmor/gnunet-service-ats
new file mode 100644
index 0000000000000000000000000000000000000000..8e6b35295237d305bdcea9cfefb3ed08a5aa9925
--- /dev/null
+++ b/contrib/apparmor/gnunet-service-ats
@@ -0,0 +1,18 @@
+# Last Modified: Wed Jul  8 10:49:34 2015
+#include <tunables/global>
+#include <tunables/gnunet>
+
+profile @{GNUNET_PREFIX}/lib/gnunet/libexec/gnunet-service-ats {
+  #include <abstractions/base>
+  #include <abstractions/gnunet-common>
+
+  @{GNUNET_PREFIX}/lib/gnunet/libexec/gnunet-service-ats mr,
+  
+  #Gnunet plugin
+# @{GNUNET_PREFIX}/lib/gnunet/libgnunet_plugin_ats_proportional.la r,
+  @{GNUNET_PREFIX}/lib/gnunet/libgnunet_plugin_ats_proportional.so mr,
+  
+  # Site-specific additions and overrides. See local/README for details.
+  #include <local/gnunet>
+
+}
diff --git a/contrib/apparmor/gnunet-service-cadet b/contrib/apparmor/gnunet-service-cadet
new file mode 100644
index 0000000000000000000000000000000000000000..056ce49fa2d75e6a4639fdf0ce4a78f33030b412
--- /dev/null
+++ b/contrib/apparmor/gnunet-service-cadet
@@ -0,0 +1,17 @@
+# Last Modified: Mon Jul 27 11:09:34 2015
+#include <tunables/global>
+#include <tunables/gnunet>
+
+profile @{GNUNET_PREFIX}/lib/gnunet/libexec/gnunet-service-cadet {
+  #include <abstractions/base>
+  #include <abstractions/gnunet-common>
+
+  /tmp/gnunet-system-runtime/gnunet-service-cadet.sock rw,
+
+  @{GNUNET_PREFIX}/lib/gnunet/libexec/gnunet-service-cadet mr,
+
+  @{GNUNET_USER}/.local/share/gnunet/private_key.ecc rk,
+  
+  # Site-specific additions and overrides. See local/README for details.
+  #include <local/gnunet>
+}
diff --git a/contrib/apparmor/gnunet-service-conversation b/contrib/apparmor/gnunet-service-conversation
new file mode 100644
index 0000000000000000000000000000000000000000..74033276815a3c78d990a83e9bd7ea7c710cf340
--- /dev/null
+++ b/contrib/apparmor/gnunet-service-conversation
@@ -0,0 +1,19 @@
+# Last Modified: Tue Jul 21 16:53:39 2015
+#include <tunables/global>
+#include <tunables/gnunet>
+
+profile @{GNUNET_PREFIX}/lib/gnunet/libexec/gnunet-service-conversation {
+  #include <abstractions/base>
+  #include <abstractions/gnunet-common>
+
+  @{GNUNET_PREFIX}/lib/gnunet/libexec/gnunet-service-conversation mr,
+
+  #GNUnet helper
+  @{GNUNET_PREFIX}/lib/gnunet/libexec/gnunet-helper-audio-playback Px,
+  @{GNUNET_PREFIX}/lib/gnunet/libexec/gnunet-helper-audio-record   Px,
+
+  @{GNUNET_USER}/.local/share/gnunet/private_key.ecc rk,
+  
+  # Site-specific additions and overrides. See local/README for details.
+  #include <local/gnunet>
+}
diff --git a/contrib/apparmor/gnunet-service-core b/contrib/apparmor/gnunet-service-core
new file mode 100644
index 0000000000000000000000000000000000000000..4d9b28353ea8158b6809b64f579dca604fa7b657
--- /dev/null
+++ b/contrib/apparmor/gnunet-service-core
@@ -0,0 +1,15 @@
+# Last Modified: Thu Jul  9 10:16:30 2015
+#include <tunables/global>
+#include <tunables/gnunet>
+
+profile @{GNUNET_PREFIX}/lib/gnunet/libexec/gnunet-service-core {
+  #include <abstractions/base>
+  #include <abstractions/gnunet-common>
+
+  @{GNUNET_USER}/.local/share/gnunet/private_key.ecc rk,
+
+  @{GNUNET_PREFIX}/lib/gnunet/libexec/gnunet-service-core mr,
+  
+  # Site-specific additions and overrides. See local/README for details.
+  #include <local/gnunet>
+}
diff --git a/contrib/apparmor/gnunet-service-datastore b/contrib/apparmor/gnunet-service-datastore
new file mode 100644
index 0000000000000000000000000000000000000000..236c5b7f4c4d7cc4032fe5ecaea29e06418da609
--- /dev/null
+++ b/contrib/apparmor/gnunet-service-datastore
@@ -0,0 +1,22 @@
+# Last Modified: Thu Jul  9 10:16:30 2015
+#include <tunables/global>
+#include <tunables/gnunet>
+
+profile @{GNUNET_PREFIX}/lib/gnunet/libexec/gnunet-service-datastore {
+  #include <abstractions/base>
+  #include <abstractions/gnunet-common>
+  #include <abstractions/gnunet-db>
+  
+  @{GNUNET_USER}/.local/share/gnunet/datastore/bloomfilter.* rw,
+  @{GNUNET_USER}/.local/share/gnunet/datastore/*.db rwk,
+  @{GNUNET_USER}/.local/share/gnunet/datastore/*.db-journal rw,
+
+  @{GNUNET_PREFIX}/lib/gnunet/libexec/gnunet-service-datastore mr,
+
+  #Gnunet plugin
+# @{GNUNET_PREFIX}/lib/gnunet/libgnunet_plugin_datastore_*.la r,
+  @{GNUNET_PREFIX}/lib/gnunet/libgnunet_plugin_datastore_*.so mr,
+  
+  # Site-specific additions and overrides. See local/README for details.
+  #include <local/gnunet>
+}
diff --git a/contrib/apparmor/gnunet-service-dht b/contrib/apparmor/gnunet-service-dht
new file mode 100644
index 0000000000000000000000000000000000000000..1d092244191d6c7143cc7f21d9fa175404e9b293
--- /dev/null
+++ b/contrib/apparmor/gnunet-service-dht
@@ -0,0 +1,36 @@
+# Last Modified: Fri Jul  3 17:37:39 2015
+#include <tunables/global>
+#include <tunables/gnunet>
+
+profile @{GNUNET_PREFIX}/lib/gnunet/libexec/gnunet-service-dht {
+  #include <abstractions/base>
+  #include <abstractions/gnunet-common>
+
+  @{GNUNET_PREFIX}/lib/gnunet/libexec/gnunet-service-dht mr,
+ 
+  #Gnunet plugin
+  @{GNUNET_PREFIX}/lib/gnunet/ r,
+# @{GNUNET_PREFIX}/lib/gnunet/libgnunet_plugin_block_template.la r,
+  @{GNUNET_PREFIX}/lib/gnunet/libgnunet_plugin_block_template.so mr,
+# @{GNUNET_PREFIX}/lib/gnunet/libgnunet_plugin_block_dns.la r,
+  @{GNUNET_PREFIX}/lib/gnunet/libgnunet_plugin_block_dns.so mr,
+# @{GNUNET_PREFIX}/lib/gnunet/libgnunet_plugin_block_fs.la r,
+  @{GNUNET_PREFIX}/lib/gnunet/libgnunet_plugin_block_fs.so mr,
+# @{GNUNET_PREFIX}/lib/gnunet/libgnunet_plugin_block_regex.la r,
+  @{GNUNET_PREFIX}/lib/gnunet/libgnunet_plugin_block_regex.so mr,
+# @{GNUNET_PREFIX}/lib/gnunet/libgnunet_plugin_block_dht.la r,
+  @{GNUNET_PREFIX}/lib/gnunet/libgnunet_plugin_block_dht.so mr,
+# @{GNUNET_PREFIX}/lib/gnunet/libgnunet_plugin_block_test.la r,
+  @{GNUNET_PREFIX}/lib/gnunet/libgnunet_plugin_block_test.so mr,
+# @{GNUNET_PREFIX}/lib/gnunet/libgnunet_plugin_block_gns.la r,
+  @{GNUNET_PREFIX}/lib/gnunet/libgnunet_plugin_block_gns.so mr,
+# @{GNUNET_PREFIX}/lib/gnunet/libgnunet_plugin_datacache_heap.la r,
+  @{GNUNET_PREFIX}/lib/gnunet/libgnunet_plugin_datacache_heap.so mr,
+
+  /tmp/gnunet-system-runtime/gnunet-service-dht.sock w,
+  
+  /tmp/gnunet-datacachebloom* rw,
+  
+  # Site-specific additions and overrides. See local/README for details.
+  #include <local/gnunet>
+}
diff --git a/contrib/apparmor/gnunet-service-dns b/contrib/apparmor/gnunet-service-dns
new file mode 100644
index 0000000000000000000000000000000000000000..394b97eb1bd735e286485cdac853d6bdc1dae025
--- /dev/null
+++ b/contrib/apparmor/gnunet-service-dns
@@ -0,0 +1,24 @@
+# Last Modified: Mon Jul 27 15:18:30 2015
+#include <tunables/global>
+#include <tunables/gnunet>
+
+profile @{GNUNET_PREFIX}/lib/gnunet/libexec/gnunet-service-dns {
+  #include <abstractions/gnunet-sgid>
+
+  capability setgid,
+
+  /usr/lib/ld-*.so r,
+
+  #GNUnet helper
+  @{GNUNET_PREFIX}/lib/gnunet/libexec/gnunet-helper-dns Px,
+
+  @{GNUNET_PREFIX}/lib/gnunet/libexec/gnunet-service-dns mr,
+
+  #Gnunet librairies
+  @{GNUNET_PREFIX}/lib/libgnunetdnsstub.so.* mr,
+  @{GNUNET_PREFIX}/lib/libgnunetstatistics.so.* mr,
+  @{GNUNET_PREFIX}/lib/libgnunettun.so.* mr,
+  
+  # Site-specific additions and overrides. See local/README for details.
+  #include <local/gnunet-sgid>
+}
diff --git a/contrib/apparmor/gnunet-service-fs b/contrib/apparmor/gnunet-service-fs
new file mode 100644
index 0000000000000000000000000000000000000000..70de39c2e1f1a8440379fa5d37989fc48161df62
--- /dev/null
+++ b/contrib/apparmor/gnunet-service-fs
@@ -0,0 +1,37 @@
+# Last Modified: Wed Jul  8 10:52:48 2015
+
+#include <tunables/global>
+#include <tunables/gnunet>
+
+profile @{GNUNET_PREFIX}/lib/gnunet/libexec/gnunet-service-fs {
+  #include <abstractions/base>
+  #include <abstractions/gnunet-common>
+
+  /tmp/gnunet-system-runtime/gnunet-service-fs.sock w,
+
+  @{GNUNET_USER}/.local/share/gnunet/private_key.ecc rk,
+
+  owner @{HOME}/.local/share/gnunet/fs/idxinfo.lst r,
+
+  @{GNUNET_PREFIX}/lib/gnunet/libexec/gnunet-service-fs mr,
+
+  #Gnunet plugin
+  @{GNUNET_PREFIX}/lib/gnunet/ r,
+# @{GNUNET_PREFIX}/lib/gnunet/libgnunet_plugin_block_dht.la r,
+  @{GNUNET_PREFIX}/lib/gnunet/libgnunet_plugin_block_dht.so mr,
+# @{GNUNET_PREFIX}/lib/gnunet/libgnunet_plugin_block_dns.la r,
+  @{GNUNET_PREFIX}/lib/gnunet/libgnunet_plugin_block_dns.so mr,
+# @{GNUNET_PREFIX}/lib/gnunet/libgnunet_plugin_block_fs.la r,
+  @{GNUNET_PREFIX}/lib/gnunet/libgnunet_plugin_block_fs.so mr,
+# @{GNUNET_PREFIX}/lib/gnunet/libgnunet_plugin_block_gns.la r,
+  @{GNUNET_PREFIX}/lib/gnunet/libgnunet_plugin_block_gns.so mr,
+# @{GNUNET_PREFIX}/lib/gnunet/libgnunet_plugin_block_regex.la r,
+  @{GNUNET_PREFIX}/lib/gnunet/libgnunet_plugin_block_regex.so mr,
+# @{GNUNET_PREFIX}/lib/gnunet/libgnunet_plugin_block_template.la r,
+  @{GNUNET_PREFIX}/lib/gnunet/libgnunet_plugin_block_template.so mr,
+# @{GNUNET_PREFIX}/lib/gnunet/libgnunet_plugin_block_test.la r,
+  @{GNUNET_PREFIX}/lib/gnunet/libgnunet_plugin_block_test.so mr,
+  
+  # Site-specific additions and overrides. See local/README for details.
+  #include <local/gnunet>
+}
diff --git a/contrib/apparmor/gnunet-service-gns b/contrib/apparmor/gnunet-service-gns
new file mode 100644
index 0000000000000000000000000000000000000000..25184e50dbbc812932c4473347e9ac2702f87f0f
--- /dev/null
+++ b/contrib/apparmor/gnunet-service-gns
@@ -0,0 +1,18 @@
+# Last Modified: Wed Jul  8 15:17:46 2015
+
+#include <tunables/global>
+#include <tunables/gnunet>
+
+profile @{GNUNET_PREFIX}/lib/gnunet/libexec/gnunet-service-gns {
+  #include <abstractions/base>
+  #include <abstractions/gnunet-common>
+
+  /tmp/gnunet-*-runtime/gnunet-service-gns.sock rw,
+
+  @{HOME}/.config/gnunet.conf r,
+
+  @{GNUNET_PREFIX}/lib/gnunet/libexec/gnunet-service-gns mr,
+  
+  # Site-specific additions and overrides. See local/README for details.
+  #include <local/gnunet>
+}
diff --git a/contrib/apparmor/gnunet-service-identity b/contrib/apparmor/gnunet-service-identity
new file mode 100644
index 0000000000000000000000000000000000000000..3e0a6bb60586b122e6545859fd10455e2d8b320b
--- /dev/null
+++ b/contrib/apparmor/gnunet-service-identity
@@ -0,0 +1,26 @@
+# Last Modified: Tue Jul 21 11:51:29 2015
+#include <tunables/global>
+#include <tunables/gnunet>
+
+profile @{GNUNET_PREFIX}/lib/gnunet/libexec/gnunet-service-identity {
+  #include <abstractions/base>
+  #include <abstractions/gnunet-common>
+
+  /tmp/gnunet-*-runtime/ a,
+
+  @{GNUNET_USER}/.local/share/gnunet/identity/ a,
+  @{GNUNET_USER}/.local/share/gnunet/identity/egos/ ra,
+
+  @{GNUNET_PREFIX}/lib/gnunet/libexec/gnunet-service-identity mr,
+
+  @{HOME}/.config/gnunet/identity/subsystem_defaults.conf rw,
+
+  @{HOME}/.local/share/gnunet/identity/egos/ r,
+  @{HOME}/.local/share/gnunet/identity/egos/master-zone rk,
+  @{HOME}/.local/share/gnunet/identity/egos/private-zone rk,
+  @{HOME}/.local/share/gnunet/identity/egos/short-zone rk,
+  @{HOME}/.local/share/gnunet/identity/egos/sks-zone rk,
+  
+  # Site-specific additions and overrides. See local/README for details.
+  #include <local/gnunet>
+}
diff --git a/contrib/apparmor/gnunet-service-mesh b/contrib/apparmor/gnunet-service-mesh
new file mode 100644
index 0000000000000000000000000000000000000000..6b79441103849d90adcd2736c454b1e74509fb1b
--- /dev/null
+++ b/contrib/apparmor/gnunet-service-mesh
@@ -0,0 +1,19 @@
+# Last Modified: Fri Jul  3 17:37:56 2015
+#include <tunables/global>
+#include <tunables/gnunet>
+
+profile @{GNUNET_PREFIX}/lib/gnunet/libexec/gnunet-service-mesh {
+  #include <abstractions/base>
+  #include <abstractions/gnunet-common>
+
+  @{GNUNET_PREFIX}/lib/gnunet/libexec/gnunet-service-mesh mr,
+
+  @{HOME}/.local/share/gnunet/private_key.ecc rk,
+
+  /tmp/gnunet-system-runtime/gnunet-service-mesh.sock w,
+
+  @{GNUNET_USER}/.local/share/gnunet/private_key.ecc rwk,
+  
+  # Site-specific additions and overrides. See local/README for details.
+  #include <local/gnunet>
+}
diff --git a/contrib/apparmor/gnunet-service-namecache b/contrib/apparmor/gnunet-service-namecache
new file mode 100644
index 0000000000000000000000000000000000000000..d40b3e56e5fdf44f661cca621fb28fe2c08732e6
--- /dev/null
+++ b/contrib/apparmor/gnunet-service-namecache
@@ -0,0 +1,23 @@
+# Last Modified: Thu Jul  9 10:01:49 2015
+#include <tunables/global>
+#include <tunables/gnunet>
+
+profile @{GNUNET_PREFIX}/lib/gnunet/libexec/gnunet-service-namecache {
+  #include <abstractions/base>
+  #include <abstractions/gnunet-common>
+  #include <abstractions/gnunet-db>
+
+  @{GNUNET_PREFIX}/lib/gnunet/libexec/gnunet-service-namecache mr,
+
+  #Gnunet plugin
+# @{GNUNET_PREFIX}/lib/gnunet/libgnunet_plugin_namecache_*.la r,
+  @{GNUNET_PREFIX}/lib/gnunet/libgnunet_plugin_namecache_*.so mr,
+
+  @{GNUNET_USER}/.local/share/gnunet/namecache/ r,
+  @{GNUNET_USER}/.local/share/gnunet/namecache/*.db rwk,
+  @{GNUNET_USER}/.local/share/gnunet/namecache/*.db-journal rw,
+  
+  # Site-specific additions and overrides. See local/README for details.
+  #include <local/gnunet>
+}
+
diff --git a/contrib/apparmor/gnunet-service-namestore b/contrib/apparmor/gnunet-service-namestore
new file mode 100644
index 0000000000000000000000000000000000000000..221b2e36f8b5e9db8683f455153892eb93166a2c
--- /dev/null
+++ b/contrib/apparmor/gnunet-service-namestore
@@ -0,0 +1,20 @@
+# Last Modified: Tue Jul  7 10:43:41 2015
+#include <tunables/global>
+#include <tunables/gnunet>
+
+profile @{GNUNET_PREFIX}/lib/gnunet/libexec/gnunet-service-namestore {
+  #include <abstractions/base>
+  #include <abstractions/gnunet-common>
+  #include <abstractions/gnunet-db>
+
+  @{GNUNET_PREFIX}/lib/gnunet/libexec/gnunet-service-namestore mr,
+
+  #Gnunet plugin
+# @{GNUNET_PREFIX}/lib/gnunet/libgnunet_plugin_namestore_*.la r,
+  @{GNUNET_PREFIX}/lib/gnunet/libgnunet_plugin_namestore_*.so mr,
+
+  /tmp/gnunet-*-runtime/ a,
+  
+  # Site-specific additions and overrides. See local/README for details.
+  #include <local/gnunet>
+}
diff --git a/contrib/apparmor/gnunet-service-nse b/contrib/apparmor/gnunet-service-nse
new file mode 100644
index 0000000000000000000000000000000000000000..6b6ecf7575e5ef3d99ed0d7e12c535f83ed00048
--- /dev/null
+++ b/contrib/apparmor/gnunet-service-nse
@@ -0,0 +1,21 @@
+# Last Modified: Fri Jul  3 17:37:49 2015
+#include <tunables/global>
+#include <tunables/gnunet>
+
+profile @{GNUNET_PREFIX}/lib/gnunet/libexec/gnunet-service-nse {
+  #include <abstractions/base>
+  #include <abstractions/gnunet-common>
+
+  @{GNUNET_PREFIX}/lib/gnunet/libexec/gnunet-service-nse mr,
+
+  /tmp/gnunet-system-runtime/gnunet-service-nse.sock rw,
+
+  @{HOME}/.local/share/gnunet/private_key.ecc rk,
+  owner @{HOME}/.local/share/gnunet/nse/proof.dat rw,
+
+  @{GNUNET_USER}/.local/share/gnunet/private_key.ecc rwk,
+  @{GNUNET_USER}/.local/share/gnunet/nse/proof.dat rw,
+  
+  # Site-specific additions and overrides. See local/README for details.
+  #include <local/gnunet>
+}
diff --git a/contrib/apparmor/gnunet-service-peerinfo b/contrib/apparmor/gnunet-service-peerinfo
new file mode 100644
index 0000000000000000000000000000000000000000..4da70eb534a3b8583c7e28180ceee5a2ac34034a
--- /dev/null
+++ b/contrib/apparmor/gnunet-service-peerinfo
@@ -0,0 +1,20 @@
+# Last Modified: Wed Jul  8 17:03:17 2015
+#include <tunables/global>
+#include <tunables/gnunet>
+
+profile @{GNUNET_PREFIX}/lib/gnunet/libexec/gnunet-service-peerinfo {
+  #include <abstractions/base>
+  #include <abstractions/gnunet-common>
+
+  @{GNUNET_PREFIX}/share/gnunet/hellos/ r,
+  @{GNUNET_PREFIX}/share/gnunet/hellos/* r,
+
+  @{GNUNET_USER}/.local/share/gnunet/peerinfo/hosts/ r,
+  @{GNUNET_USER}/.local/share/gnunet/peerinfo/hosts/* rw,
+
+
+  @{GNUNET_PREFIX}/lib/gnunet/libexec/gnunet-service-peerinfo mr,
+  
+  # Site-specific additions and overrides. See local/README for details.
+  #include <local/gnunet>
+}
diff --git a/contrib/apparmor/gnunet-service-peerstore b/contrib/apparmor/gnunet-service-peerstore
new file mode 100644
index 0000000000000000000000000000000000000000..54d178532dea87ca487d4e2df200460aa7f499b1
--- /dev/null
+++ b/contrib/apparmor/gnunet-service-peerstore
@@ -0,0 +1,21 @@
+# Last Modified: Mon Jul 27 11:06:13 2015
+#include <tunables/global>
+#include <tunables/gnunet>
+
+profile @{GNUNET_PREFIX}/lib/gnunet/libexec/gnunet-service-peerstore {
+  #include <abstractions/base>
+  #include <abstractions/gnunet-common>
+  #include <abstractions/gnunet-db>
+
+  @{GNUNET_PREFIX}/lib/gnunet/libexec/gnunet-service-peerstore mr,
+
+  #Gnunet Plugin
+# @{GNUNET_PREFIX}/lib/gnunet/libgnunet_plugin_peerstore_*.la r,
+  @{GNUNET_PREFIX}/lib/gnunet/libgnunet_plugin_peerstore_*.so mr,
+
+  @{GNUNET_USER}/.local/share/gnunet/peerstore/*.db rwk,
+  @{GNUNET_USER}/.local/share/gnunet/peerstore/*.db-journal rw,
+  
+  # Site-specific additions and overrides. See local/README for details.
+  #include <local/gnunet>
+}
diff --git a/contrib/apparmor/gnunet-service-regex b/contrib/apparmor/gnunet-service-regex
new file mode 100644
index 0000000000000000000000000000000000000000..ba7a4f3a59bb0e3f39fe21b4bd84ccc173223520
--- /dev/null
+++ b/contrib/apparmor/gnunet-service-regex
@@ -0,0 +1,15 @@
+# Last Modified: Tue Jul 21 16:59:39 2015
+#include <tunables/global>
+#include <tunables/gnunet>
+
+profile @{GNUNET_PREFIX}/lib/gnunet/libexec/gnunet-service-regex {
+  #include <abstractions/base>
+  #include <abstractions/gnunet-common>
+
+  @{GNUNET_PREFIX}/lib/gnunet/libexec/gnunet-service-regex mr,
+
+  @{GNUNET_USER}/.local/share/gnunet/private_key.ecc rk,
+  
+  # Site-specific additions and overrides. See local/README for details.
+  #include <local/gnunet>
+}
diff --git a/contrib/apparmor/gnunet-service-resolver b/contrib/apparmor/gnunet-service-resolver
new file mode 100644
index 0000000000000000000000000000000000000000..9e2002575b2b19ae40cae088882c41dc493542c3
--- /dev/null
+++ b/contrib/apparmor/gnunet-service-resolver
@@ -0,0 +1,20 @@
+# Last Modified: Thu Jul  9 10:01:36 2015
+#include <tunables/global>
+#include <tunables/gnunet>
+
+profile @{GNUNET_PREFIX}/lib/gnunet/libexec/gnunet-service-resolver {
+  #include <abstractions/base>
+  #include <abstractions/gnunet-common>
+
+  @{GNUNET_PREFIX}/lib/gnunet/libexec/gnunet-service-resolver mr,
+
+  /etc/nsswitch.conf r,
+  /etc/resolv.conf r,
+  /etc/host.conf r,
+  /etc/hosts r,
+
+  /tmp/gnunet-system-runtime/gnunet-service-resolver.sock w,
+  
+  # Site-specific additions and overrides. See local/README for details.
+  #include <local/gnunet>
+}
diff --git a/contrib/apparmor/gnunet-service-revocation b/contrib/apparmor/gnunet-service-revocation
new file mode 100644
index 0000000000000000000000000000000000000000..cd3c59f03dc425b3d5f34b2f9f89875856452a1d
--- /dev/null
+++ b/contrib/apparmor/gnunet-service-revocation
@@ -0,0 +1,19 @@
+# Last Modified: Thu Jul  9 10:16:30 2015
+#include <tunables/global>
+#include <tunables/gnunet>
+
+profile @{GNUNET_PREFIX}/lib/gnunet/libexec/gnunet-service-revocation {
+  #include <abstractions/base>
+  #include <abstractions/gnunet-common>
+  
+  /tmp/gnunet-system-runtime/gnunet-service-revocation.sock rw,
+
+  @{GNUNET_USER}/.local/share/gnunet/revocation.dat rw,
+
+  @{HOME}/.local/share/gnunet/revocation.dat rw,
+
+  @{GNUNET_PREFIX}/lib/gnunet/libexec/gnunet-service-revocation mr,
+  
+  # Site-specific additions and overrides. See local/README for details.
+  #include <local/gnunet>
+}
diff --git a/contrib/apparmor/gnunet-service-scalarproduct-alice b/contrib/apparmor/gnunet-service-scalarproduct-alice
new file mode 100644
index 0000000000000000000000000000000000000000..8801ca8240452b25f3f8fe34adee0b64d4b19036
--- /dev/null
+++ b/contrib/apparmor/gnunet-service-scalarproduct-alice
@@ -0,0 +1,13 @@
+# Last Modified: Mon Jul 27 15:48:05 2015
+#include <tunables/global>
+#include <tunables/gnunet>
+
+profile @{GNUNET_PREFIX}/lib/gnunet/libexec/gnunet-service-scalarproduct-alice {
+  #include <abstractions/base>
+  #include <abstractions/gnunet-common>
+
+  @{GNUNET_PREFIX}/lib/gnunet/libexec/gnunet-service-scalarproduct-alice mr,
+  
+  # Site-specific additions and overrides. See local/README for details.
+  #include <local/gnunet>
+}
diff --git a/contrib/apparmor/gnunet-service-scalarproduct-bob b/contrib/apparmor/gnunet-service-scalarproduct-bob
new file mode 100644
index 0000000000000000000000000000000000000000..72a7e7f84c8fa1771ea05bb7559aaa7eee1a86a4
--- /dev/null
+++ b/contrib/apparmor/gnunet-service-scalarproduct-bob
@@ -0,0 +1,13 @@
+# Last Modified: Mon Jul 27 15:48:05 2015
+#include <tunables/global>
+#include <tunables/gnunet>
+
+profile @{GNUNET_PREFIX}/lib/gnunet/libexec/gnunet-service-scalarproduct-bob {
+  #include <abstractions/base>
+  #include <abstractions/gnunet-common>
+
+  @{GNUNET_PREFIX}/lib/gnunet/libexec/gnunet-service-scalarproduct-bob mr,
+  
+  # Site-specific additions and overrides. See local/README for details.
+  #include <local/gnunet>
+}
diff --git a/contrib/apparmor/gnunet-service-set b/contrib/apparmor/gnunet-service-set
new file mode 100644
index 0000000000000000000000000000000000000000..000884cd65cbc3e9e3cabbd7408cc12890c2eb3a
--- /dev/null
+++ b/contrib/apparmor/gnunet-service-set
@@ -0,0 +1,13 @@
+# Last Modified: Wed Jul  8 10:52:48 2015
+#include <tunables/global>
+#include <tunables/gnunet>
+
+profile @{GNUNET_PREFIX}/lib/gnunet/libexec/gnunet-service-set {
+  #include <abstractions/base>
+  #include <abstractions/gnunet-common>
+
+  @{GNUNET_PREFIX}/lib/gnunet/libexec/gnunet-service-set mr,
+  
+  # Site-specific additions and overrides. See local/README for details.
+  #include <local/gnunet>
+}
diff --git a/contrib/apparmor/gnunet-service-statistics b/contrib/apparmor/gnunet-service-statistics
new file mode 100644
index 0000000000000000000000000000000000000000..e5a8df7c441fa56cf6c2229495a8789b6a19c8fb
--- /dev/null
+++ b/contrib/apparmor/gnunet-service-statistics
@@ -0,0 +1,15 @@
+# Last Modified: Thu Jul  9 10:16:30 2015
+#include <tunables/global>
+#include <tunables/gnunet>
+
+profile @{GNUNET_PREFIX}/lib/gnunet/libexec/gnunet-service-statistics {
+  #include <abstractions/base>
+  #include <abstractions/gnunet-common>
+
+  @{GNUNET_USER}/.local/share/gnunet/statistics.dat rw,
+
+  @{GNUNET_PREFIX}/lib/gnunet/libexec/gnunet-service-statistics mr,
+  
+  # Site-specific additions and overrides. See local/README for details.
+  #include <local/gnunet>
+}
diff --git a/contrib/apparmor/gnunet-service-template b/contrib/apparmor/gnunet-service-template
new file mode 100644
index 0000000000000000000000000000000000000000..4b442239f30d3c6c2058b61095f6fef0cc0a1f3d
--- /dev/null
+++ b/contrib/apparmor/gnunet-service-template
@@ -0,0 +1,16 @@
+# Last Modified: Tue Jul 21 16:06:04 2015
+#include <tunables/global>
+#include <tunables/gnunet>
+
+profile @{GNUNET_PREFIX}/lib/gnunet/libexec/gnunet-service-template {
+  #include <abstractions/base>
+  #include <abstractions/gnunet-common>
+
+  /tmp/gnunet-system-runtime/ w,
+  /tmp/gnunet-system-runtime/gnunet-service-template.sock w,
+
+  @{GNUNET_PREFIX}/lib/gnunet/libexec/gnunet-service-template mr,
+  
+  # Site-specific additions and overrides. See local/README for details.
+  #include <local/gnunet>
+}
diff --git a/contrib/apparmor/gnunet-service-testbed b/contrib/apparmor/gnunet-service-testbed
new file mode 100644
index 0000000000000000000000000000000000000000..24f5c452585a2f68d3866ddd4666b4ff644f05e0
--- /dev/null
+++ b/contrib/apparmor/gnunet-service-testbed
@@ -0,0 +1,29 @@
+# Last Modified: Mon Jul 27 11:02:46 2015
+#include <tunables/global>
+#include <tunables/gnunet>
+
+profile @{GNUNET_PREFIX}/lib/gnunet/libexec/gnunet-service-testbed {
+  #include <abstractions/base>
+  #include <abstractions/gnunet-common>
+  #include <abstractions/gnunet-test>
+
+  /etc/gai.conf r,
+ 
+  /tmp/gnunet-system-runtime/ w,
+  /tmp/gnunet-system-runtime/gnunet-service-testbed-barrier.sock w,
+  /tmp/gnunet-system-runtime/gnunet-service-testbed.sock w,
+
+  @{GNUNET_PREFIX}/lib/gnunet/libexec/gnunet-* r,
+
+  @{GNUNET_PREFIX}/lib/gnunet/libexec/ r,
+  @{GNUNET_PREFIX}/lib/gnunet/libexec/gnunet-service-arm Px,
+  @{GNUNET_PREFIX}/lib/gnunet/libexec/gnunet-service-testbed mr,
+
+  @{GNUNET_PREFIX}/share/gnunet/testing_hostkeys.ecc r,
+  
+  #GNUnet helper
+  @{GNUNET_PREFIX}/lib/gnunet/libexec/gnunet-helper-testbed Px,
+  
+  # Site-specific additions and overrides. See local/README for details.
+  #include <local/gnunet>
+}
diff --git a/contrib/apparmor/gnunet-service-testbed-logger b/contrib/apparmor/gnunet-service-testbed-logger
new file mode 100644
index 0000000000000000000000000000000000000000..0baefb466fcf55956e77e6c0d4d653fe7212481a
--- /dev/null
+++ b/contrib/apparmor/gnunet-service-testbed-logger
@@ -0,0 +1,19 @@
+# Last Modified: Tue Jul 21 17:19:18 2015
+#include <tunables/global>
+#include <tunables/gnunet>
+
+profile @{GNUNET_PREFIX}/lib/gnunet/libexec/gnunet-service-testbed-logger {
+  #include <abstractions/base>
+  #include <abstractions/gnunet-common>
+
+  #???
+  /tmp/archlinux_*.dat w,
+
+  /tmp/gnunet-system-runtime/ w,
+  /tmp/gnunet-system-runtime/gnunet-gnunet-testbed-logger.sock w,
+
+  @{GNUNET_PREFIX}/lib/gnunet/libexec/gnunet-service-testbed-logger mr,
+  
+  # Site-specific additions and overrides. See local/README for details.
+  #include <local/gnunet>
+}
diff --git a/contrib/apparmor/gnunet-service-transport b/contrib/apparmor/gnunet-service-transport
new file mode 100644
index 0000000000000000000000000000000000000000..ab724c153f6f3d20e71fe52f24baf8b9669db6af
--- /dev/null
+++ b/contrib/apparmor/gnunet-service-transport
@@ -0,0 +1,21 @@
+# Last Modified: Thu Jul  9 10:16:30 2015
+#include <tunables/global>
+#include <tunables/gnunet>
+
+profile @{GNUNET_PREFIX}/lib/gnunet/libexec/gnunet-service-transport {
+  #include <abstractions/base>
+  #include <abstractions/gnunet-common>
+
+  @{GNUNET_USER}/.local/share/gnunet/private_key.ecc rk,
+
+  @{GNUNET_PREFIX}/lib/gnunet/libexec/gnunet-service-transport mr,
+
+  #Gnunet plugin
+# @{GNUNET_PREFIX}/lib/gnunet/libgnunet_plugin_transport_tcp.la r,
+  @{GNUNET_PREFIX}/lib/gnunet/libgnunet_plugin_transport_tcp.so mr,
+# @{GNUNET_PREFIX}/lib/gnunet/libgnunet_plugin_transport_udp.la r,
+  @{GNUNET_PREFIX}/lib/gnunet/libgnunet_plugin_transport_udp.so mr,
+  
+  # Site-specific additions and overrides. See local/README for details.
+  #include <local/gnunet>
+}
diff --git a/contrib/apparmor/gnunet-service-vpn b/contrib/apparmor/gnunet-service-vpn
new file mode 100644
index 0000000000000000000000000000000000000000..d17925f1b8bff991e1e449b868c85f84f40c021f
--- /dev/null
+++ b/contrib/apparmor/gnunet-service-vpn
@@ -0,0 +1,17 @@
+# Last Modified: Mon Jul 20 11:20:57 2015
+#include <tunables/global>
+#include <tunables/gnunet>
+
+profile @{GNUNET_PREFIX}/lib/gnunet/libexec/gnunet-service-vpn {
+  #include <abstractions/base>
+  #include <abstractions/gnunet-common>
+
+
+  @{GNUNET_PREFIX}/lib/gnunet/libexec/gnunet-service-vpn mr,
+
+  #Gnunet helper
+  @{GNUNET_PREFIX}/lib/gnunet/libexec/gnunet-helper-vpn Px,
+  
+  # Site-specific additions and overrides. See local/README for details.
+  #include <local/gnunet>
+}
diff --git a/contrib/apparmor/gnunet-set-ibf-profiler b/contrib/apparmor/gnunet-set-ibf-profiler
new file mode 100644
index 0000000000000000000000000000000000000000..71fa986493d220591dcbcd2152d9ade9d96ec292
--- /dev/null
+++ b/contrib/apparmor/gnunet-set-ibf-profiler
@@ -0,0 +1,13 @@
+# Last Modified: Mon Aug 10 18:15:38 2015
+#include <tunables/global>
+#include <tunables/gnunet>
+
+profile @{GNUNET_PREFIX}/bin/gnunet-set-ibf-profiler {
+  #include <abstractions/base>
+  #include <abstractions/gnunet-common>
+
+  @{GNUNET_PREFIX}/bin/gnunet-set-ibf-profiler mr,
+
+  # Site-specific additions and overrides. See local/README for details.
+  #include <local/gnunet>
+}
diff --git a/contrib/apparmor/gnunet-set-profiler b/contrib/apparmor/gnunet-set-profiler
new file mode 100644
index 0000000000000000000000000000000000000000..f72c4a226448e0e3ef3008842075bdccb9554214
--- /dev/null
+++ b/contrib/apparmor/gnunet-set-profiler
@@ -0,0 +1,14 @@
+# Last Modified: Mon Aug 10 18:17:19 2015
+#include <tunables/global>
+#include <tunables/gnunet>
+
+profile @{GNUNET_PREFIX}/bin/gnunet-set-profiler {
+  #include <abstractions/base>
+  #include <abstractions/gnunet-common>
+
+  @{HOME}/.local/share/gnunet/private_key.ecc rk,
+  @{GNUNET_PREFIX}/bin/gnunet-set-profiler mr,
+
+  # Site-specific additions and overrides. See local/README for details.
+  #include <local/gnunet>
+}
diff --git a/contrib/apparmor/gnunet-setup b/contrib/apparmor/gnunet-setup
new file mode 100644
index 0000000000000000000000000000000000000000..9243dd75e5e6b38794b990e765f05064135bc189
--- /dev/null
+++ b/contrib/apparmor/gnunet-setup
@@ -0,0 +1,57 @@
+# Last Modified: Tue Aug 11 16:25:03 2015
+#include <tunables/global>
+#include <tunables/gnunet>
+
+profile @{GNUNET_PREFIX}/bin/gnunet-setup {
+  #include <abstractions/gnome>
+  #include <abstractions/gnunet-gtk>
+  #include <abstractions/kde>
+
+  /etc/nsswitch.conf r,
+  /etc/passwd r,
+  @{PROC}/@{pid}/fd/ r,
+
+  /usr/bin/exo-open rix,
+
+  @{GNUNET_PREFIX}/bin/gnunet-peerinfo-gtk Px,
+  @{GNUNET_PREFIX}/lib/gnunet/libexec/gnunet-daemon-hostlist Px,
+
+  @{GNUNET_PREFIX}/bin/gnunet-setup mr,
+
+  @{GNUNET_PREFIX}/share/gnunet-gtk/*.png r,
+  @{GNUNET_PREFIX}/share/gnunet-gtk/gnunet_setup_main_window.glade r,
+
+  @{HOME}/.config/gtk-*/bookmarks r,
+
+  #GNUnet plugin
+# @{GNUNET_PREFIX}/lib/gnunet/libgnunet_plugin_datacache_heap.la r,
+  @{GNUNET_PREFIX}/lib/gnunet/libgnunet_plugin_datacache_heap.so mr,
+# @{GNUNET_PREFIX}/lib/gnunet/libgnunet_plugin_datacache_sqlite.la r,
+  @{GNUNET_PREFIX}/lib/gnunet/libgnunet_plugin_datacache_sqlite.so mr,
+# @{GNUNET_PREFIX}/lib/gnunet/libgnunet_plugin_datastore_mysql.la r,
+  @{GNUNET_PREFIX}/lib/gnunet/libgnunet_plugin_datastore_mysql.so mr,
+# @{GNUNET_PREFIX}/lib/gnunet/libgnunet_plugin_datastore_sqlite.la r,
+  @{GNUNET_PREFIX}/lib/gnunet/libgnunet_plugin_datastore_sqlite.so mr,
+# @{GNUNET_PREFIX}/lib/gnunet/libgnunet_plugin_namestore_sqlite.la r,
+  @{GNUNET_PREFIX}/lib/gnunet/libgnunet_plugin_namestore_sqlite.so mr,
+# @{GNUNET_PREFIX}/lib/gnunet/libgnunet_plugin_transport_http_client.la r,
+  @{GNUNET_PREFIX}/lib/gnunet/libgnunet_plugin_transport_http_client.so mr,
+# @{GNUNET_PREFIX}/lib/gnunet/libgnunet_plugin_transport_http_server.la r,
+  @{GNUNET_PREFIX}/lib/gnunet/libgnunet_plugin_transport_http_server.so mr,
+# @{GNUNET_PREFIX}/lib/gnunet/libgnunet_plugin_transport_https_client.la r,
+  @{GNUNET_PREFIX}/lib/gnunet/libgnunet_plugin_transport_https_client.so mr,
+# @{GNUNET_PREFIX}/lib/gnunet/libgnunet_plugin_transport_https_server.la r,
+  @{GNUNET_PREFIX}/lib/gnunet/libgnunet_plugin_transport_https_server.so mr,
+# @{GNUNET_PREFIX}/lib/gnunet/libgnunet_plugin_transport_tcp.la r,
+  @{GNUNET_PREFIX}/lib/gnunet/libgnunet_plugin_transport_tcp.so mr,
+# @{GNUNET_PREFIX}/lib/gnunet/libgnunet_plugin_transport_udp.la r,
+  @{GNUNET_PREFIX}/lib/gnunet/libgnunet_plugin_transport_udp.so mr,
+# @{GNUNET_PREFIX}/lib/gnunet/libgnunet_plugin_transport_wlan.la r,
+  @{GNUNET_PREFIX}/lib/gnunet/libgnunet_plugin_transport_wlan.so mr,
+
+  /usr/share/glib-*/schemas/gschemas.compiled r,
+  /usr/share/gtk-*/gtkrc r,
+
+  # Site-specific additions and overrides. See local/README for details.
+  #include <local/gnunet>
+}
diff --git a/contrib/apparmor/gnunet-statistics b/contrib/apparmor/gnunet-statistics
new file mode 100644
index 0000000000000000000000000000000000000000..d9538e35be7469bf2ecf44f50c921f869c8ad342
--- /dev/null
+++ b/contrib/apparmor/gnunet-statistics
@@ -0,0 +1,13 @@
+# Last Modified: Mon Aug 10 16:15:07 2015
+#include <tunables/global>
+#include <tunables/gnunet>
+
+profile @{GNUNET_PREFIX}/bin/gnunet-statistics {
+  #include <abstractions/base>
+  #include <abstractions/gnunet-common>
+
+  @{GNUNET_PREFIX}/bin/gnunet-statistics mr,
+
+  # Site-specific additions and overrides. See local/README for details.
+  #include <local/gnunet>
+}
diff --git a/contrib/apparmor/gnunet-statistics-gtk b/contrib/apparmor/gnunet-statistics-gtk
new file mode 100644
index 0000000000000000000000000000000000000000..2e13b8adaedc7696e1ab125eed915bc174ea153f
--- /dev/null
+++ b/contrib/apparmor/gnunet-statistics-gtk
@@ -0,0 +1,16 @@
+# Last Modified: Wed Aug  5 11:25:27 2015
+#include <tunables/global>
+#include <tunables/gnunet>
+
+profile @{GNUNET_PREFIX}/bin/gnunet-statistics-gtk {
+  #include <abstractions/kde>
+  #include <abstractions/gnome>
+  #include <abstractions/gnunet-gtk>
+
+  @{GNUNET_PREFIX}/bin/gnunet-statistics-gtk mr,
+
+  @{GNUNET_PREFIX}/share/gnunet-gtk/gnunet_statistics_gtk_main_window.glade r,
+  
+  # Site-specific additions and overrides. See local/README for details.
+  #include <local/gnunet>
+}
diff --git a/contrib/apparmor/gnunet-template b/contrib/apparmor/gnunet-template
new file mode 100644
index 0000000000000000000000000000000000000000..844dc22aed26d36ef782f320be39824ec187b605
--- /dev/null
+++ b/contrib/apparmor/gnunet-template
@@ -0,0 +1,13 @@
+# Last Modified: Mon Aug 10 16:22:33 2015
+#include <tunables/global>
+#include <tunables/gnunet>
+
+profile @{GNUNET_PREFIX}/bin/gnunet-template {
+  #include <abstractions/base>
+  #include <abstractions/gnunet-common>
+
+  @{GNUNET_PREFIX}/bin/gnunet-template mr,
+
+  # Site-specific additions and overrides. See local/README for details.
+  #include <local/gnunet>
+}
diff --git a/contrib/apparmor/gnunet-testbed-profiler b/contrib/apparmor/gnunet-testbed-profiler
new file mode 100644
index 0000000000000000000000000000000000000000..0f8d79ad949d2146f1ae30c58394d11571505f95
--- /dev/null
+++ b/contrib/apparmor/gnunet-testbed-profiler
@@ -0,0 +1,13 @@
+# Last Modified: Mon Aug 10 16:38:17 2015
+#include <tunables/global>
+#include <tunables/gnunet>
+
+profile @{GNUNET_PREFIX}/bin/gnunet-testbed-profiler {
+  #include <abstractions/base>
+  #include <abstractions/gnunet-common>
+
+  @{GNUNET_PREFIX}/bin/gnunet-testbed-profiler mr,
+
+  # Site-specific additions and overrides. See local/README for details.
+  #include <local/gnunet>
+}
diff --git a/contrib/apparmor/gnunet-testing b/contrib/apparmor/gnunet-testing
new file mode 100644
index 0000000000000000000000000000000000000000..a0cac673db530caa78f84b54b336a16faff044e9
--- /dev/null
+++ b/contrib/apparmor/gnunet-testing
@@ -0,0 +1,20 @@
+# Last Modified: Mon Aug 10 16:54:53 2015
+#include <tunables/global>
+#include <tunables/gnunet>
+
+profile @{GNUNET_PREFIX}/bin/gnunet-testing {
+  #include <abstractions/base>
+  #include <abstractions/gnunet-common>
+  #include <abstractions/gnunet-test>
+
+  /etc/gai.conf r,
+
+  @{GNUNET_PREFIX}/bin/gnunet-testing mr,
+
+  @{GNUNET_PREFIX}/lib/gnunet/libexec/gnunet-service-* Px,
+   
+  @{GNUNET_PREFIX}/share/gnunet/testing_hostkeys.ecc r,
+
+  # Site-specific additions and overrides. See local/README for details.
+  #include <local/gnunet>
+}
diff --git a/contrib/apparmor/gnunet-transport b/contrib/apparmor/gnunet-transport
new file mode 100644
index 0000000000000000000000000000000000000000..70b0cd22883c0121fb3e0876b1c279c02f19059b
--- /dev/null
+++ b/contrib/apparmor/gnunet-transport
@@ -0,0 +1,15 @@
+# Last Modified: Mon Aug 10 17:17:40 2015
+#include <tunables/global>
+#include <tunables/gnunet>
+
+profile @{GNUNET_PREFIX}/bin/gnunet-transport {
+  #include <abstractions/base>
+  #include <abstractions/gnunet-common>
+
+  @{GNUNET_PREFIX}/bin/gnunet-transport mr,
+
+  @{GNUNET_PREFIX}/lib/gnunet/libexec/gnunet-service-resolver Px,
+
+  # Site-specific additions and overrides. See local/README for details.
+  #include <local/gnunet>
+}
diff --git a/contrib/apparmor/gnunet-transport-certificate-creation b/contrib/apparmor/gnunet-transport-certificate-creation
new file mode 100644
index 0000000000000000000000000000000000000000..fa65305d712166065c2400a07ca121c798f408cc
--- /dev/null
+++ b/contrib/apparmor/gnunet-transport-certificate-creation
@@ -0,0 +1,26 @@
+# Last Modified: Mon Aug 10 17:31:32 2015
+#include <tunables/global>
+#include <tunables/gnunet>
+
+profile @{GNUNET_PREFIX}/bin/gnunet-transport-certificate-creation {
+  #include <abstractions/base>
+  #include <abstractions/openssl>
+  #include <abstractions/gnunet-common>
+
+  @{HOME}/.rnd rw,
+
+  @{PROC}/meminfo r,
+
+  /usr/bin/openssl rix,
+
+  @{GNUNET_PREFIX}/bin/gnunet-transport-certificate-creation mr,
+
+  #Access to arg privatekey and certificate ?
+  @{HOME}/ rw,
+  @{HOME}/** rw,
+  deny @{HOME}/.*/ rw,
+  deny @{HOME}/.*/** rw,
+
+  # Site-specific additions and overrides. See local/README for details.
+  #include <local/gnunet>
+}
diff --git a/contrib/apparmor/gnunet-unindex b/contrib/apparmor/gnunet-unindex
new file mode 100644
index 0000000000000000000000000000000000000000..e94a33152e13096d7ea65f91c5aea3249b847157
--- /dev/null
+++ b/contrib/apparmor/gnunet-unindex
@@ -0,0 +1,21 @@
+# Last Modified: Mon Aug 10 17:40:53 2015
+#include <tunables/global>
+#include <tunables/gnunet>
+
+profile @{GNUNET_PREFIX}/bin/gnunet-unindex {
+  #include <abstractions/base>
+  #include <abstractions/gnunet-common>
+
+  @{GNUNET_PREFIX}/bin/gnunet-unindex mr,
+  
+  @{GNUNET_PREFIX}/lib/gnunet/libexec/gnunet-helper-fs-publish Px,
+
+  #Path to files to unindex ?
+  @{HOME}/ rw,
+  @{HOME}/** rw,
+  deny @{HOME}/.*/ rw,
+  deny @{HOME}/.*/** rw,
+
+  # Site-specific additions and overrides. See local/README for details.
+  #include <local/gnunet>
+}
diff --git a/contrib/apparmor/gnunet-uri b/contrib/apparmor/gnunet-uri
new file mode 100644
index 0000000000000000000000000000000000000000..d314fbad5678206a01ff2b8caf9f7028ece90da3
--- /dev/null
+++ b/contrib/apparmor/gnunet-uri
@@ -0,0 +1,16 @@
+# Last Modified: Mon Aug 10 18:04:08 2015
+#include <tunables/global>
+#include <tunables/gnunet>
+
+profile @{GNUNET_PREFIX}/bin/gnunet-uri {
+  #include <abstractions/base>
+  #include <abstractions/gnunet-common>
+
+  #More needed
+  @{GNUNET_PREFIX}/bin/gnunet-fs-gtk Px,
+
+  @{GNUNET_PREFIX}/bin/gnunet-uri mr,
+
+  # Site-specific additions and overrides. See local/README for details.
+  #include <local/gnunet>
+}
diff --git a/contrib/apparmor/gnunet-vpn b/contrib/apparmor/gnunet-vpn
new file mode 100644
index 0000000000000000000000000000000000000000..1cf5b5eccb5ca539e281c0253a03bdf6d67beb14
--- /dev/null
+++ b/contrib/apparmor/gnunet-vpn
@@ -0,0 +1,13 @@
+# Last Modified: Mon Aug 10 18:11:26 2015
+#include <tunables/global>
+#include <tunables/gnunet>
+
+profile @{GNUNET_PREFIX}/bin/gnunet-vpn {
+  #include <abstractions/base>
+  #include <abstractions/gnunet-common>
+
+  @{GNUNET_PREFIX}/bin/gnunet-vpn mr,
+
+  # Site-specific additions and overrides. See local/README for details.
+  #include <local/gnunet>
+}
diff --git a/contrib/apparmor/tunables/gnunet b/contrib/apparmor/tunables/gnunet
new file mode 100644
index 0000000000000000000000000000000000000000..106169714677771500dea044f9ec91a3d1c563bc
--- /dev/null
+++ b/contrib/apparmor/tunables/gnunet
@@ -0,0 +1,6 @@
+@{GNUNET_PREFIX}=/usr/local
+@{GNUNET_USER}=/var/lib/gnunet
+@{LIBPRE}=/ /usr/
+@{LIBDIRS}=lib{,32,64} lib/@{multiarch}
+@{LIBS}=libc libm linux-vso 
+
diff --git a/contrib/apparmor/usr.bin.gnunet-helper-nat-server b/contrib/apparmor/usr.bin.gnunet-helper-nat-server
new file mode 100644
index 0000000000000000000000000000000000000000..637c9aa7c928146aa0c0f5f6f3a566b81509ab87
--- /dev/null
+++ b/contrib/apparmor/usr.bin.gnunet-helper-nat-server
@@ -0,0 +1,32 @@
+# ------------------------------------------------------------------
+#
+#  Copyright (C) 2011 Jacob Appelbaum <jacob@appelbaum.net>
+#
+#  This program is free software; you can redistribute it and/or
+#  modify it under the terms of version 2 of the GNU General Public
+#  License published by the Free Software Foundation.
+#
+#  SPDX-License-Identifier: GPL2.0
+#
+#  This should be placed in /etc/apparmor.d/usr.sbin.gnunet-helper-nat-server
+#  This profile may be a reasonable starting point for other NAT helpers.
+#
+# ------------------------------------------------------------------
+
+#include <tunables/global>
+/usr/bin/gnunet-helper-nat-server {
+  #include <abstractions/base>
+  #include <abstractions/consoles>
+
+  # Allow these
+  capability net_raw,
+  capability setuid,
+  network inet raw,
+  network inet dgram, # UDP IPv4
+
+  # Deny these
+  deny network inet6 stream, # TCP IPv6
+  deny network inet6 dgram, # UDP IPv6
+
+  # Deny everything else by default with AppArmor
+}
diff --git a/contrib/benchmark/collect.awk b/contrib/benchmark/collect.awk
new file mode 100644
index 0000000000000000000000000000000000000000..66bdf387e70c4c8c42cc0d4ac387b35f02461764
--- /dev/null
+++ b/contrib/benchmark/collect.awk
@@ -0,0 +1,118 @@
+# This file is part of GNUnet
+# Copyright (C) 2018 GNUnet e.V.
+#
+# GNUnet is free software: you can redistribute it and/or modify it
+# under the terms of the GNU Affero General Public License as published
+# by the Free Software Foundation, either version 3 of the License, 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
+# Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+#
+# SPDX-License-Identfier: AGPL3.0-or-later
+
+# Aggregate benchmarking data from multiple threads/processes
+# generated by util/benchmark.c.
+#
+# Can be used as
+# awk -f collect.awk gnunet-benchmark-{ops,urls}-*.txt
+
+
+# records are of the following forms:
+# 1:op 2:<op> 3:count 4:<count> 6:time_us 7:<time_us>
+# 1:url 2:<url> 3:status 4:<status> 5:count 6:<count> 7:time_us 8:<time_us> 9:time_us_max 10:<time_us_max>
+#   11:bytes_sent 12:<bytes_sent> 13:bytes_received 14:<bytes_received>
+
+
+function abs(v) {
+  return v < 0 ? -v : v
+}
+
+{
+  if ($1 == "op") {
+    n = $4;
+    t = $6;
+    op[$2]["count"] += n;
+    op[$2]["time_us"] += t;
+    if (n > 0) {
+      op[$2]["time_us_sq"] += n * (t/n) * (t/n);
+    }
+    total_ops += t;
+  } else if ($1 == "url") {
+    n = $6;
+    t = $8;
+    sent = $12
+    recv = $14
+    url[$2][$4]["count"] += n;
+    url[$2][$4]["time_us"] += t;
+    if (n > 0) {
+      url[$2][$4]["time_us_sq"] += n * (t/n) * (t/n);
+    }
+    url[$2][$4]["bytes_sent"] += sent;
+    url[$2][$4]["bytes_received"] += recv;
+    max = url[$2][$4]["time_us_max"];
+    url[$2][$4]["time_us_max"] = (t/n > max ? t/n : max)
+  } else if ($1 == "op_baseline") {
+    # take average time for operations from baseline values with format:
+    # op_baseline <opname> time_avg_us <t>
+    op_baseline[$2] = $4;
+    have_baseline = 1;
+  }
+}
+
+function avg(sum, n) {
+  if (n == 0) {
+    return 0;
+  } else {
+    return sum / n;
+  }
+}
+
+function stdev(sum, sum_sq, n) {
+  if (n == 0) {
+    return 0;
+  } else {
+    return sqrt(abs((sum_sq / n) - ((sum / n) * (sum / n))));
+  }
+}
+
+END {
+  for (x in op) {
+    print "op", x, "count", op[x]["count"], "time_us", op[x]["time_us"], \
+          "time_avg_us", avg(op[x]["time_us"], op[x]["count"]), \
+          "stdev", stdev(op[x]["time_us"], op[x]["time_us_sq"], op[x]["count"]);
+  }
+  for (x in url) {
+    for (y in url[x]) {
+      print "url", x, "status", y, \
+            "count", url[x][y]["count"], "time_us", url[x][y]["time_us"], \
+            "time_avg_us", avg(url[x][y]["time_us"], url[x][y]["count"]), \
+            "stdev", stdev(url[x][y]["time_us"], url[x][y]["time_us_sq"], url[x][y]["count"]), \
+            "time_us_max", url[x][y]["time_us_max"], \
+            "bytes_sent_avg", avg(url[x][y]["bytes_sent"], url[x][y]["count"]), \
+            "bytes_received_avg", avg(url[x][y]["bytes_received"], url[x][y]["count"]);
+    }
+  }
+  if (total_ops) {
+    print "total_ops_ms", total_ops;
+  }
+
+  # Invoke awk with -V baseline_out=<filename> to extract baseline average
+  if (baseline_out) {
+    for (x in op) {
+      print "op_baseline", x, "time_avg_us", avg(op[x]["time_us"], op[x]["count"]) > baseline_out
+    }
+  }
+
+  if (have_baseline) {
+    for (x in op) {
+      total_ops_adjusted += op_baseline[x] * op[x]["count"];
+    }
+    print "total_ops_adjusted_ms", int(total_ops_adjusted);
+  }
+}
diff --git a/contrib/branding/logo/gnunet-logo-big.png b/contrib/branding/logo/gnunet-logo-big.png
new file mode 100644
index 0000000000000000000000000000000000000000..54c418f8f334bcad4b6d7a61b51e3b075c95639b
Binary files /dev/null and b/contrib/branding/logo/gnunet-logo-big.png differ
diff --git a/contrib/branding/logo/gnunet-logo-dark-only-text.svg b/contrib/branding/logo/gnunet-logo-dark-only-text.svg
new file mode 100644
index 0000000000000000000000000000000000000000..f4ca0f9d21d5799ae80240318b0c52f1ab177d2a
--- /dev/null
+++ b/contrib/branding/logo/gnunet-logo-dark-only-text.svg
@@ -0,0 +1,1144 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg
+   xmlns:dc="http://purl.org/dc/elements/1.1/"
+   xmlns:cc="http://creativecommons.org/ns#"
+   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+   xmlns:svg="http://www.w3.org/2000/svg"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:xlink="http://www.w3.org/1999/xlink"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   version="1.1"
+   id="svg2"
+   height="42.057301"
+   width="159.35417"
+   sodipodi:docname="gnunet-logo-dark-only-text.svg"
+   inkscape:version="0.92.3 (2405546, 2018-03-11)">
+  <sodipodi:namedview
+     pagecolor="#ffffff"
+     bordercolor="#666666"
+     borderopacity="1"
+     objecttolerance="10"
+     gridtolerance="10"
+     guidetolerance="10"
+     inkscape:pageopacity="0"
+     inkscape:pageshadow="2"
+     inkscape:window-width="1130"
+     inkscape:window-height="760"
+     id="namedview5639"
+     showgrid="false"
+     inkscape:zoom="3.2071429"
+     inkscape:cx="-2.4948441"
+     inkscape:cy="7.4954053"
+     inkscape:window-x="0"
+     inkscape:window-y="0"
+     inkscape:window-maximized="0"
+     inkscape:current-layer="svg2" />
+  <title
+     id="title3310">logo for GNUnet</title>
+  <defs
+     id="defs4">
+    <linearGradient
+       id="gnunet">
+      <stop
+         style="stop-color:#ff0000;stop-opacity:0.58431375;"
+         offset="0"
+         id="stop9516" />
+      <stop
+         style="stop-color:#ffcc00;stop-opacity:1;"
+         offset="1"
+         id="stop9518" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient4094">
+      <stop
+         style="stop-color:#232323;stop-opacity:1;"
+         offset="0"
+         id="stop4096" />
+      <stop
+         style="stop-color:#4d4d4d;stop-opacity:1;"
+         offset="1"
+         id="stop4098" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient4014">
+      <stop
+         style="stop-color:#a0a0a0;stop-opacity:1;"
+         offset="0"
+         id="stop4016" />
+      <stop
+         style="stop-color:#ffffff;stop-opacity:1;"
+         offset="1"
+         id="stop4018" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient4678">
+      <stop
+         style="stop-color:#e5e5e5;stop-opacity:1;"
+         offset="0"
+         id="stop4680" />
+      <stop
+         style="stop-color:#d3cdcd;stop-opacity:1;"
+         offset="1"
+         id="stop4682" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient4341">
+      <stop
+         id="stop4343"
+         offset="0"
+         style="stop-color:#333333;stop-opacity:1;" />
+      <stop
+         id="stop4345"
+         offset="1"
+         style="stop-color:#484848;stop-opacity:1;" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient4696-5">
+      <stop
+         id="stop4698-6"
+         offset="0"
+         style="stop-color:#ffb638;stop-opacity:1;" />
+      <stop
+         id="stop4700-2"
+         offset="1"
+         style="stop-color:#f0ae26;stop-opacity:1;" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient4702-3-6">
+      <stop
+         id="stop4704-1"
+         offset="0"
+         style="stop-color:#ff0000;stop-opacity:0.58431375;" />
+      <stop
+         id="stop4706-8"
+         offset="1"
+         style="stop-color:#ffcc00;stop-opacity:1;" />
+    </linearGradient>
+    <color-profile
+       name="Artifex-PS-CMYK-Profile"
+       xlink:href="/usr/share/color/icc/ghostscript/ps_cmyk.icc"
+       id="color-profile5435" />
+    <linearGradient
+       y2="69.791016"
+       x2="177.04297"
+       y1="63.65625"
+       x1="142.96875"
+       gradientTransform="matrix(-0.88803314,0,0,0.88803314,595.57001,1106.9291)"
+       gradientUnits="userSpaceOnUse"
+       id="linearGradient3138"
+       xlink:href="#linearGradient4702-3-6" />
+    <linearGradient
+       y2="1043.709"
+       x2="80.655251"
+       y1="1025.709"
+       x1="108.08774"
+       gradientTransform="matrix(-0.49726789,0,0,0.49726789,555.31016,722.70088)"
+       gradientUnits="userSpaceOnUse"
+       id="linearGradient3141"
+       xlink:href="#linearGradient4696-5" />
+    <linearGradient
+       y2="922.07178"
+       x2="78.000107"
+       y1="1004.8033"
+       x1="113.5146"
+       gradientTransform="matrix(0.88803314,0,0,0.88803314,415.18739,350.00262)"
+       gradientUnits="userSpaceOnUse"
+       id="linearGradient3144"
+       xlink:href="#linearGradient4702-3-6" />
+    <linearGradient
+       y2="70.667412"
+       x2="176.60477"
+       y1="63.65625"
+       x1="142.96875"
+       gradientTransform="matrix(0.88803314,0,0,0.88803314,415.2161,1106.9294)"
+       gradientUnits="userSpaceOnUse"
+       id="linearGradient3148"
+       xlink:href="#linearGradient4702-3-6" />
+    <linearGradient
+       y2="70.667412"
+       x2="176.60477"
+       y1="63.65625"
+       x1="142.96875"
+       gradientTransform="matrix(0.88803314,0,0,0.88803314,415.2161,1106.9294)"
+       gradientUnits="userSpaceOnUse"
+       id="linearGradient3780"
+       xlink:href="#linearGradient4702-3-6" />
+    <linearGradient
+       y2="922.07178"
+       x2="78.000107"
+       y1="1004.8033"
+       x1="113.5146"
+       gradientTransform="matrix(0.88803314,0,0,0.88803314,415.18739,350.00262)"
+       gradientUnits="userSpaceOnUse"
+       id="linearGradient3782"
+       xlink:href="#linearGradient4702-3-6" />
+    <linearGradient
+       y2="1043.709"
+       x2="80.655251"
+       y1="1025.709"
+       x1="108.08774"
+       gradientTransform="matrix(-0.49726789,0,0,0.49726789,555.31016,722.70088)"
+       gradientUnits="userSpaceOnUse"
+       id="linearGradient3784"
+       xlink:href="#linearGradient4696-5" />
+    <linearGradient
+       y2="69.791016"
+       x2="177.04297"
+       y1="63.65625"
+       x1="142.96875"
+       gradientTransform="matrix(-0.88803314,0,0,0.88803314,595.57001,1106.9291)"
+       gradientUnits="userSpaceOnUse"
+       id="linearGradient3786"
+       xlink:href="#linearGradient4702-3-6" />
+    <filter
+       id="filter9204"
+       style="color-interpolation-filters:sRGB">
+      <feColorMatrix
+         id="feColorMatrix9194"
+         result="colormatrix"
+         values="1 0 0 0 0 0 1 0 0 0 0 0 1 0 0 -0.2125 -0.7154 -0.0721 1 0 "
+         in="SourceGraphic" />
+      <feComposite
+         k1="0"
+         id="feComposite9196"
+         result="composite"
+         k4="0"
+         k3="0"
+         k2="1"
+         operator="arithmetic"
+         in2="colormatrix"
+         in="SourceGraphic" />
+      <feGaussianBlur
+         id="feGaussianBlur9198"
+         result="blur1"
+         stdDeviation="5 0.01" />
+      <feGaussianBlur
+         id="feGaussianBlur9200"
+         result="blur2"
+         stdDeviation="0.01 5"
+         in="composite" />
+      <feBlend
+         id="feBlend9202"
+         result="blend"
+         mode="darken"
+         in2="blur1"
+         in="blur2" />
+    </filter>
+    <filter
+       id="filter9330"
+       style="color-interpolation-filters:sRGB">
+      <feGaussianBlur
+         id="feGaussianBlur9328"
+         result="blur"
+         stdDeviation="2 2" />
+    </filter>
+  </defs>
+  <metadata
+     id="metadata7">
+    <rdf:RDF>
+      <cc:Work
+         rdf:about="">
+        <dc:format>image/svg+xml</dc:format>
+        <dc:type
+           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+        <dc:title>logo for GNUnet</dc:title>
+        <dc:creator>
+          <cc:Agent>
+            <dc:title>Luis Felipe López Acevedo, Amirouche Boubekki, carlo von lynX</dc:title>
+          </cc:Agent>
+        </dc:creator>
+        <dc:rights>
+          <cc:Agent>
+            <dc:title>GNUnet e.V.</dc:title>
+          </cc:Agent>
+        </dc:rights>
+        <cc:license
+           rdf:resource="http://creativecommons.org/licenses/by-sa/4.0/" />
+        <dc:description />
+      </cc:Work>
+      <cc:License
+         rdf:about="http://creativecommons.org/licenses/by-sa/4.0/">
+        <cc:permits
+           rdf:resource="http://creativecommons.org/ns#Reproduction" />
+        <cc:permits
+           rdf:resource="http://creativecommons.org/ns#Distribution" />
+        <cc:requires
+           rdf:resource="http://creativecommons.org/ns#Notice" />
+        <cc:requires
+           rdf:resource="http://creativecommons.org/ns#Attribution" />
+        <cc:permits
+           rdf:resource="http://creativecommons.org/ns#DerivativeWorks" />
+        <cc:requires
+           rdf:resource="http://creativecommons.org/ns#ShareAlike" />
+      </cc:License>
+    </rdf:RDF>
+  </metadata>
+  <g
+     id="g5346"
+     style="display:none"
+     transform="translate(-467.72664,-836.92541)">
+    <text
+       xml:space="preserve"
+       style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:16.53852463px;line-height:125%;font-family:Ubuntu;-inkscape-font-specification:Ubuntu;letter-spacing:0px;word-spacing:0px;display:inline;opacity:1;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1.03365779px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+       x="453.95291"
+       y="869.96057"
+       id="text5344"><tspan
+         id="tspan5342"
+         x="453.95291"
+         y="869.96057"
+         style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:49.33333206px;font-family:'Ubuntu Bold';-inkscape-font-specification:'Ubuntu Bold, ';fill:#ffffff;stroke-width:1.03365779px"
+         dx="0 0 0">gnu net</tspan></text>
+  </g>
+  <g
+     transform="translate(-467.72664,-836.92541)"
+     style="display:none"
+     id="g950">
+    <text
+       id="text948"
+       y="869.21057"
+       x="467.77612"
+       style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:16.53852463px;line-height:125%;font-family:Ubuntu;-inkscape-font-specification:Ubuntu;letter-spacing:0px;word-spacing:0px;display:inline;opacity:1;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1.03365779px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+       xml:space="preserve"><tspan
+         dx="0 -2.5 -3 0 -19.25 -2.5 -3"
+         style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:50.66666794px;font-family:'Anonymous Pro';-inkscape-font-specification:'Anonymous Pro Bold';fill:#ffffff;stroke-width:1.03365779px"
+         y="869.21057"
+         x="467.77612"
+         id="tspan946">gnu net</tspan></text>
+  </g>
+  <g
+     id="g941"
+     style="display:none"
+     transform="translate(-80.31201,-247.1061)">
+    <ellipse
+       ry="17.690269"
+       rx="17.68549"
+       style="display:inline;opacity:1;fill:#ee0000;fill-opacity:1;stroke:#ee0000;stroke-width:1.68696308;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.97635139"
+       id="ellipse937"
+       cx="157.97346"
+       cy="180.65355" />
+    <ellipse
+       ry="17.690269"
+       rx="17.68549"
+       style="display:inline;opacity:1;fill:#ee0000;fill-opacity:1;stroke:#ee0000;stroke-width:1.68696308;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.97635139"
+       id="ellipse939"
+       cx="157.97346"
+       cy="111.16864" />
+  </g>
+  <g
+     transform="translate(-467.72664,-836.92541)"
+     style="display:none"
+     id="g935">
+    <g
+       aria-label="gnu net"
+       style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:16.53852463px;line-height:125%;font-family:Ubuntu;-inkscape-font-specification:Ubuntu;letter-spacing:0px;word-spacing:0px;display:inline;opacity:1;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1.03365779px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;image-rendering:auto"
+       id="g933">
+      <path
+         d="m 423.90503,684.79003 h 22.14128 v 61.61056 q 0,11.55196 4.3855,16.04443 4.38546,4.49242 12.72857,4.49242 12.19374,0 20.00203,-9.94753 7.80828,-9.94753 7.80828,-27.48942 v -44.71046 h 22.14128 v 99.6893 h -22.14128 v -24.92231 q -3.31586,12.83553 -12.30071,20.10899 -8.98489,7.27346 -22.14132,7.27346 -15.29567,0 -23.95963,-9.94753 -8.664,-10.0545 -8.664,-30.59135 z"
+         style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:50.66666794px;font-family:'Anonymous Pro';-inkscape-font-specification:'Anonymous Pro Bold';fill:#ffffff;stroke-width:4.46906853px"
+         id="path925"
+         inkscape:connector-curvature="0" />
+      <path
+         d="m 669.48029,784.47933 h -22.14128 v -61.50359 q 0,-11.65892 -4.3855,-16.15139 -4.38546,-4.49243 -12.72857,-4.49243 -12.30071,0 -20.10899,9.94753 -7.70132,9.94754 -7.70132,27.48947 v 44.71041 h -22.14128 v -99.6893 h 22.14128 v 25.02928 q 3.31586,-12.94249 12.30071,-20.10899 8.98489,-7.27346 22.14132,-7.27346 15.29567,0 23.95967,9.94753 8.66396,9.94753 8.66396,30.59135 z"
+         style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:50.66666794px;font-family:'Anonymous Pro';-inkscape-font-specification:'Anonymous Pro Bold';fill:#ffffff;stroke-width:4.46906853px"
+         id="path927"
+         inkscape:connector-curvature="0" />
+    </g>
+  </g>
+  <g
+     id="g1296"
+     style="display:none"
+     transform="translate(-80.31201,-294.38421)">
+    <path
+       style="fill:none;stroke:#dddddd;stroke-width:1.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+       d="m 62.698223,85.778107 -39.5,48.000003 v 0 l -1,2"
+       id="path1256"
+       inkscape:connector-curvature="0" />
+    <path
+       style="fill:none;stroke:#dddddd;stroke-width:2.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+       d="m 12.698223,104.77811 10,29 21,-10.5 v 0 0"
+       id="path1258"
+       inkscape:connector-curvature="0" />
+    <path
+       style="display:inline;fill:none;fill-rule:evenodd;stroke:#dddddd;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+       d="m 11.809253,105.24526 63.6227,34.91188 23.31802,-11.09978 -35.03955,28.74946 11.86161,-17.77468 -53.18435,-5.79678 40.95076,23.69646 25.32406,0.49689 24.193047,3.02495 v 48.02104 l 21.04995,-32.14943 -20.559,-15.87161 32.52749,48.02104 -8.06937,31.38386 -24.94907,-31.76198 24.94907,77.51429 22.25436,-36.69889 21.97354,37.07701 -43.59987,-0.37188 41.32877,-28.87448 22.05899,-21.17152 -19.90986,50.171 -3.71591,-29.60613 -8.57843,-31.7682 -9.69437,24.71516 54.37611,-52.19866 -24.96716,8.94671 -18.39175,19.15282 18.27579,-55.07718 25.20812,27.362 20.66591,-41.35238 -46.00204,14.12783 22.94304,-37.07431 23.05297,23.0777 31.8814,-26.48075 40.07874,-25.58708 -15.26372,39.20869 -24.69305,-13.74039 -55.05634,4.03119 79.62738,9.58108 -56.57441,12.73416"
+       id="path1260"
+       inkscape:connector-curvature="0" />
+    <path
+       style="display:inline;fill:none;fill-rule:evenodd;stroke:#dddddd;stroke-width:1.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+       d="m 98.868943,129.31358 37.045597,48.02106"
+       id="path1262"
+       inkscape:connector-curvature="0" />
+    <path
+       style="display:inline;fill:none;fill-rule:evenodd;stroke:#dddddd;stroke-width:1.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+       d="m 88.284483,158.4287 10.96248,-29.11512 12.474537,32.51819"
+       id="path1264"
+       inkscape:connector-curvature="0" />
+    <path
+       style="display:inline;fill:none;fill-rule:evenodd;stroke:#dddddd;stroke-width:3;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+       d="m 212.13974,133.78236 54.69043,-3.64603 -31.75647,27.04795"
+       id="path1266"
+       inkscape:connector-curvature="0" />
+    <path
+       transform="translate(-387.41463,-542.5412)"
+       style="display:inline;opacity:1;fill:none;fill-opacity:1;stroke:#dddddd;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+       d="m 399.11285,648.31931 50.5,-19.5 -14.05,28.1 0.925,-1.725 -5.875,11.75 -0.25,-0.75"
+       id="path1268"
+       inkscape:connector-curvature="0" />
+    <path
+       transform="translate(-387.41463,-542.5412)"
+       style="display:inline;opacity:1;fill:#729fcf;fill-rule:evenodd;stroke:#dddddd;stroke-width:1.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+       d="m 601.57854,741.42859 -2.26809,-64.28015"
+       id="path1270"
+       inkscape:connector-curvature="0" />
+    <path
+       style="fill:none;stroke:#dddddd;stroke-width:1.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+       d="m 189.57322,206.52811 -44,2.625 25.375,17.125 v 0"
+       id="path1272"
+       inkscape:connector-curvature="0" />
+    <path
+       transform="translate(-387.41463,-542.5412)"
+       style="display:inline;opacity:1;fill:none;fill-rule:evenodd;stroke:#dddddd;stroke-width:3;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+       d="m 475.69911,700.21367 24.57107,51.42411"
+       id="path1274"
+       inkscape:connector-curvature="0" />
+    <path
+       transform="translate(-387.41463,-542.5412)"
+       style="display:inline;opacity:1;fill:none;fill-rule:evenodd;stroke:#dddddd;stroke-width:1.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+       d="m 534.29164,751.63778 12.85257,40.08057"
+       id="path1276"
+       inkscape:connector-curvature="0" />
+    <path
+       transform="translate(-387.41463,-542.5412)"
+       style="display:inline;opacity:1;fill:none;fill-rule:evenodd;stroke:#dddddd;stroke-width:1.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+       d="m 525.21925,783.02162 0.37803,45.75234"
+       id="path1278"
+       inkscape:connector-curvature="0" />
+    <path
+       transform="translate(-387.41463,-542.5412)"
+       style="display:inline;opacity:1;fill:none;fill-rule:evenodd;stroke:#dddddd;stroke-width:1.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+       d="m 601.95657,742.56293 -12.09653,36.6775"
+       id="path1280"
+       inkscape:connector-curvature="0" />
+    <path
+       transform="translate(-387.41463,-542.5412)"
+       style="display:inline;opacity:1;fill:none;fill-rule:evenodd;stroke:#dddddd;stroke-width:1.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+       d="m 475.69911,700.59178 46.98395,22.0278 10.85256,28.26194"
+       id="path1282"
+       inkscape:connector-curvature="0" />
+    <path
+       transform="translate(-387.41463,-542.5412)"
+       style="display:inline;opacity:1;fill:none;fill-rule:evenodd;stroke:#dddddd;stroke-width:1.58654225px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+       d="m 589.104,778.86231 -12.85255,-66.17074 v 36.6775 z"
+       id="path1284"
+       inkscape:connector-curvature="0" />
+    <path
+       transform="translate(-387.41463,-542.5412)"
+       style="display:inline;opacity:1;fill:none;fill-rule:evenodd;stroke:#dddddd;stroke-width:1.58654225px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+       d="m 557.35064,768.27501 31.75336,10.5873"
+       id="path1286"
+       inkscape:connector-curvature="0" />
+    <path
+       transform="translate(-387.41463,-542.5412)"
+       style="display:inline;opacity:1;fill:none;fill-rule:evenodd;stroke:#dddddd;stroke-width:1.58654225px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+       d="m 500.27018,704.37298 v 48.77728 l 24.57105,30.2495 23.81505,9.45293"
+       id="path1288"
+       inkscape:connector-curvature="0" />
+    <path
+       transform="translate(-387.41463,-542.5412)"
+       style="display:inline;opacity:1;fill:none;fill-rule:evenodd;stroke:#dddddd;stroke-width:3;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+       d="m 524.46323,829.53019 44.98392,-0.37812"
+       id="path1290"
+       inkscape:connector-curvature="0" />
+    <path
+       transform="translate(-387.41463,-542.5412)"
+       style="display:inline;opacity:1;fill:none;stroke:#dddddd;stroke-width:2.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+       d="m 694.61285,647.31931 -40.285,-17.00922 -4.715,-1.99078 29,57.5 v -0.5 0 h 0.5 v 0"
+       id="path1292"
+       inkscape:connector-curvature="0" />
+    <path
+       transform="translate(-387.41463,-542.5412)"
+       style="display:inline;opacity:1;fill:none;fill-rule:evenodd;stroke:#dddddd;stroke-width:1.58654225px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+       d="m 409.92428,677.14844 54.05634,6.0499"
+       id="path1294"
+       inkscape:connector-curvature="0" />
+  </g>
+  <g
+     transform="translate(-80.31201,-294.38421)"
+     style="display:none"
+     id="g1254">
+    <ellipse
+       transform="translate(-387.41463,-542.5412)"
+       ry="4.1593032"
+       rx="4.1581793"
+       cy="829.24042"
+       cx="568.98083"
+       id="ellipse1194"
+       style="display:inline;opacity:1;fill:#ffffff;fill-opacity:1;stroke:#eeeeee;stroke-width:0.39663559;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
+    <ellipse
+       transform="translate(-387.41463,-542.5412)"
+       ry="4.1593032"
+       rx="4.1581793"
+       style="display:inline;opacity:1;fill:#ffffff;fill-opacity:1;stroke:#eeeeee;stroke-width:0.39663559;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+       id="ellipse1196"
+       cx="588.85413"
+       cy="778.67493" />
+    <ellipse
+       transform="translate(-387.41463,-542.5412)"
+       ry="4.1593032"
+       rx="4.1581793"
+       cy="740.67249"
+       cx="601.57867"
+       id="ellipse1198"
+       style="display:inline;opacity:1;fill:#ffffff;fill-opacity:1;stroke:#eeeeee;stroke-width:0.39663559;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
+    <ellipse
+       transform="translate(-387.41463,-542.5412)"
+       ry="4.1593032"
+       rx="4.1581793"
+       style="display:inline;opacity:1;fill:#ffffff;fill-opacity:1;stroke:#eeeeee;stroke-width:0.39663559;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+       id="ellipse1200"
+       cx="525.79852"
+       cy="829.24042" />
+    <ellipse
+       transform="translate(-387.41463,-542.5412)"
+       ry="4.1593032"
+       rx="4.1581793"
+       style="display:inline;opacity:1;fill:#ffffff;fill-opacity:1;stroke:#eeeeee;stroke-width:0.39663559;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+       id="ellipse1202"
+       cx="557.82654"
+       cy="768.71582" />
+    <ellipse
+       transform="translate(-387.41463,-542.5412)"
+       ry="4.1593032"
+       rx="4.1581793"
+       cy="783.02173"
+       cx="525.21936"
+       id="ellipse1204"
+       style="display:inline;opacity:1;fill:#ffffff;fill-opacity:1;stroke:#eeeeee;stroke-width:0.39663559;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
+    <ellipse
+       transform="translate(-387.41463,-542.5412)"
+       ry="4.1593032"
+       rx="4.1581793"
+       style="display:inline;opacity:1;fill:#ffffff;fill-opacity:1;stroke:#eeeeee;stroke-width:0.39663559;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+       id="ellipse1206"
+       cx="400.09586"
+       cy="647.34271" />
+    <ellipse
+       transform="translate(-387.41463,-542.5412)"
+       ry="4.1593032"
+       rx="4.1581793"
+       style="display:inline;opacity:1;fill:#ffffff;fill-opacity:1;stroke:#eeeeee;stroke-width:0.39663559;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+       id="ellipse1208"
+       cx="450.11285"
+       cy="628.31934" />
+    <ellipse
+       transform="translate(-387.41463,-542.5412)"
+       ry="4.1593032"
+       rx="4.1581793"
+       style="display:inline;opacity:1;fill:#ffffff;fill-opacity:1;stroke:#eeeeee;stroke-width:0.39663559;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+       id="ellipse1210"
+       cx="622.36951"
+       cy="699.45752" />
+    <ellipse
+       transform="translate(-387.41463,-542.5412)"
+       ry="4.1593032"
+       rx="4.1581793"
+       style="display:inline;opacity:1;fill:#ffffff;fill-opacity:1;stroke:#eeeeee;stroke-width:0.39663559;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+       id="ellipse1212"
+       cx="547.21771"
+       cy="792.29773" />
+    <ellipse
+       transform="translate(-387.41463,-542.5412)"
+       ry="4.1593032"
+       rx="4.1581793"
+       style="display:inline;opacity:1;fill:#ffffff;fill-opacity:1;stroke:#eeeeee;stroke-width:0.39663559;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+       id="ellipse1214"
+       cx="566.20697"
+       cy="800.12549" />
+    <ellipse
+       transform="translate(-387.41463,-542.5412)"
+       ry="4.1593032"
+       rx="4.1581793"
+       cy="751.63794"
+       cx="500.64822"
+       id="ellipse1216"
+       style="display:inline;opacity:1;fill:#ffffff;fill-opacity:1;stroke:#eeeeee;stroke-width:0.39663559;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
+    <ellipse
+       transform="translate(-387.41463,-542.5412)"
+       ry="4.1593032"
+       rx="4.1581793"
+       style="display:inline;opacity:1;fill:#ffffff;fill-opacity:1;stroke:#eeeeee;stroke-width:0.39663559;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+       id="ellipse1218"
+       cx="533.33447"
+       cy="751.72632" />
+    <ellipse
+       transform="translate(-387.41463,-542.5412)"
+       ry="4.1593032"
+       rx="4.1581793"
+       style="display:inline;opacity:1;fill:#ffffff;fill-opacity:1;stroke:#eeeeee;stroke-width:0.39663559;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+       id="ellipse1220"
+       cx="450.75012"
+       cy="699.83545" />
+    <ellipse
+       transform="translate(-387.41463,-542.5412)"
+       ry="4.1593032"
+       rx="4.1581793"
+       cy="700.59174"
+       cx="476.07718"
+       id="ellipse1222"
+       style="display:inline;opacity:1;fill:#ffffff;fill-opacity:1;stroke:#eeeeee;stroke-width:0.39663559;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
+    <ellipse
+       transform="translate(-387.41463,-542.5412)"
+       ry="4.1593032"
+       rx="4.1581793"
+       style="display:inline;opacity:1;fill:#ffffff;fill-opacity:1;stroke:#eeeeee;stroke-width:0.39663559;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+       id="ellipse1224"
+       cx="521.49146"
+       cy="719.65314" />
+    <ellipse
+       transform="translate(-387.41463,-542.5412)"
+       ry="4.1593032"
+       rx="4.1581793"
+       style="display:inline;opacity:1;fill:#ffffff;fill-opacity:1;stroke:#eeeeee;stroke-width:0.39663559;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+       id="ellipse1226"
+       cx="500.6362"
+       cy="703.87305" />
+    <ellipse
+       ry="4.1593032"
+       rx="4.1581793"
+       cy="134.28851"
+       cx="211.9584"
+       id="ellipse1228"
+       style="display:inline;opacity:1;fill:#ffffff;fill-opacity:1;stroke:#eeeeee;stroke-width:0.39663559;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
+    <ellipse
+       transform="translate(-387.41463,-542.5412)"
+       ry="4.1593032"
+       rx="4.1581793"
+       style="display:inline;opacity:1;fill:#ffffff;fill-opacity:1;stroke:#eeeeee;stroke-width:0.39663559;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+       id="ellipse1230"
+       cx="576.62964"
+       cy="713.44794" />
+    <ellipse
+       ry="4.1593032"
+       rx="4.1581793"
+       cy="123.16669"
+       cx="43.166531"
+       id="ellipse1232"
+       style="display:inline;opacity:1;fill:#ffffff;fill-opacity:1;stroke:#eeeeee;stroke-width:0.39663559;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
+    <ellipse
+       ry="4.1593032"
+       rx="4.1581793"
+       style="display:inline;opacity:1;fill:#ffffff;fill-opacity:1;stroke:#eeeeee;stroke-width:0.39663559;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+       id="ellipse1234"
+       cx="98.865997"
+       cy="129.43542" />
+    <ellipse
+       ry="4.1593032"
+       rx="4.1581793"
+       cy="130.05022"
+       cx="267.08618"
+       id="ellipse1236"
+       style="display:inline;opacity:1;fill:#ffffff;fill-opacity:1;stroke:#eeeeee;stroke-width:0.39663559;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
+    <ellipse
+       transform="translate(-387.41463,-542.5412)"
+       ry="4.1593032"
+       rx="4.1581793"
+       style="display:inline;opacity:1;fill:#ffffff;fill-opacity:1;stroke:#eeeeee;stroke-width:0.39663559;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+       id="ellipse1238"
+       cx="679.07196"
+       cy="686.22339" />
+    <ellipse
+       transform="translate(-387.41463,-542.5412)"
+       ry="4.1593032"
+       rx="4.1581793"
+       cy="748.99109"
+       cx="577.00763"
+       id="ellipse1240"
+       style="display:inline;opacity:1;fill:#ffffff;fill-opacity:1;stroke:#eeeeee;stroke-width:0.39663559;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
+    <ellipse
+       transform="translate(-387.41463,-542.5412)"
+       ry="4.1593032"
+       rx="4.1581793"
+       style="display:inline;opacity:1;fill:#ffffff;fill-opacity:1;stroke:#eeeeee;stroke-width:0.39663559;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+       id="ellipse1242"
+       cx="577.00763"
+       cy="748.99109" />
+    <ellipse
+       transform="translate(-387.41463,-542.5412)"
+       ry="4.1593032"
+       rx="4.1581793"
+       cy="748.99109"
+       cx="577.07013"
+       id="ellipse1244"
+       style="display:inline;opacity:1;fill:#ffffff;fill-opacity:1;stroke:#eeeeee;stroke-width:0.39663559;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
+    <ellipse
+       transform="translate(0,-3e-6)"
+       ry="4.1593032"
+       rx="4.1581793"
+       cy="133.85095"
+       cx="22.887779"
+       id="ellipse1246"
+       style="display:inline;opacity:1;fill:#ffffff;fill-opacity:1;stroke:#eeeeee;stroke-width:0.39663559;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
+    <ellipse
+       transform="translate(-387.41463,-542.5412)"
+       ry="4.1593032"
+       rx="4.1581793"
+       cy="682.1922"
+       cx="462.47165"
+       id="ellipse1248"
+       style="display:inline;opacity:1;fill:#ffffff;fill-opacity:1;stroke:#eeeeee;stroke-width:0.39663559;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
+    <ellipse
+       transform="translate(-387.41463,-542.5412)"
+       ry="4.1593032"
+       rx="4.1581793"
+       cy="647.3053"
+       cx="694.58264"
+       id="ellipse1250"
+       style="display:inline;opacity:1;fill:#ffffff;fill-opacity:1;stroke:#eeeeee;stroke-width:0.39663559;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
+    <ellipse
+       transform="translate(-387.41463,-542.5412)"
+       ry="4.1593032"
+       rx="4.1581793"
+       style="display:inline;opacity:1;fill:#ffffff;fill-opacity:1;stroke:#eeeeee;stroke-width:0.39663559;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+       id="ellipse1252"
+       cx="649.61285"
+       cy="628.31934" />
+  </g>
+  <g
+     id="g1539"
+     style="display:inline"
+     transform="translate(-80.31201,-247.1061)">
+    <ellipse
+       ry="4.1593032"
+       rx="4.1581793"
+       style="display:inline;opacity:1;fill:#3399cc;fill-opacity:1;stroke:#3399cc;stroke-width:0.39663559;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+       id="ellipse1535"
+       cx="159.80099"
+       cy="276.32968" />
+    <ellipse
+       ry="4.1593032"
+       rx="4.1581793"
+       style="display:inline;opacity:1;fill:#3399cc;fill-opacity:1;stroke:#3399cc;stroke-width:0.39663559;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+       id="ellipse1537"
+       cx="159.80099"
+       cy="259.99252" />
+  </g>
+  <g
+     transform="translate(-80.31201,-294.38421)"
+     style="display:none"
+     id="layer3">
+    <path
+       id="path5313"
+       d="m 62.698223,85.778107 -39.5,48.000003 v 0 l -1,2"
+       style="fill:none;stroke:#cc0000;stroke-width:1.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:0.99607843"
+       inkscape:connector-curvature="0" />
+    <path
+       id="path5311"
+       d="m 12.698223,104.77811 10,29 21,-10.5 v 0 0"
+       style="fill:none;stroke:#cc0000;stroke-width:2.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:0.99607843"
+       inkscape:connector-curvature="0" />
+    <path
+       id="path9316"
+       d="m 11.809253,105.24526 63.6227,34.91188 23.31802,-11.09978 -35.03955,28.74946 11.86161,-17.77468 -53.18435,-5.79678 40.95076,23.69646 25.32406,0.49689 24.193047,3.02495 v 48.02104 l 21.04995,-32.14943 -20.559,-15.87161 32.52749,48.02104 -8.06937,31.38386 -24.94907,-31.76198 24.94907,77.51429 22.25436,-36.69889 21.97354,37.07701 -43.59987,-0.37188 41.32877,-28.87448 22.05899,-21.17152 -19.90986,50.171 -3.71591,-29.60613 -8.57843,-31.7682 -9.69437,24.71516 54.37611,-52.19866 -24.96716,8.94671 -18.39175,19.15282 18.27579,-55.07718 25.20812,27.362 20.66591,-41.35238 -46.00204,14.12783 22.94304,-37.07431 23.05297,23.0777 31.8814,-26.48075 40.07874,-25.58708 -15.26372,39.20869 -24.69305,-13.74039 -55.05634,4.03119 79.62738,9.58108 -56.57441,12.73416"
+       style="display:inline;fill:none;fill-rule:evenodd;stroke:#cc0000;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:0.99607843"
+       inkscape:connector-curvature="0" />
+    <path
+       id="path9318"
+       d="m 98.868943,129.31358 37.045597,48.02106"
+       style="display:inline;fill:none;fill-rule:evenodd;stroke:#cc0000;stroke-width:1.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:0.99607843"
+       inkscape:connector-curvature="0" />
+    <path
+       id="path12058"
+       d="m 88.284483,158.4287 10.96248,-29.11512 12.474537,32.51819"
+       style="display:inline;fill:none;fill-rule:evenodd;stroke:#cc0000;stroke-width:1.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:0.99607843"
+       inkscape:connector-curvature="0" />
+    <path
+       id="path12250"
+       d="m 212.13974,133.78236 54.69043,-3.64603 -31.75647,27.04795"
+       style="display:inline;fill:none;fill-rule:evenodd;stroke:#cc0000;stroke-width:3;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:0.99607843"
+       inkscape:connector-curvature="0" />
+    <path
+       id="path5161"
+       d="m 399.11285,648.31931 50.5,-19.5 -14.05,28.1 0.925,-1.725 -5.875,11.75 -0.25,-0.75"
+       style="display:inline;opacity:1;fill:none;fill-opacity:1;stroke:#cc0000;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:0.99607843"
+       transform="translate(-387.41463,-542.5412)"
+       inkscape:connector-curvature="0" />
+    <path
+       id="path12206"
+       d="m 601.57854,741.42859 -2.26809,-64.28015"
+       style="display:inline;opacity:1;fill:#729fcf;fill-rule:evenodd;stroke:#cc0000;stroke-width:1.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:0.99607843"
+       transform="translate(-387.41463,-542.5412)"
+       inkscape:connector-curvature="0" />
+    <path
+       id="path5331"
+       d="m 189.57322,206.52811 -44,2.625 25.375,17.125 v 0"
+       style="fill:none;stroke:#cc0000;stroke-width:1.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:0.99607843"
+       inkscape:connector-curvature="0" />
+    <path
+       id="path9320"
+       d="m 475.69911,700.21367 24.57107,51.42411"
+       style="display:inline;opacity:1;fill:none;fill-rule:evenodd;stroke:#cc0000;stroke-width:3;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:0.99607843"
+       transform="translate(-387.41463,-542.5412)"
+       inkscape:connector-curvature="0" />
+    <path
+       id="path9322"
+       d="m 534.29164,751.63778 12.85257,40.08057"
+       style="display:inline;opacity:1;fill:none;fill-rule:evenodd;stroke:#cc0000;stroke-width:1.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:0.99607843"
+       transform="translate(-387.41463,-542.5412)"
+       inkscape:connector-curvature="0" />
+    <path
+       id="path9324"
+       d="m 525.21925,783.02162 0.37803,45.75234"
+       style="display:inline;opacity:1;fill:none;fill-rule:evenodd;stroke:#cc0000;stroke-width:1.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:0.99607843"
+       transform="translate(-387.41463,-542.5412)"
+       inkscape:connector-curvature="0" />
+    <path
+       id="path9326"
+       d="m 601.95657,742.56293 -12.09653,36.6775"
+       style="display:inline;opacity:1;fill:none;fill-rule:evenodd;stroke:#cc0000;stroke-width:1.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:0.99607843"
+       transform="translate(-387.41463,-542.5412)"
+       inkscape:connector-curvature="0" />
+    <path
+       id="path12060"
+       d="m 475.69911,700.59178 46.98395,22.0278 10.85256,28.26194"
+       style="display:inline;opacity:1;fill:none;fill-rule:evenodd;stroke:#cc0000;stroke-width:1.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:0.99607843"
+       transform="translate(-387.41463,-542.5412)"
+       inkscape:connector-curvature="0" />
+    <path
+       id="path12208"
+       d="m 589.104,778.86231 -12.85255,-66.17074 v 36.6775 z"
+       style="display:inline;opacity:1;fill:none;fill-rule:evenodd;stroke:#cc0000;stroke-width:1.58654225px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:0.99607843"
+       transform="translate(-387.41463,-542.5412)"
+       inkscape:connector-curvature="0" />
+    <path
+       id="path12210"
+       d="m 557.35064,768.27501 31.75336,10.5873"
+       style="display:inline;opacity:1;fill:none;fill-rule:evenodd;stroke:#cc0000;stroke-width:1.58654225px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:0.99607843"
+       transform="translate(-387.41463,-542.5412)"
+       inkscape:connector-curvature="0" />
+    <path
+       id="path12212"
+       d="m 500.27018,704.37298 v 48.77728 l 24.57105,30.2495 23.81505,9.45293"
+       style="display:inline;opacity:1;fill:none;fill-rule:evenodd;stroke:#cc0000;stroke-width:1.58654225px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:0.99607843"
+       transform="translate(-387.41463,-542.5412)"
+       inkscape:connector-curvature="0" />
+    <path
+       id="path12216"
+       d="m 524.46323,829.53019 44.98392,-0.37812"
+       style="display:inline;opacity:1;fill:none;fill-rule:evenodd;stroke:#cc0000;stroke-width:3;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:0.99607843"
+       transform="translate(-387.41463,-542.5412)"
+       inkscape:connector-curvature="0" />
+    <path
+       id="path5163"
+       d="m 694.61285,647.31931 -40.285,-17.00922 -4.715,-1.99078 29,57.5 v -0.5 0 h 0.5 v 0"
+       style="display:inline;opacity:1;fill:none;stroke:#cc0000;stroke-width:2.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:0.99607843"
+       transform="translate(-387.41463,-542.5412)"
+       inkscape:connector-curvature="0" />
+    <path
+       id="path12214"
+       d="m 409.92428,677.14844 54.05634,6.0499"
+       style="display:inline;opacity:1;fill:none;fill-rule:evenodd;stroke:#cc0000;stroke-width:1.58654225px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:0.99607843"
+       transform="translate(-387.41463,-542.5412)"
+       inkscape:connector-curvature="0" />
+  </g>
+  <g
+     id="g325"
+     style="display:none"
+     transform="translate(-80.31201,-294.38421)">
+    <ellipse
+       style="display:inline;opacity:1;fill:#ee0000;fill-opacity:1;stroke:#cc0000;stroke-width:0.39663559;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+       id="ellipse12254"
+       cx="568.98083"
+       cy="829.24042"
+       rx="4.1581793"
+       ry="4.1593032"
+       transform="translate(-387.41463,-542.5412)" />
+    <ellipse
+       cy="778.67493"
+       cx="588.85413"
+       id="ellipse12290"
+       style="display:inline;opacity:1;fill:#ee0000;fill-opacity:1;stroke:#cc0000;stroke-width:0.39663559;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+       rx="4.1581793"
+       ry="4.1593032"
+       transform="translate(-387.41463,-542.5412)" />
+    <ellipse
+       style="display:inline;opacity:1;fill:#ee0000;fill-opacity:1;stroke:#cc0000;stroke-width:0.39663559;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+       id="ellipse12284"
+       cx="601.57867"
+       cy="740.67249"
+       rx="4.1581793"
+       ry="4.1593032"
+       transform="translate(-387.41463,-542.5412)" />
+    <ellipse
+       cy="829.24042"
+       cx="525.79852"
+       id="ellipse12256"
+       style="display:inline;opacity:1;fill:#ee0000;fill-opacity:1;stroke:#cc0000;stroke-width:0.39663559;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+       rx="4.1581793"
+       ry="4.1593032"
+       transform="translate(-387.41463,-542.5412)" />
+    <ellipse
+       cy="768.71582"
+       cx="557.82654"
+       id="ellipse12306"
+       style="display:inline;opacity:1;fill:#ee0000;fill-opacity:1;stroke:#cc0000;stroke-width:0.39663559;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+       rx="4.1581793"
+       ry="4.1593032"
+       transform="translate(-387.41463,-542.5412)" />
+    <ellipse
+       style="display:inline;opacity:1;fill:#ee0000;fill-opacity:1;stroke:#cc0000;stroke-width:0.39663559;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+       id="ellipse12280"
+       cx="525.21936"
+       cy="783.02173"
+       rx="4.1581793"
+       ry="4.1593032"
+       transform="translate(-387.41463,-542.5412)" />
+    <ellipse
+       cy="647.34271"
+       cx="400.09586"
+       id="ellipse12258"
+       style="display:inline;opacity:1;fill:#ee0000;fill-opacity:1;stroke:#cc0000;stroke-width:0.39663559;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+       rx="4.1581793"
+       ry="4.1593032"
+       transform="translate(-387.41463,-542.5412)" />
+    <ellipse
+       cy="628.31934"
+       cx="450.11285"
+       id="ellipse12258-3"
+       style="display:inline;opacity:1;fill:#ee0000;fill-opacity:1;stroke:#cc0000;stroke-width:0.39663559;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+       rx="4.1581793"
+       ry="4.1593032"
+       transform="translate(-387.41463,-542.5412)" />
+    <ellipse
+       cy="699.45752"
+       cx="622.36951"
+       id="ellipse12294"
+       style="display:inline;opacity:1;fill:#ee0000;fill-opacity:1;stroke:#cc0000;stroke-width:0.39663559;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+       rx="4.1581793"
+       ry="4.1593032"
+       transform="translate(-387.41463,-542.5412)" />
+    <ellipse
+       cy="792.29773"
+       cx="547.21771"
+       id="ellipse12252"
+       style="display:inline;opacity:1;fill:#ee0000;fill-opacity:1;stroke:#cc0000;stroke-width:0.39663559;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+       rx="4.1581793"
+       ry="4.1593032"
+       transform="translate(-387.41463,-542.5412)" />
+    <ellipse
+       cy="800.12549"
+       cx="566.20697"
+       id="ellipse12282"
+       style="display:inline;opacity:1;fill:#ee0000;fill-opacity:1;stroke:#cc0000;stroke-width:0.39663559;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+       rx="4.1581793"
+       ry="4.1593032"
+       transform="translate(-387.41463,-542.5412)" />
+    <ellipse
+       style="display:inline;opacity:1;fill:#ee0000;fill-opacity:1;stroke:#cc0000;stroke-width:0.39663559;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+       id="ellipse12276"
+       cx="500.64822"
+       cy="751.63794"
+       rx="4.1581793"
+       ry="4.1593032"
+       transform="translate(-387.41463,-542.5412)" />
+    <ellipse
+       cy="751.72632"
+       cx="533.33447"
+       id="ellipse12278"
+       style="display:inline;opacity:1;fill:#ee0000;fill-opacity:1;stroke:#cc0000;stroke-width:0.39663559;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+       rx="4.1581793"
+       ry="4.1593032"
+       transform="translate(-387.41463,-542.5412)" />
+    <ellipse
+       cy="699.83545"
+       cx="450.75012"
+       id="ellipse12262"
+       style="display:inline;opacity:1;fill:#ee0000;fill-opacity:1;stroke:#cc0000;stroke-width:0.39663559;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+       rx="4.1581793"
+       ry="4.1593032"
+       transform="translate(-387.41463,-542.5412)" />
+    <ellipse
+       style="display:inline;opacity:1;fill:#ee0000;fill-opacity:1;stroke:#cc0000;stroke-width:0.39663559;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+       id="ellipse12268"
+       cx="476.07718"
+       cy="700.59174"
+       rx="4.1581793"
+       ry="4.1593032"
+       transform="translate(-387.41463,-542.5412)" />
+    <ellipse
+       cy="719.65314"
+       cx="521.49146"
+       id="ellipse12270"
+       style="display:inline;opacity:1;fill:#ee0000;fill-opacity:1;stroke:#cc0000;stroke-width:0.39663559;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+       rx="4.1581793"
+       ry="4.1593032"
+       transform="translate(-387.41463,-542.5412)" />
+    <ellipse
+       cy="703.87305"
+       cx="500.6362"
+       id="ellipse12274"
+       style="display:inline;opacity:1;fill:#ee0000;fill-opacity:1;stroke:#cc0000;stroke-width:0.39663559;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+       rx="4.1581793"
+       ry="4.1593032"
+       transform="translate(-387.41463,-542.5412)" />
+    <ellipse
+       style="display:inline;opacity:1;fill:#ee0000;fill-opacity:1;stroke:#cc0000;stroke-width:0.39663559;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+       id="ellipse12292"
+       cx="211.9584"
+       cy="134.28851"
+       rx="4.1581793"
+       ry="4.1593032" />
+    <ellipse
+       cy="713.44794"
+       cx="576.62964"
+       id="ellipse12286"
+       style="display:inline;opacity:1;fill:#ee0000;fill-opacity:1;stroke:#cc0000;stroke-width:0.39663559;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+       rx="4.1581793"
+       ry="4.1593032"
+       transform="translate(-387.41463,-542.5412)" />
+    <ellipse
+       style="display:inline;opacity:1;fill:#ee0000;fill-opacity:1;stroke:#cc0000;stroke-width:0.39663559;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+       id="ellipse12260"
+       cx="43.166531"
+       cy="123.16669"
+       rx="4.1581793"
+       ry="4.1593032" />
+    <ellipse
+       cy="129.43542"
+       cx="98.865997"
+       id="ellipse12266"
+       style="display:inline;opacity:1;fill:#ee0000;fill-opacity:1;stroke:#cc0000;stroke-width:0.39663559;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+       rx="4.1581793"
+       ry="4.1593032" />
+    <ellipse
+       style="display:inline;opacity:1;fill:#ee0000;fill-opacity:1;stroke:#cc0000;stroke-width:0.39663559;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+       id="ellipse12296"
+       cx="267.08618"
+       cy="130.05022"
+       rx="4.1581793"
+       ry="4.1593032" />
+    <ellipse
+       cy="686.22339"
+       cx="679.07196"
+       id="ellipse12298"
+       style="display:inline;opacity:1;fill:#ee0000;fill-opacity:1;stroke:#cc0000;stroke-width:0.39663559;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+       rx="4.1581793"
+       ry="4.1593032"
+       transform="translate(-387.41463,-542.5412)" />
+    <ellipse
+       style="display:inline;opacity:1;fill:#ee0000;fill-opacity:1;stroke:#cc0000;stroke-width:0.39663559;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+       id="ellipse12288"
+       cx="577.00763"
+       cy="748.99109"
+       rx="4.1581793"
+       ry="4.1593032"
+       transform="translate(-387.41463,-542.5412)" />
+    <ellipse
+       cy="748.99109"
+       cx="577.00763"
+       id="ellipse12302"
+       style="display:inline;opacity:1;fill:#ee0000;fill-opacity:1;stroke:#cc0000;stroke-width:0.39663559;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+       rx="4.1581793"
+       ry="4.1593032"
+       transform="translate(-387.41463,-542.5412)" />
+    <ellipse
+       style="display:inline;opacity:1;fill:#ee0000;fill-opacity:1;stroke:#cc0000;stroke-width:0.39663559;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+       id="ellipse12304"
+       cx="577.07013"
+       cy="748.99109"
+       rx="4.1581793"
+       ry="4.1593032"
+       transform="translate(-387.41463,-542.5412)" />
+    <ellipse
+       style="display:inline;opacity:1;fill:#ee0000;fill-opacity:1;stroke:#cc0000;stroke-width:0.39663559;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+       id="ellipse12264"
+       cx="22.887779"
+       cy="133.85095"
+       rx="4.1581793"
+       ry="4.1593032"
+       transform="translate(0,-3e-6)" />
+    <ellipse
+       style="display:inline;opacity:1;fill:#ee0000;fill-opacity:1;stroke:#cc0000;stroke-width:0.39663559;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+       id="ellipse12272"
+       cx="462.47165"
+       cy="682.1922"
+       rx="4.1581793"
+       ry="4.1593032"
+       transform="translate(-387.41463,-542.5412)" />
+    <ellipse
+       style="display:inline;opacity:1;fill:#ee0000;fill-opacity:1;stroke:#cc0000;stroke-width:0.39663559;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+       id="ellipse12300"
+       cx="694.58264"
+       cy="647.3053"
+       rx="4.1581793"
+       ry="4.1593032"
+       transform="translate(-387.41463,-542.5412)" />
+    <ellipse
+       cy="628.31934"
+       cx="649.61285"
+       id="ellipse12258-3-0"
+       style="display:inline;opacity:1;fill:#ee0000;fill-opacity:1;stroke:#cc0000;stroke-width:0.39663559;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+       rx="4.1581793"
+       ry="4.1593032"
+       transform="translate(-387.41463,-542.5412)" />
+  </g>
+  <g
+     transform="translate(-80.31201,-247.1061)"
+     style="display:none"
+     id="layer6">
+    <ellipse
+       cy="276.32968"
+       cx="159.80099"
+       id="ellipse12282-8-9-0"
+       style="display:inline;opacity:1;fill:#ee0000;fill-opacity:1;stroke:#ee0000;stroke-width:0.39663559;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.97635139"
+       rx="4.1581793"
+       ry="4.1593032" />
+    <ellipse
+       cy="259.99252"
+       cx="159.80099"
+       id="ellipse12282-8-9"
+       style="display:inline;opacity:1;fill:#ee0000;fill-opacity:1;stroke:#ee0000;stroke-width:0.39663559;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.97635139"
+       rx="4.1581793"
+       ry="4.1593032" />
+  </g>
+  <g
+     id="g975"
+     style="display:inline"
+     transform="translate(-467.72664,-836.92541)">
+    <g
+       id="text973"
+       style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:16.53852463px;line-height:125%;font-family:Ubuntu;-inkscape-font-specification:Ubuntu;letter-spacing:0px;word-spacing:0px;display:inline;opacity:1;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1.03365779px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;image-rendering:auto"
+       aria-label="gnu net">
+      <path
+         id="path977"
+         style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:50.66666794px;font-family:'Anonymous Pro';-inkscape-font-specification:'Anonymous Pro Bold';fill:#292929;fill-opacity:1;stroke-width:1.03365779px"
+         d="m 489.62118,868.96318 q 0,2.375 -0.81641,4.23046 -0.81641,1.85547 -2.30078,3.14193 -1.45964,1.28646 -3.46354,1.95443 -1.97917,0.69271 -4.42839,0.69271 -6.01172,0 -10.26693,-3.63672 l 2.42448,-3.95834 q 3.53776,3.04297 7.84245,3.04297 2.64714,0 4.25521,-1.31119 1.63281,-1.28646 1.63281,-4.0573 v -2.47395 q -1.58333,1.36067 -3.04297,2.02864 -1.45963,0.64323 -3.38932,0.64323 -2.22656,0 -4.13151,-0.9401 -1.90495,-0.94011 -3.29037,-2.54818 -1.36067,-1.63281 -2.15234,-3.78516 -0.76693,-2.15234 -0.76693,-4.57682 0,-2.42448 0.76693,-4.57682 0.79167,-2.17709 2.15234,-3.76042 1.38542,-1.60807 3.29037,-2.52344 1.90495,-0.9401 4.13151,-0.9401 1.92969,0 3.4388,0.66797 1.50912,0.64323 2.99349,1.95442 v -2.07812 h 5.1211 z m -5.1211,-16.67448 q -0.91536,-1.01433 -2.375,-1.53386 -1.43489,-0.54427 -2.79557,-0.54427 -2.89453,0 -4.70052,2.02865 -1.78125,2.02864 -1.78125,5.17057 0,1.55859 0.47005,2.89453 0.49479,1.3112 1.33594,2.27604 0.86588,0.96485 2.05338,1.53386 1.21224,0.54427 2.6224,0.54427 1.36068,0 2.79557,-0.54427 1.45964,-0.56901 2.375,-1.58334 z"
+         inkscape:connector-curvature="0" />
+      <path
+         id="path979"
+         style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:50.66666794px;font-family:'Anonymous Pro';-inkscape-font-specification:'Anonymous Pro Bold';fill:#292929;fill-opacity:1;stroke-width:1.03365779px"
+         d="m 514.82951,869.21057 h -5.12109 v -14.22526 q 0,-2.69661 -1.01433,-3.73568 -1.01432,-1.03906 -2.94401,-1.03906 -2.84505,0 -4.65104,2.30078 -1.78125,2.30078 -1.78125,6.35808 v 10.34114 h -5.12109 v -23.05729 h 5.12109 v 5.78906 q 0.76693,-2.99349 2.84505,-4.65104 2.07813,-1.68229 5.1211,-1.68229 3.53776,0 5.54166,2.30078 2.00391,2.30078 2.00391,7.07552 z"
+         inkscape:connector-curvature="0" />
+      <path
+         id="path981"
+         style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:50.66666794px;font-family:'Anonymous Pro';-inkscape-font-specification:'Anonymous Pro Bold';fill:#292929;fill-opacity:1;stroke-width:1.03365779px"
+         d="m 518.90503,846.15328 h 5.12109 v 14.25 q 0,2.67187 1.01433,3.71094 1.01432,1.03906 2.94401,1.03906 2.82031,0 4.6263,-2.30078 1.80599,-2.30078 1.80599,-6.35807 v -10.34115 h 5.12109 v 23.05729 h -5.12109 v -5.76432 q -0.76693,2.96875 -2.84505,4.65104 -2.07813,1.68229 -5.1211,1.68229 -3.53776,0 -5.54166,-2.30078 -2.00391,-2.32552 -2.00391,-7.07552 z"
+         inkscape:connector-curvature="0" />
+      <path
+         id="path983"
+         style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:50.66666794px;font-family:'Anonymous Pro';-inkscape-font-specification:'Anonymous Pro Bold';fill:#292929;fill-opacity:1;stroke-width:1.03365779px"
+         d="m 575.70451,869.21057 h -5.12109 v -14.22526 q 0,-2.69661 -1.01433,-3.73568 -1.01432,-1.03906 -2.94401,-1.03906 -2.84505,0 -4.65104,2.30078 -1.78125,2.30078 -1.78125,6.35808 v 10.34114 h -5.12109 v -23.05729 h 5.12109 v 5.78906 q 0.76693,-2.99349 2.84505,-4.65104 2.07813,-1.68229 5.1211,-1.68229 3.53776,0 5.54167,2.30078 2.0039,2.30078 2.0039,7.07552 z"
+         inkscape:connector-curvature="0" />
+      <path
+         id="path985"
+         style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:50.66666794px;font-family:'Anonymous Pro';-inkscape-font-specification:'Anonymous Pro Bold';fill:#292929;fill-opacity:1;stroke-width:1.03365779px"
+         d="m 583.76832,859.63635 q 0.37109,2.375 2.2513,3.95834 1.90495,1.55859 5.09635,1.55859 2.4987,0 4.32943,-0.76693 1.85547,-0.79166 3.19141,-2.07812 l 2.62239,3.61198 q -2.22656,2.22656 -4.72526,3.04297 -2.47396,0.8164 -5.41797,0.8164 -2.67187,0 -4.97265,-0.89062 -2.30079,-0.89063 -3.98308,-2.47396 -1.68229,-1.60807 -2.64713,-3.8099 -0.94011,-2.20182 -0.94011,-4.89844 0,-2.62239 0.86589,-4.82421 0.89062,-2.22657 2.47396,-3.83464 1.60807,-1.63281 3.83463,-2.52344 2.22657,-0.91536 4.92318,-0.91536 2.79557,0 5.07161,0.96484 2.27605,0.94011 3.88412,2.7461 1.63281,1.80599 2.54818,4.42838 0.91536,2.59766 0.91536,5.88802 z m 13.53255,-4.5026 q -0.39584,-2.22656 -2.30078,-3.5625 -1.90495,-1.36068 -4.32943,-1.36068 -2.42448,0 -4.35417,1.36068 -1.92968,1.33594 -2.32552,3.5625 z"
+         inkscape:connector-curvature="0" />
+      <path
+         id="path987"
+         style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:50.66666794px;font-family:'Anonymous Pro';-inkscape-font-specification:'Anonymous Pro Bold';fill:#292929;fill-opacity:1;stroke-width:1.03365779px"
+         d="m 627.08081,861.86291 q -0.39583,3.63672 -2.86979,5.78907 -2.44922,2.1276 -6.13542,2.1276 -2.02864,0 -3.71094,-0.66797 -1.68229,-0.66797 -2.86979,-1.85547 -1.1875,-1.1875 -1.85547,-2.84505 -0.64322,-1.68229 -0.64322,-3.66146 v -9.97005 h -5.22006 v -4.6263 h 5.22006 v -9.22787 h 5.12109 v 9.22787 h 9.67318 v 4.6263 h -9.67318 v 9.97005 q 0,2.22657 1.08854,3.31511 1.08854,1.08854 2.86979,1.08854 2.17709,0 3.24089,-1.26172 1.0638,-1.26172 1.26172,-3.04297 z"
+         inkscape:connector-curvature="0" />
+    </g>
+  </g>
+</svg>
diff --git a/contrib/branding/logo/gnunet-logo-dark-text.svg b/contrib/branding/logo/gnunet-logo-dark-text.svg
new file mode 100644
index 0000000000000000000000000000000000000000..5644e0ae7796b3fc049668e325da754b589b5b57
--- /dev/null
+++ b/contrib/branding/logo/gnunet-logo-dark-text.svg
@@ -0,0 +1,1411 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg
+   xmlns:dc="http://purl.org/dc/elements/1.1/"
+   xmlns:cc="http://creativecommons.org/ns#"
+   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+   xmlns:svg="http://www.w3.org/2000/svg"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:xlink="http://www.w3.org/1999/xlink"
+   version="1.1"
+   id="svg2"
+   height="280"
+   width="320">
+  <title
+     id="title3310">logo for GNUnet</title>
+  <defs
+     id="defs4">
+    <linearGradient
+       id="gnunet">
+      <stop
+         style="stop-color:#ff0000;stop-opacity:0.58431375;"
+         offset="0"
+         id="stop9516" />
+      <stop
+         style="stop-color:#ffcc00;stop-opacity:1;"
+         offset="1"
+         id="stop9518" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient4094">
+      <stop
+         style="stop-color:#232323;stop-opacity:1;"
+         offset="0"
+         id="stop4096" />
+      <stop
+         style="stop-color:#4d4d4d;stop-opacity:1;"
+         offset="1"
+         id="stop4098" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient4014">
+      <stop
+         style="stop-color:#a0a0a0;stop-opacity:1;"
+         offset="0"
+         id="stop4016" />
+      <stop
+         style="stop-color:#ffffff;stop-opacity:1;"
+         offset="1"
+         id="stop4018" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient4678">
+      <stop
+         style="stop-color:#e5e5e5;stop-opacity:1;"
+         offset="0"
+         id="stop4680" />
+      <stop
+         style="stop-color:#d3cdcd;stop-opacity:1;"
+         offset="1"
+         id="stop4682" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient4341">
+      <stop
+         id="stop4343"
+         offset="0"
+         style="stop-color:#333333;stop-opacity:1;" />
+      <stop
+         id="stop4345"
+         offset="1"
+         style="stop-color:#484848;stop-opacity:1;" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient4696-5">
+      <stop
+         id="stop4698-6"
+         offset="0"
+         style="stop-color:#ffb638;stop-opacity:1;" />
+      <stop
+         id="stop4700-2"
+         offset="1"
+         style="stop-color:#f0ae26;stop-opacity:1;" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient4702-3-6">
+      <stop
+         id="stop4704-1"
+         offset="0"
+         style="stop-color:#ff0000;stop-opacity:0.58431375;" />
+      <stop
+         id="stop4706-8"
+         offset="1"
+         style="stop-color:#ffcc00;stop-opacity:1;" />
+    </linearGradient>
+    <color-profile
+       name="Artifex-PS-CMYK-Profile"
+       xlink:href="/usr/share/color/icc/ghostscript/ps_cmyk.icc"
+       id="color-profile27" />
+    <linearGradient
+       y2="69.791016"
+       x2="177.04297"
+       y1="63.65625"
+       x1="142.96875"
+       gradientTransform="matrix(-0.88803314,0,0,0.88803314,595.57001,1106.9291)"
+       gradientUnits="userSpaceOnUse"
+       id="linearGradient3138"
+       xlink:href="#linearGradient4702-3-6" />
+    <linearGradient
+       y2="1043.709"
+       x2="80.655251"
+       y1="1025.709"
+       x1="108.08774"
+       gradientTransform="matrix(-0.49726789,0,0,0.49726789,555.31016,722.70088)"
+       gradientUnits="userSpaceOnUse"
+       id="linearGradient3141"
+       xlink:href="#linearGradient4696-5" />
+    <linearGradient
+       y2="922.07178"
+       x2="78.000107"
+       y1="1004.8033"
+       x1="113.5146"
+       gradientTransform="matrix(0.88803314,0,0,0.88803314,415.18739,350.00262)"
+       gradientUnits="userSpaceOnUse"
+       id="linearGradient3144"
+       xlink:href="#linearGradient4702-3-6" />
+    <linearGradient
+       y2="70.667412"
+       x2="176.60477"
+       y1="63.65625"
+       x1="142.96875"
+       gradientTransform="matrix(0.88803314,0,0,0.88803314,415.2161,1106.9294)"
+       gradientUnits="userSpaceOnUse"
+       id="linearGradient3148"
+       xlink:href="#linearGradient4702-3-6" />
+    <linearGradient
+       y2="70.667412"
+       x2="176.60477"
+       y1="63.65625"
+       x1="142.96875"
+       gradientTransform="matrix(0.88803314,0,0,0.88803314,415.2161,1106.9294)"
+       gradientUnits="userSpaceOnUse"
+       id="linearGradient3780"
+       xlink:href="#linearGradient4702-3-6" />
+    <linearGradient
+       y2="922.07178"
+       x2="78.000107"
+       y1="1004.8033"
+       x1="113.5146"
+       gradientTransform="matrix(0.88803314,0,0,0.88803314,415.18739,350.00262)"
+       gradientUnits="userSpaceOnUse"
+       id="linearGradient3782"
+       xlink:href="#linearGradient4702-3-6" />
+    <linearGradient
+       y2="1043.709"
+       x2="80.655251"
+       y1="1025.709"
+       x1="108.08774"
+       gradientTransform="matrix(-0.49726789,0,0,0.49726789,555.31016,722.70088)"
+       gradientUnits="userSpaceOnUse"
+       id="linearGradient3784"
+       xlink:href="#linearGradient4696-5" />
+    <linearGradient
+       y2="69.791016"
+       x2="177.04297"
+       y1="63.65625"
+       x1="142.96875"
+       gradientTransform="matrix(-0.88803314,0,0,0.88803314,595.57001,1106.9291)"
+       gradientUnits="userSpaceOnUse"
+       id="linearGradient3786"
+       xlink:href="#linearGradient4702-3-6" />
+    <filter
+       id="filter9204"
+       style="color-interpolation-filters:sRGB">
+      <feColorMatrix
+         id="feColorMatrix9194"
+         result="colormatrix"
+         values="1 0 0 0 0 0 1 0 0 0 0 0 1 0 0 -0.2125 -0.7154 -0.0721 1 0 "
+         in="SourceGraphic" />
+      <feComposite
+         k1="0"
+         id="feComposite9196"
+         result="composite"
+         k4="0"
+         k3="0"
+         k2="1"
+         operator="arithmetic"
+         in2="colormatrix"
+         in="SourceGraphic" />
+      <feGaussianBlur
+         id="feGaussianBlur9198"
+         result="blur1"
+         stdDeviation="5 0.01" />
+      <feGaussianBlur
+         id="feGaussianBlur9200"
+         result="blur2"
+         stdDeviation="0.01 5"
+         in="composite" />
+      <feBlend
+         id="feBlend9202"
+         result="blend"
+         mode="darken"
+         in2="blur1"
+         in="blur2" />
+    </filter>
+    <filter
+       id="filter9330"
+       style="color-interpolation-filters:sRGB">
+      <feGaussianBlur
+         id="feGaussianBlur9328"
+         result="blur"
+         stdDeviation="2 2" />
+    </filter>
+  </defs>
+  <metadata
+     id="metadata7">
+    <rdf:RDF>
+      <cc:Work
+         rdf:about="">
+        <dc:format>image/svg+xml</dc:format>
+        <dc:type
+           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+        <dc:title>logo for GNUnet</dc:title>
+        <dc:creator>
+          <cc:Agent>
+            <dc:title>Luis Felipe López Acevedo, Amirouche Boubekki, carlo von lynX</dc:title>
+          </cc:Agent>
+        </dc:creator>
+        <dc:rights>
+          <cc:Agent>
+            <dc:title>GNUnet e.V.</dc:title>
+          </cc:Agent>
+        </dc:rights>
+        <cc:license
+           rdf:resource="http://creativecommons.org/licenses/by-sa/4.0/" />
+        <dc:description />
+      </cc:Work>
+      <cc:License
+         rdf:about="http://creativecommons.org/licenses/by-sa/4.0/">
+        <cc:permits
+           rdf:resource="http://creativecommons.org/ns#Reproduction" />
+        <cc:permits
+           rdf:resource="http://creativecommons.org/ns#Distribution" />
+        <cc:requires
+           rdf:resource="http://creativecommons.org/ns#Notice" />
+        <cc:requires
+           rdf:resource="http://creativecommons.org/ns#Attribution" />
+        <cc:permits
+           rdf:resource="http://creativecommons.org/ns#DerivativeWorks" />
+        <cc:requires
+           rdf:resource="http://creativecommons.org/ns#ShareAlike" />
+      </cc:License>
+    </rdf:RDF>
+  </metadata>
+  <g
+     id="g5346"
+     style="display:none"
+     transform="translate(-387.41463,-609.81931)">
+    <text
+       xml:space="preserve"
+       style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:16.53852463px;line-height:125%;font-family:Ubuntu;-inkscape-font-specification:Ubuntu;letter-spacing:0px;word-spacing:0px;display:inline;opacity:1;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1.03365779px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+       x="453.95291"
+       y="869.96057"
+       id="text5344"><tspan
+         id="tspan5342"
+         x="453.95291"
+         y="869.96057"
+         style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:49.33333206px;font-family:'Ubuntu Bold';-inkscape-font-specification:'Ubuntu Bold, ';fill:#ffffff;stroke-width:1.03365779px"
+         dx="0 0 0">gnu net</tspan></text>
+  </g>
+  <g
+     transform="translate(-387.41463,-609.81931)"
+     style="display:none"
+     id="g950">
+    <text
+       id="text948"
+       y="869.21057"
+       x="467.77612"
+       style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:16.53852463px;line-height:125%;font-family:Ubuntu;-inkscape-font-specification:Ubuntu;letter-spacing:0px;word-spacing:0px;display:inline;opacity:1;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1.03365779px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+       xml:space="preserve"><tspan
+         dx="0 -2.5 -3 0 -19.25 -2.5 -3"
+         style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:50.66666794px;font-family:'Anonymous Pro';-inkscape-font-specification:'Anonymous Pro Bold';fill:#ffffff;stroke-width:1.03365779px"
+         y="869.21057"
+         x="467.77612"
+         id="tspan946">gnu net</tspan></text>
+  </g>
+  <g
+     id="g941"
+     style="display:none"
+     transform="translate(0,-20)">
+    <ellipse
+       ry="17.690269"
+       rx="17.68549"
+       style="display:inline;opacity:1;fill:#ee0000;fill-opacity:1;stroke:#ee0000;stroke-width:1.68696308;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.97635139"
+       id="ellipse937"
+       cx="157.97346"
+       cy="180.65355" />
+    <ellipse
+       ry="17.690269"
+       rx="17.68549"
+       style="display:inline;opacity:1;fill:#ee0000;fill-opacity:1;stroke:#ee0000;stroke-width:1.68696308;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.97635139"
+       id="ellipse939"
+       cx="157.97346"
+       cy="111.16864" />
+  </g>
+  <g
+     transform="translate(-387.41463,-609.81931)"
+     style="display:none"
+     id="g935">
+    <g
+       aria-label="gnu net"
+       style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:16.53852463px;line-height:125%;font-family:Ubuntu;-inkscape-font-specification:Ubuntu;letter-spacing:0px;word-spacing:0px;display:inline;opacity:1;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1.03365779px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;image-rendering:auto"
+       id="g933">
+      <path
+         d="m 423.90503,684.79003 h 22.14128 v 61.61056 q 0,11.55196 4.3855,16.04443 4.38546,4.49242 12.72857,4.49242 12.19374,0 20.00203,-9.94753 7.80828,-9.94753 7.80828,-27.48942 v -44.71046 h 22.14128 v 99.6893 h -22.14128 v -24.92231 q -3.31586,12.83553 -12.30071,20.10899 -8.98489,7.27346 -22.14132,7.27346 -15.29567,0 -23.95963,-9.94753 -8.664,-10.0545 -8.664,-30.59135 z"
+         style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:50.66666794px;font-family:'Anonymous Pro';-inkscape-font-specification:'Anonymous Pro Bold';fill:#ffffff;stroke-width:4.46906853px"
+         id="path925" />
+      <path
+         d="m 669.48029,784.47933 h -22.14128 v -61.50359 q 0,-11.65892 -4.3855,-16.15139 -4.38546,-4.49243 -12.72857,-4.49243 -12.30071,0 -20.10899,9.94753 -7.70132,9.94754 -7.70132,27.48947 v 44.71041 h -22.14128 v -99.6893 h 22.14128 v 25.02928 q 3.31586,-12.94249 12.30071,-20.10899 8.98489,-7.27346 22.14132,-7.27346 15.29567,0 23.95967,9.94753 8.66396,9.94753 8.66396,30.59135 z"
+         style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:50.66666794px;font-family:'Anonymous Pro';-inkscape-font-specification:'Anonymous Pro Bold';fill:#ffffff;stroke-width:4.46906853px"
+         id="path927" />
+    </g>
+  </g>
+  <g
+     id="g1296"
+     style="display:none"
+     transform="translate(0,-67.278107)">
+    <path
+       style="fill:none;stroke:#dddddd;stroke-width:1.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+       d="m 62.698223,85.778107 -39.5,48.000003 v 0 l -1,2"
+       id="path1256" />
+    <path
+       style="fill:none;stroke:#dddddd;stroke-width:2.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+       d="m 12.698223,104.77811 10,29 21,-10.5 v 0 0"
+       id="path1258" />
+    <path
+       style="display:inline;fill:none;fill-rule:evenodd;stroke:#dddddd;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+       d="m 11.809253,105.24526 63.6227,34.91188 23.31802,-11.09978 -35.03955,28.74946 11.86161,-17.77468 -53.18435,-5.79678 40.95076,23.69646 25.32406,0.49689 24.193047,3.02495 v 48.02104 l 21.04995,-32.14943 -20.559,-15.87161 32.52749,48.02104 -8.06937,31.38386 -24.94907,-31.76198 24.94907,77.51429 22.25436,-36.69889 21.97354,37.07701 -43.59987,-0.37188 41.32877,-28.87448 22.05899,-21.17152 -19.90986,50.171 -3.71591,-29.60613 -8.57843,-31.7682 -9.69437,24.71516 54.37611,-52.19866 -24.96716,8.94671 -18.39175,19.15282 18.27579,-55.07718 25.20812,27.362 20.66591,-41.35238 -46.00204,14.12783 22.94304,-37.07431 23.05297,23.0777 31.8814,-26.48075 40.07874,-25.58708 -15.26372,39.20869 -24.69305,-13.74039 -55.05634,4.03119 79.62738,9.58108 -56.57441,12.73416"
+       id="path1260" />
+    <path
+       style="display:inline;fill:none;fill-rule:evenodd;stroke:#dddddd;stroke-width:1.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+       d="m 98.868943,129.31358 37.045597,48.02106"
+       id="path1262" />
+    <path
+       style="display:inline;fill:none;fill-rule:evenodd;stroke:#dddddd;stroke-width:1.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+       d="m 88.284483,158.4287 10.96248,-29.11512 12.474537,32.51819"
+       id="path1264" />
+    <path
+       style="display:inline;fill:none;fill-rule:evenodd;stroke:#dddddd;stroke-width:3;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+       d="m 212.13974,133.78236 54.69043,-3.64603 -31.75647,27.04795"
+       id="path1266" />
+    <path
+       transform="translate(-387.41463,-542.5412)"
+       style="display:inline;opacity:1;fill:none;fill-opacity:1;stroke:#dddddd;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+       d="m 399.11285,648.31931 50.5,-19.5 -14.05,28.1 0.925,-1.725 -5.875,11.75 -0.25,-0.75"
+       id="path1268" />
+    <path
+       transform="translate(-387.41463,-542.5412)"
+       style="display:inline;opacity:1;fill:#729fcf;fill-rule:evenodd;stroke:#dddddd;stroke-width:1.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+       d="m 601.57854,741.42859 -2.26809,-64.28015"
+       id="path1270" />
+    <path
+       style="fill:none;stroke:#dddddd;stroke-width:1.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+       d="m 189.57322,206.52811 -44,2.625 25.375,17.125 v 0"
+       id="path1272" />
+    <path
+       transform="translate(-387.41463,-542.5412)"
+       style="display:inline;opacity:1;fill:none;fill-rule:evenodd;stroke:#dddddd;stroke-width:3;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+       d="m 475.69911,700.21367 24.57107,51.42411"
+       id="path1274" />
+    <path
+       transform="translate(-387.41463,-542.5412)"
+       style="display:inline;opacity:1;fill:none;fill-rule:evenodd;stroke:#dddddd;stroke-width:1.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+       d="m 534.29164,751.63778 12.85257,40.08057"
+       id="path1276" />
+    <path
+       transform="translate(-387.41463,-542.5412)"
+       style="display:inline;opacity:1;fill:none;fill-rule:evenodd;stroke:#dddddd;stroke-width:1.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+       d="m 525.21925,783.02162 0.37803,45.75234"
+       id="path1278" />
+    <path
+       transform="translate(-387.41463,-542.5412)"
+       style="display:inline;opacity:1;fill:none;fill-rule:evenodd;stroke:#dddddd;stroke-width:1.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+       d="m 601.95657,742.56293 -12.09653,36.6775"
+       id="path1280" />
+    <path
+       transform="translate(-387.41463,-542.5412)"
+       style="display:inline;opacity:1;fill:none;fill-rule:evenodd;stroke:#dddddd;stroke-width:1.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+       d="m 475.69911,700.59178 46.98395,22.0278 10.85256,28.26194"
+       id="path1282" />
+    <path
+       transform="translate(-387.41463,-542.5412)"
+       style="display:inline;opacity:1;fill:none;fill-rule:evenodd;stroke:#dddddd;stroke-width:1.58654225px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+       d="m 589.104,778.86231 -12.85255,-66.17074 v 36.6775 z"
+       id="path1284" />
+    <path
+       transform="translate(-387.41463,-542.5412)"
+       style="display:inline;opacity:1;fill:none;fill-rule:evenodd;stroke:#dddddd;stroke-width:1.58654225px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+       d="m 557.35064,768.27501 31.75336,10.5873"
+       id="path1286" />
+    <path
+       transform="translate(-387.41463,-542.5412)"
+       style="display:inline;opacity:1;fill:none;fill-rule:evenodd;stroke:#dddddd;stroke-width:1.58654225px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+       d="m 500.27018,704.37298 v 48.77728 l 24.57105,30.2495 23.81505,9.45293"
+       id="path1288" />
+    <path
+       transform="translate(-387.41463,-542.5412)"
+       style="display:inline;opacity:1;fill:none;fill-rule:evenodd;stroke:#dddddd;stroke-width:3;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+       d="m 524.46323,829.53019 44.98392,-0.37812"
+       id="path1290" />
+    <path
+       transform="translate(-387.41463,-542.5412)"
+       style="display:inline;opacity:1;fill:none;stroke:#dddddd;stroke-width:2.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+       d="m 694.61285,647.31931 -40.285,-17.00922 -4.715,-1.99078 29,57.5 v -0.5 0 h 0.5 v 0"
+       id="path1292" />
+    <path
+       transform="translate(-387.41463,-542.5412)"
+       style="display:inline;opacity:1;fill:none;fill-rule:evenodd;stroke:#dddddd;stroke-width:1.58654225px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+       d="m 409.92428,677.14844 54.05634,6.0499"
+       id="path1294" />
+  </g>
+  <g
+     transform="translate(0,-67.278107)"
+     style="display:none"
+     id="g1254">
+    <ellipse
+       transform="translate(-387.41463,-542.5412)"
+       ry="4.1593032"
+       rx="4.1581793"
+       cy="829.24042"
+       cx="568.98083"
+       id="ellipse1194"
+       style="display:inline;opacity:1;fill:#ffffff;fill-opacity:1;stroke:#eeeeee;stroke-width:0.39663559;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
+    <ellipse
+       transform="translate(-387.41463,-542.5412)"
+       ry="4.1593032"
+       rx="4.1581793"
+       style="display:inline;opacity:1;fill:#ffffff;fill-opacity:1;stroke:#eeeeee;stroke-width:0.39663559;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+       id="ellipse1196"
+       cx="588.85413"
+       cy="778.67493" />
+    <ellipse
+       transform="translate(-387.41463,-542.5412)"
+       ry="4.1593032"
+       rx="4.1581793"
+       cy="740.67249"
+       cx="601.57867"
+       id="ellipse1198"
+       style="display:inline;opacity:1;fill:#ffffff;fill-opacity:1;stroke:#eeeeee;stroke-width:0.39663559;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
+    <ellipse
+       transform="translate(-387.41463,-542.5412)"
+       ry="4.1593032"
+       rx="4.1581793"
+       style="display:inline;opacity:1;fill:#ffffff;fill-opacity:1;stroke:#eeeeee;stroke-width:0.39663559;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+       id="ellipse1200"
+       cx="525.79852"
+       cy="829.24042" />
+    <ellipse
+       transform="translate(-387.41463,-542.5412)"
+       ry="4.1593032"
+       rx="4.1581793"
+       style="display:inline;opacity:1;fill:#ffffff;fill-opacity:1;stroke:#eeeeee;stroke-width:0.39663559;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+       id="ellipse1202"
+       cx="557.82654"
+       cy="768.71582" />
+    <ellipse
+       transform="translate(-387.41463,-542.5412)"
+       ry="4.1593032"
+       rx="4.1581793"
+       cy="783.02173"
+       cx="525.21936"
+       id="ellipse1204"
+       style="display:inline;opacity:1;fill:#ffffff;fill-opacity:1;stroke:#eeeeee;stroke-width:0.39663559;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
+    <ellipse
+       transform="translate(-387.41463,-542.5412)"
+       ry="4.1593032"
+       rx="4.1581793"
+       style="display:inline;opacity:1;fill:#ffffff;fill-opacity:1;stroke:#eeeeee;stroke-width:0.39663559;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+       id="ellipse1206"
+       cx="400.09586"
+       cy="647.34271" />
+    <ellipse
+       transform="translate(-387.41463,-542.5412)"
+       ry="4.1593032"
+       rx="4.1581793"
+       style="display:inline;opacity:1;fill:#ffffff;fill-opacity:1;stroke:#eeeeee;stroke-width:0.39663559;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+       id="ellipse1208"
+       cx="450.11285"
+       cy="628.31934" />
+    <ellipse
+       transform="translate(-387.41463,-542.5412)"
+       ry="4.1593032"
+       rx="4.1581793"
+       style="display:inline;opacity:1;fill:#ffffff;fill-opacity:1;stroke:#eeeeee;stroke-width:0.39663559;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+       id="ellipse1210"
+       cx="622.36951"
+       cy="699.45752" />
+    <ellipse
+       transform="translate(-387.41463,-542.5412)"
+       ry="4.1593032"
+       rx="4.1581793"
+       style="display:inline;opacity:1;fill:#ffffff;fill-opacity:1;stroke:#eeeeee;stroke-width:0.39663559;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+       id="ellipse1212"
+       cx="547.21771"
+       cy="792.29773" />
+    <ellipse
+       transform="translate(-387.41463,-542.5412)"
+       ry="4.1593032"
+       rx="4.1581793"
+       style="display:inline;opacity:1;fill:#ffffff;fill-opacity:1;stroke:#eeeeee;stroke-width:0.39663559;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+       id="ellipse1214"
+       cx="566.20697"
+       cy="800.12549" />
+    <ellipse
+       transform="translate(-387.41463,-542.5412)"
+       ry="4.1593032"
+       rx="4.1581793"
+       cy="751.63794"
+       cx="500.64822"
+       id="ellipse1216"
+       style="display:inline;opacity:1;fill:#ffffff;fill-opacity:1;stroke:#eeeeee;stroke-width:0.39663559;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
+    <ellipse
+       transform="translate(-387.41463,-542.5412)"
+       ry="4.1593032"
+       rx="4.1581793"
+       style="display:inline;opacity:1;fill:#ffffff;fill-opacity:1;stroke:#eeeeee;stroke-width:0.39663559;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+       id="ellipse1218"
+       cx="533.33447"
+       cy="751.72632" />
+    <ellipse
+       transform="translate(-387.41463,-542.5412)"
+       ry="4.1593032"
+       rx="4.1581793"
+       style="display:inline;opacity:1;fill:#ffffff;fill-opacity:1;stroke:#eeeeee;stroke-width:0.39663559;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+       id="ellipse1220"
+       cx="450.75012"
+       cy="699.83545" />
+    <ellipse
+       transform="translate(-387.41463,-542.5412)"
+       ry="4.1593032"
+       rx="4.1581793"
+       cy="700.59174"
+       cx="476.07718"
+       id="ellipse1222"
+       style="display:inline;opacity:1;fill:#ffffff;fill-opacity:1;stroke:#eeeeee;stroke-width:0.39663559;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
+    <ellipse
+       transform="translate(-387.41463,-542.5412)"
+       ry="4.1593032"
+       rx="4.1581793"
+       style="display:inline;opacity:1;fill:#ffffff;fill-opacity:1;stroke:#eeeeee;stroke-width:0.39663559;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+       id="ellipse1224"
+       cx="521.49146"
+       cy="719.65314" />
+    <ellipse
+       transform="translate(-387.41463,-542.5412)"
+       ry="4.1593032"
+       rx="4.1581793"
+       style="display:inline;opacity:1;fill:#ffffff;fill-opacity:1;stroke:#eeeeee;stroke-width:0.39663559;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+       id="ellipse1226"
+       cx="500.6362"
+       cy="703.87305" />
+    <ellipse
+       ry="4.1593032"
+       rx="4.1581793"
+       cy="134.28851"
+       cx="211.9584"
+       id="ellipse1228"
+       style="display:inline;opacity:1;fill:#ffffff;fill-opacity:1;stroke:#eeeeee;stroke-width:0.39663559;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
+    <ellipse
+       transform="translate(-387.41463,-542.5412)"
+       ry="4.1593032"
+       rx="4.1581793"
+       style="display:inline;opacity:1;fill:#ffffff;fill-opacity:1;stroke:#eeeeee;stroke-width:0.39663559;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+       id="ellipse1230"
+       cx="576.62964"
+       cy="713.44794" />
+    <ellipse
+       ry="4.1593032"
+       rx="4.1581793"
+       cy="123.16669"
+       cx="43.166531"
+       id="ellipse1232"
+       style="display:inline;opacity:1;fill:#ffffff;fill-opacity:1;stroke:#eeeeee;stroke-width:0.39663559;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
+    <ellipse
+       ry="4.1593032"
+       rx="4.1581793"
+       style="display:inline;opacity:1;fill:#ffffff;fill-opacity:1;stroke:#eeeeee;stroke-width:0.39663559;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+       id="ellipse1234"
+       cx="98.865997"
+       cy="129.43542" />
+    <ellipse
+       ry="4.1593032"
+       rx="4.1581793"
+       cy="130.05022"
+       cx="267.08618"
+       id="ellipse1236"
+       style="display:inline;opacity:1;fill:#ffffff;fill-opacity:1;stroke:#eeeeee;stroke-width:0.39663559;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
+    <ellipse
+       transform="translate(-387.41463,-542.5412)"
+       ry="4.1593032"
+       rx="4.1581793"
+       style="display:inline;opacity:1;fill:#ffffff;fill-opacity:1;stroke:#eeeeee;stroke-width:0.39663559;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+       id="ellipse1238"
+       cx="679.07196"
+       cy="686.22339" />
+    <ellipse
+       transform="translate(-387.41463,-542.5412)"
+       ry="4.1593032"
+       rx="4.1581793"
+       cy="748.99109"
+       cx="577.00763"
+       id="ellipse1240"
+       style="display:inline;opacity:1;fill:#ffffff;fill-opacity:1;stroke:#eeeeee;stroke-width:0.39663559;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
+    <ellipse
+       transform="translate(-387.41463,-542.5412)"
+       ry="4.1593032"
+       rx="4.1581793"
+       style="display:inline;opacity:1;fill:#ffffff;fill-opacity:1;stroke:#eeeeee;stroke-width:0.39663559;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+       id="ellipse1242"
+       cx="577.00763"
+       cy="748.99109" />
+    <ellipse
+       transform="translate(-387.41463,-542.5412)"
+       ry="4.1593032"
+       rx="4.1581793"
+       cy="748.99109"
+       cx="577.07013"
+       id="ellipse1244"
+       style="display:inline;opacity:1;fill:#ffffff;fill-opacity:1;stroke:#eeeeee;stroke-width:0.39663559;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
+    <ellipse
+       transform="translate(0,-3e-6)"
+       ry="4.1593032"
+       rx="4.1581793"
+       cy="133.85095"
+       cx="22.887779"
+       id="ellipse1246"
+       style="display:inline;opacity:1;fill:#ffffff;fill-opacity:1;stroke:#eeeeee;stroke-width:0.39663559;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
+    <ellipse
+       transform="translate(-387.41463,-542.5412)"
+       ry="4.1593032"
+       rx="4.1581793"
+       cy="682.1922"
+       cx="462.47165"
+       id="ellipse1248"
+       style="display:inline;opacity:1;fill:#ffffff;fill-opacity:1;stroke:#eeeeee;stroke-width:0.39663559;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
+    <ellipse
+       transform="translate(-387.41463,-542.5412)"
+       ry="4.1593032"
+       rx="4.1581793"
+       cy="647.3053"
+       cx="694.58264"
+       id="ellipse1250"
+       style="display:inline;opacity:1;fill:#ffffff;fill-opacity:1;stroke:#eeeeee;stroke-width:0.39663559;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
+    <ellipse
+       transform="translate(-387.41463,-542.5412)"
+       ry="4.1593032"
+       rx="4.1581793"
+       style="display:inline;opacity:1;fill:#ffffff;fill-opacity:1;stroke:#eeeeee;stroke-width:0.39663559;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+       id="ellipse1252"
+       cx="649.61285"
+       cy="628.31934" />
+  </g>
+  <g
+     transform="translate(0,-67.278107)"
+     style="display:inline"
+     id="g1533">
+    <path
+       id="path1493"
+       d="m 62.698223,85.778107 -39.5,48.000003 v 0 l -1,2"
+       style="fill:none;stroke:#3399cc;stroke-width:1.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+    <path
+       id="path1495"
+       d="m 12.698223,104.77811 10,29 21,-10.5 v 0 0"
+       style="fill:none;stroke:#3399cc;stroke-width:2.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+    <path
+       id="path1497"
+       d="m 11.809253,105.24526 63.6227,34.91188 23.31802,-11.09978 -35.03955,28.74946 11.86161,-17.77468 -53.18435,-5.79678 40.95076,23.69646 25.32406,0.49689 24.193047,3.02495 v 48.02104 l 21.04995,-32.14943 -20.559,-15.87161 32.52749,48.02104 -8.06937,31.38386 -24.94907,-31.76198 24.94907,77.51429 22.25436,-36.69889 21.97354,37.07701 -43.59987,-0.37188 41.32877,-28.87448 22.05899,-21.17152 -19.90986,50.171 -3.71591,-29.60613 -8.57843,-31.7682 -9.69437,24.71516 54.37611,-52.19866 -24.96716,8.94671 -18.39175,19.15282 18.27579,-55.07718 25.20812,27.362 20.66591,-41.35238 -46.00204,14.12783 22.94304,-37.07431 23.05297,23.0777 31.8814,-26.48075 40.07874,-25.58708 -15.26372,39.20869 -24.69305,-13.74039 -55.05634,4.03119 79.62738,9.58108 -56.57441,12.73416"
+       style="display:inline;fill:none;fill-rule:evenodd;stroke:#3399cc;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+    <path
+       id="path1499"
+       d="m 98.868943,129.31358 37.045597,48.02106"
+       style="display:inline;fill:none;fill-rule:evenodd;stroke:#3399cc;stroke-width:1.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+    <path
+       id="path1501"
+       d="m 88.284483,158.4287 10.96248,-29.11512 12.474537,32.51819"
+       style="display:inline;fill:none;fill-rule:evenodd;stroke:#3399cc;stroke-width:1.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+    <path
+       id="path1503"
+       d="m 212.13974,133.78236 54.69043,-3.64603 -31.75647,27.04795"
+       style="display:inline;fill:none;fill-rule:evenodd;stroke:#3399cc;stroke-width:3;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+    <path
+       id="path1505"
+       d="m 399.11285,648.31931 50.5,-19.5 -14.05,28.1 0.925,-1.725 -5.875,11.75 -0.25,-0.75"
+       style="display:inline;opacity:1;fill:none;fill-opacity:1;stroke:#3399cc;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+       transform="translate(-387.41463,-542.5412)" />
+    <path
+       id="path1507"
+       d="m 601.57854,741.42859 -2.26809,-64.28015"
+       style="display:inline;opacity:1;fill:#729fcf;fill-rule:evenodd;stroke:#3399cc;stroke-width:1.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+       transform="translate(-387.41463,-542.5412)" />
+    <path
+       id="path1509"
+       d="m 189.57322,206.52811 -44,2.625 25.375,17.125 v 0"
+       style="fill:none;stroke:#3399cc;stroke-width:1.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+    <path
+       id="path1511"
+       d="m 475.69911,700.21367 24.57107,51.42411"
+       style="display:inline;opacity:1;fill:none;fill-rule:evenodd;stroke:#3399cc;stroke-width:3;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+       transform="translate(-387.41463,-542.5412)" />
+    <path
+       id="path1513"
+       d="m 534.29164,751.63778 12.85257,40.08057"
+       style="display:inline;opacity:1;fill:none;fill-rule:evenodd;stroke:#3399cc;stroke-width:1.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+       transform="translate(-387.41463,-542.5412)" />
+    <path
+       id="path1515"
+       d="m 525.21925,783.02162 0.37803,45.75234"
+       style="display:inline;opacity:1;fill:none;fill-rule:evenodd;stroke:#3399cc;stroke-width:1.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+       transform="translate(-387.41463,-542.5412)" />
+    <path
+       id="path1517"
+       d="m 601.95657,742.56293 -12.09653,36.6775"
+       style="display:inline;opacity:1;fill:none;fill-rule:evenodd;stroke:#3399cc;stroke-width:1.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+       transform="translate(-387.41463,-542.5412)" />
+    <path
+       id="path1519"
+       d="m 475.69911,700.59178 46.98395,22.0278 10.85256,28.26194"
+       style="display:inline;opacity:1;fill:none;fill-rule:evenodd;stroke:#3399cc;stroke-width:1.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+       transform="translate(-387.41463,-542.5412)" />
+    <path
+       id="path1521"
+       d="m 589.104,778.86231 -12.85255,-66.17074 v 36.6775 z"
+       style="display:inline;opacity:1;fill:none;fill-rule:evenodd;stroke:#3399cc;stroke-width:1.58654225px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+       transform="translate(-387.41463,-542.5412)" />
+    <path
+       id="path1523"
+       d="m 557.35064,768.27501 31.75336,10.5873"
+       style="display:inline;opacity:1;fill:none;fill-rule:evenodd;stroke:#3399cc;stroke-width:1.58654225px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+       transform="translate(-387.41463,-542.5412)" />
+    <path
+       id="path1525"
+       d="m 500.27018,704.37298 v 48.77728 l 24.57105,30.2495 23.81505,9.45293"
+       style="display:inline;opacity:1;fill:none;fill-rule:evenodd;stroke:#3399cc;stroke-width:1.58654225px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+       transform="translate(-387.41463,-542.5412)" />
+    <path
+       id="path1527"
+       d="m 524.46323,829.53019 44.98392,-0.37812"
+       style="display:inline;opacity:1;fill:none;fill-rule:evenodd;stroke:#3399cc;stroke-width:3;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+       transform="translate(-387.41463,-542.5412)" />
+    <path
+       id="path1529"
+       d="m 694.61285,647.31931 -40.285,-17.00922 -4.715,-1.99078 29,57.5 v -0.5 0 h 0.5 v 0"
+       style="display:inline;opacity:1;fill:none;stroke:#3399cc;stroke-width:2.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+       transform="translate(-387.41463,-542.5412)" />
+    <path
+       id="path1531"
+       d="m 409.92428,677.14844 54.05634,6.0499"
+       style="display:inline;opacity:1;fill:none;fill-rule:evenodd;stroke:#3399cc;stroke-width:1.58654225px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+       transform="translate(-387.41463,-542.5412)" />
+  </g>
+  <g
+     id="g1491"
+     style="display:inline"
+     transform="translate(0,-67.278107)">
+    <ellipse
+       style="display:inline;opacity:1;fill:#419edb;fill-opacity:1;stroke:#3399cc;stroke-width:0.39663559;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+       id="ellipse1431"
+       cx="568.98083"
+       cy="829.24042"
+       rx="4.1581793"
+       ry="4.1593032"
+       transform="translate(-387.41463,-542.5412)" />
+    <ellipse
+       cy="778.67493"
+       cx="588.85413"
+       id="ellipse1433"
+       style="display:inline;opacity:1;fill:#419edb;fill-opacity:1;stroke:#3399cc;stroke-width:0.39663559;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+       rx="4.1581793"
+       ry="4.1593032"
+       transform="translate(-387.41463,-542.5412)" />
+    <ellipse
+       style="display:inline;opacity:1;fill:#419edb;fill-opacity:1;stroke:#3399cc;stroke-width:0.39663559;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+       id="ellipse1435"
+       cx="601.57867"
+       cy="740.67249"
+       rx="4.1581793"
+       ry="4.1593032"
+       transform="translate(-387.41463,-542.5412)" />
+    <ellipse
+       cy="829.24042"
+       cx="525.79852"
+       id="ellipse1437"
+       style="display:inline;opacity:1;fill:#419edb;fill-opacity:1;stroke:#3399cc;stroke-width:0.39663559;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+       rx="4.1581793"
+       ry="4.1593032"
+       transform="translate(-387.41463,-542.5412)" />
+    <ellipse
+       cy="768.71582"
+       cx="557.82654"
+       id="ellipse1439"
+       style="display:inline;opacity:1;fill:#419edb;fill-opacity:1;stroke:#3399cc;stroke-width:0.39663559;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+       rx="4.1581793"
+       ry="4.1593032"
+       transform="translate(-387.41463,-542.5412)" />
+    <ellipse
+       style="display:inline;opacity:1;fill:#419edb;fill-opacity:1;stroke:#3399cc;stroke-width:0.39663559;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+       id="ellipse1441"
+       cx="525.21936"
+       cy="783.02173"
+       rx="4.1581793"
+       ry="4.1593032"
+       transform="translate(-387.41463,-542.5412)" />
+    <ellipse
+       cy="647.34271"
+       cx="400.09586"
+       id="ellipse1443"
+       style="display:inline;opacity:1;fill:#419edb;fill-opacity:1;stroke:#3399cc;stroke-width:0.39663559;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+       rx="4.1581793"
+       ry="4.1593032"
+       transform="translate(-387.41463,-542.5412)" />
+    <ellipse
+       cy="628.31934"
+       cx="450.11285"
+       id="ellipse1445"
+       style="display:inline;opacity:1;fill:#419edb;fill-opacity:1;stroke:#3399cc;stroke-width:0.39663559;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+       rx="4.1581793"
+       ry="4.1593032"
+       transform="translate(-387.41463,-542.5412)" />
+    <ellipse
+       cy="699.45752"
+       cx="622.36951"
+       id="ellipse1447"
+       style="display:inline;opacity:1;fill:#419edb;fill-opacity:1;stroke:#3399cc;stroke-width:0.39663559;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+       rx="4.1581793"
+       ry="4.1593032"
+       transform="translate(-387.41463,-542.5412)" />
+    <ellipse
+       cy="792.29773"
+       cx="547.21771"
+       id="ellipse1449"
+       style="display:inline;opacity:1;fill:#419edb;fill-opacity:1;stroke:#3399cc;stroke-width:0.39663559;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+       rx="4.1581793"
+       ry="4.1593032"
+       transform="translate(-387.41463,-542.5412)" />
+    <ellipse
+       cy="800.12549"
+       cx="566.20697"
+       id="ellipse1451"
+       style="display:inline;opacity:1;fill:#419edb;fill-opacity:1;stroke:#3399cc;stroke-width:0.39663559;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+       rx="4.1581793"
+       ry="4.1593032"
+       transform="translate(-387.41463,-542.5412)" />
+    <ellipse
+       style="display:inline;opacity:1;fill:#419edb;fill-opacity:1;stroke:#3399cc;stroke-width:0.39663559;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+       id="ellipse1453"
+       cx="500.64822"
+       cy="751.63794"
+       rx="4.1581793"
+       ry="4.1593032"
+       transform="translate(-387.41463,-542.5412)" />
+    <ellipse
+       cy="751.72632"
+       cx="533.33447"
+       id="ellipse1455"
+       style="display:inline;opacity:1;fill:#419edb;fill-opacity:1;stroke:#3399cc;stroke-width:0.39663559;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+       rx="4.1581793"
+       ry="4.1593032"
+       transform="translate(-387.41463,-542.5412)" />
+    <ellipse
+       cy="699.83545"
+       cx="450.75012"
+       id="ellipse1457"
+       style="display:inline;opacity:1;fill:#419edb;fill-opacity:1;stroke:#3399cc;stroke-width:0.39663559;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+       rx="4.1581793"
+       ry="4.1593032"
+       transform="translate(-387.41463,-542.5412)" />
+    <ellipse
+       style="display:inline;opacity:1;fill:#419edb;fill-opacity:1;stroke:#3399cc;stroke-width:0.39663559;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+       id="ellipse1459"
+       cx="476.07718"
+       cy="700.59174"
+       rx="4.1581793"
+       ry="4.1593032"
+       transform="translate(-387.41463,-542.5412)" />
+    <ellipse
+       cy="719.65314"
+       cx="521.49146"
+       id="ellipse1461"
+       style="display:inline;opacity:1;fill:#419edb;fill-opacity:1;stroke:#3399cc;stroke-width:0.39663559;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+       rx="4.1581793"
+       ry="4.1593032"
+       transform="translate(-387.41463,-542.5412)" />
+    <ellipse
+       cy="703.87305"
+       cx="500.6362"
+       id="ellipse1463"
+       style="display:inline;opacity:1;fill:#419edb;fill-opacity:1;stroke:#3399cc;stroke-width:0.39663559;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+       rx="4.1581793"
+       ry="4.1593032"
+       transform="translate(-387.41463,-542.5412)" />
+    <ellipse
+       style="display:inline;opacity:1;fill:#419edb;fill-opacity:1;stroke:#3399cc;stroke-width:0.39663559;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+       id="ellipse1465"
+       cx="211.9584"
+       cy="134.28851"
+       rx="4.1581793"
+       ry="4.1593032" />
+    <ellipse
+       cy="713.44794"
+       cx="576.62964"
+       id="ellipse1467"
+       style="display:inline;opacity:1;fill:#419edb;fill-opacity:1;stroke:#3399cc;stroke-width:0.39663559;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+       rx="4.1581793"
+       ry="4.1593032"
+       transform="translate(-387.41463,-542.5412)" />
+    <ellipse
+       style="display:inline;opacity:1;fill:#419edb;fill-opacity:1;stroke:#3399cc;stroke-width:0.39663559;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+       id="ellipse1469"
+       cx="43.166531"
+       cy="123.16669"
+       rx="4.1581793"
+       ry="4.1593032" />
+    <ellipse
+       cy="129.43542"
+       cx="98.865997"
+       id="ellipse1471"
+       style="display:inline;opacity:1;fill:#419edb;fill-opacity:1;stroke:#3399cc;stroke-width:0.39663559;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+       rx="4.1581793"
+       ry="4.1593032" />
+    <ellipse
+       style="display:inline;opacity:1;fill:#419edb;fill-opacity:1;stroke:#3399cc;stroke-width:0.39663559;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+       id="ellipse1473"
+       cx="267.08618"
+       cy="130.05022"
+       rx="4.1581793"
+       ry="4.1593032" />
+    <ellipse
+       cy="686.22339"
+       cx="679.07196"
+       id="ellipse1475"
+       style="display:inline;opacity:1;fill:#419edb;fill-opacity:1;stroke:#3399cc;stroke-width:0.39663559;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+       rx="4.1581793"
+       ry="4.1593032"
+       transform="translate(-387.41463,-542.5412)" />
+    <ellipse
+       style="display:inline;opacity:1;fill:#419edb;fill-opacity:1;stroke:#3399cc;stroke-width:0.39663559;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+       id="ellipse1477"
+       cx="577.00763"
+       cy="748.99109"
+       rx="4.1581793"
+       ry="4.1593032"
+       transform="translate(-387.41463,-542.5412)" />
+    <ellipse
+       cy="748.99109"
+       cx="577.00763"
+       id="ellipse1479"
+       style="display:inline;opacity:1;fill:#419edb;fill-opacity:1;stroke:#3399cc;stroke-width:0.39663559;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+       rx="4.1581793"
+       ry="4.1593032"
+       transform="translate(-387.41463,-542.5412)" />
+    <ellipse
+       style="display:inline;opacity:1;fill:#419edb;fill-opacity:1;stroke:#3399cc;stroke-width:0.39663559;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+       id="ellipse1481"
+       cx="577.07013"
+       cy="748.99109"
+       rx="4.1581793"
+       ry="4.1593032"
+       transform="translate(-387.41463,-542.5412)" />
+    <ellipse
+       style="display:inline;opacity:1;fill:#419edb;fill-opacity:1;stroke:#3399cc;stroke-width:0.39663559;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+       id="ellipse1483"
+       cx="22.887779"
+       cy="133.85095"
+       rx="4.1581793"
+       ry="4.1593032"
+       transform="translate(0,-3e-6)" />
+    <ellipse
+       style="display:inline;opacity:1;fill:#419edb;fill-opacity:1;stroke:#3399cc;stroke-width:0.39663559;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+       id="ellipse1485"
+       cx="462.47165"
+       cy="682.1922"
+       rx="4.1581793"
+       ry="4.1593032"
+       transform="translate(-387.41463,-542.5412)" />
+    <ellipse
+       style="display:inline;opacity:1;fill:#419edb;fill-opacity:1;stroke:#3399cc;stroke-width:0.39663559;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+       id="ellipse1487"
+       cx="694.58264"
+       cy="647.3053"
+       rx="4.1581793"
+       ry="4.1593032"
+       transform="translate(-387.41463,-542.5412)" />
+    <ellipse
+       cy="628.31934"
+       cx="649.61285"
+       id="ellipse1489"
+       style="display:inline;opacity:1;fill:#419edb;fill-opacity:1;stroke:#3399cc;stroke-width:0.39663559;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+       rx="4.1581793"
+       ry="4.1593032"
+       transform="translate(-387.41463,-542.5412)" />
+  </g>
+  <g
+     id="g1539"
+     style="display:inline"
+     transform="translate(0,-20)">
+    <ellipse
+       ry="4.1593032"
+       rx="4.1581793"
+       style="display:inline;opacity:1;fill:#3399cc;fill-opacity:1;stroke:#3399cc;stroke-width:0.39663559;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+       id="ellipse1535"
+       cx="159.80099"
+       cy="276.32968" />
+    <ellipse
+       ry="4.1593032"
+       rx="4.1581793"
+       style="display:inline;opacity:1;fill:#3399cc;fill-opacity:1;stroke:#3399cc;stroke-width:0.39663559;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+       id="ellipse1537"
+       cx="159.80099"
+       cy="259.99252" />
+  </g>
+  <g
+     transform="translate(0,-67.278107)"
+     style="display:none"
+     id="layer3">
+    <path
+       id="path5313"
+       d="m 62.698223,85.778107 -39.5,48.000003 v 0 l -1,2"
+       style="fill:none;stroke:#cc0000;stroke-width:1.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:0.99607843" />
+    <path
+       id="path5311"
+       d="m 12.698223,104.77811 10,29 21,-10.5 v 0 0"
+       style="fill:none;stroke:#cc0000;stroke-width:2.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:0.99607843" />
+    <path
+       id="path9316"
+       d="m 11.809253,105.24526 63.6227,34.91188 23.31802,-11.09978 -35.03955,28.74946 11.86161,-17.77468 -53.18435,-5.79678 40.95076,23.69646 25.32406,0.49689 24.193047,3.02495 v 48.02104 l 21.04995,-32.14943 -20.559,-15.87161 32.52749,48.02104 -8.06937,31.38386 -24.94907,-31.76198 24.94907,77.51429 22.25436,-36.69889 21.97354,37.07701 -43.59987,-0.37188 41.32877,-28.87448 22.05899,-21.17152 -19.90986,50.171 -3.71591,-29.60613 -8.57843,-31.7682 -9.69437,24.71516 54.37611,-52.19866 -24.96716,8.94671 -18.39175,19.15282 18.27579,-55.07718 25.20812,27.362 20.66591,-41.35238 -46.00204,14.12783 22.94304,-37.07431 23.05297,23.0777 31.8814,-26.48075 40.07874,-25.58708 -15.26372,39.20869 -24.69305,-13.74039 -55.05634,4.03119 79.62738,9.58108 -56.57441,12.73416"
+       style="display:inline;fill:none;fill-rule:evenodd;stroke:#cc0000;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:0.99607843" />
+    <path
+       id="path9318"
+       d="m 98.868943,129.31358 37.045597,48.02106"
+       style="display:inline;fill:none;fill-rule:evenodd;stroke:#cc0000;stroke-width:1.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:0.99607843" />
+    <path
+       id="path12058"
+       d="m 88.284483,158.4287 10.96248,-29.11512 12.474537,32.51819"
+       style="display:inline;fill:none;fill-rule:evenodd;stroke:#cc0000;stroke-width:1.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:0.99607843" />
+    <path
+       id="path12250"
+       d="m 212.13974,133.78236 54.69043,-3.64603 -31.75647,27.04795"
+       style="display:inline;fill:none;fill-rule:evenodd;stroke:#cc0000;stroke-width:3;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:0.99607843" />
+    <path
+       id="path5161"
+       d="m 399.11285,648.31931 50.5,-19.5 -14.05,28.1 0.925,-1.725 -5.875,11.75 -0.25,-0.75"
+       style="display:inline;opacity:1;fill:none;fill-opacity:1;stroke:#cc0000;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:0.99607843"
+       transform="translate(-387.41463,-542.5412)" />
+    <path
+       id="path12206"
+       d="m 601.57854,741.42859 -2.26809,-64.28015"
+       style="display:inline;opacity:1;fill:#729fcf;fill-rule:evenodd;stroke:#cc0000;stroke-width:1.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:0.99607843"
+       transform="translate(-387.41463,-542.5412)" />
+    <path
+       id="path5331"
+       d="m 189.57322,206.52811 -44,2.625 25.375,17.125 v 0"
+       style="fill:none;stroke:#cc0000;stroke-width:1.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:0.99607843" />
+    <path
+       id="path9320"
+       d="m 475.69911,700.21367 24.57107,51.42411"
+       style="display:inline;opacity:1;fill:none;fill-rule:evenodd;stroke:#cc0000;stroke-width:3;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:0.99607843"
+       transform="translate(-387.41463,-542.5412)" />
+    <path
+       id="path9322"
+       d="m 534.29164,751.63778 12.85257,40.08057"
+       style="display:inline;opacity:1;fill:none;fill-rule:evenodd;stroke:#cc0000;stroke-width:1.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:0.99607843"
+       transform="translate(-387.41463,-542.5412)" />
+    <path
+       id="path9324"
+       d="m 525.21925,783.02162 0.37803,45.75234"
+       style="display:inline;opacity:1;fill:none;fill-rule:evenodd;stroke:#cc0000;stroke-width:1.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:0.99607843"
+       transform="translate(-387.41463,-542.5412)" />
+    <path
+       id="path9326"
+       d="m 601.95657,742.56293 -12.09653,36.6775"
+       style="display:inline;opacity:1;fill:none;fill-rule:evenodd;stroke:#cc0000;stroke-width:1.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:0.99607843"
+       transform="translate(-387.41463,-542.5412)" />
+    <path
+       id="path12060"
+       d="m 475.69911,700.59178 46.98395,22.0278 10.85256,28.26194"
+       style="display:inline;opacity:1;fill:none;fill-rule:evenodd;stroke:#cc0000;stroke-width:1.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:0.99607843"
+       transform="translate(-387.41463,-542.5412)" />
+    <path
+       id="path12208"
+       d="m 589.104,778.86231 -12.85255,-66.17074 v 36.6775 z"
+       style="display:inline;opacity:1;fill:none;fill-rule:evenodd;stroke:#cc0000;stroke-width:1.58654225px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:0.99607843"
+       transform="translate(-387.41463,-542.5412)" />
+    <path
+       id="path12210"
+       d="m 557.35064,768.27501 31.75336,10.5873"
+       style="display:inline;opacity:1;fill:none;fill-rule:evenodd;stroke:#cc0000;stroke-width:1.58654225px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:0.99607843"
+       transform="translate(-387.41463,-542.5412)" />
+    <path
+       id="path12212"
+       d="m 500.27018,704.37298 v 48.77728 l 24.57105,30.2495 23.81505,9.45293"
+       style="display:inline;opacity:1;fill:none;fill-rule:evenodd;stroke:#cc0000;stroke-width:1.58654225px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:0.99607843"
+       transform="translate(-387.41463,-542.5412)" />
+    <path
+       id="path12216"
+       d="m 524.46323,829.53019 44.98392,-0.37812"
+       style="display:inline;opacity:1;fill:none;fill-rule:evenodd;stroke:#cc0000;stroke-width:3;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:0.99607843"
+       transform="translate(-387.41463,-542.5412)" />
+    <path
+       id="path5163"
+       d="m 694.61285,647.31931 -40.285,-17.00922 -4.715,-1.99078 29,57.5 v -0.5 0 h 0.5 v 0"
+       style="display:inline;opacity:1;fill:none;stroke:#cc0000;stroke-width:2.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:0.99607843"
+       transform="translate(-387.41463,-542.5412)" />
+    <path
+       id="path12214"
+       d="m 409.92428,677.14844 54.05634,6.0499"
+       style="display:inline;opacity:1;fill:none;fill-rule:evenodd;stroke:#cc0000;stroke-width:1.58654225px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:0.99607843"
+       transform="translate(-387.41463,-542.5412)" />
+  </g>
+  <g
+     id="g325"
+     style="display:none"
+     transform="translate(0,-67.278107)">
+    <ellipse
+       style="display:inline;opacity:1;fill:#ee0000;fill-opacity:1;stroke:#cc0000;stroke-width:0.39663559;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+       id="ellipse12254"
+       cx="568.98083"
+       cy="829.24042"
+       rx="4.1581793"
+       ry="4.1593032"
+       transform="translate(-387.41463,-542.5412)" />
+    <ellipse
+       cy="778.67493"
+       cx="588.85413"
+       id="ellipse12290"
+       style="display:inline;opacity:1;fill:#ee0000;fill-opacity:1;stroke:#cc0000;stroke-width:0.39663559;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+       rx="4.1581793"
+       ry="4.1593032"
+       transform="translate(-387.41463,-542.5412)" />
+    <ellipse
+       style="display:inline;opacity:1;fill:#ee0000;fill-opacity:1;stroke:#cc0000;stroke-width:0.39663559;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+       id="ellipse12284"
+       cx="601.57867"
+       cy="740.67249"
+       rx="4.1581793"
+       ry="4.1593032"
+       transform="translate(-387.41463,-542.5412)" />
+    <ellipse
+       cy="829.24042"
+       cx="525.79852"
+       id="ellipse12256"
+       style="display:inline;opacity:1;fill:#ee0000;fill-opacity:1;stroke:#cc0000;stroke-width:0.39663559;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+       rx="4.1581793"
+       ry="4.1593032"
+       transform="translate(-387.41463,-542.5412)" />
+    <ellipse
+       cy="768.71582"
+       cx="557.82654"
+       id="ellipse12306"
+       style="display:inline;opacity:1;fill:#ee0000;fill-opacity:1;stroke:#cc0000;stroke-width:0.39663559;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+       rx="4.1581793"
+       ry="4.1593032"
+       transform="translate(-387.41463,-542.5412)" />
+    <ellipse
+       style="display:inline;opacity:1;fill:#ee0000;fill-opacity:1;stroke:#cc0000;stroke-width:0.39663559;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+       id="ellipse12280"
+       cx="525.21936"
+       cy="783.02173"
+       rx="4.1581793"
+       ry="4.1593032"
+       transform="translate(-387.41463,-542.5412)" />
+    <ellipse
+       cy="647.34271"
+       cx="400.09586"
+       id="ellipse12258"
+       style="display:inline;opacity:1;fill:#ee0000;fill-opacity:1;stroke:#cc0000;stroke-width:0.39663559;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+       rx="4.1581793"
+       ry="4.1593032"
+       transform="translate(-387.41463,-542.5412)" />
+    <ellipse
+       cy="628.31934"
+       cx="450.11285"
+       id="ellipse12258-3"
+       style="display:inline;opacity:1;fill:#ee0000;fill-opacity:1;stroke:#cc0000;stroke-width:0.39663559;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+       rx="4.1581793"
+       ry="4.1593032"
+       transform="translate(-387.41463,-542.5412)" />
+    <ellipse
+       cy="699.45752"
+       cx="622.36951"
+       id="ellipse12294"
+       style="display:inline;opacity:1;fill:#ee0000;fill-opacity:1;stroke:#cc0000;stroke-width:0.39663559;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+       rx="4.1581793"
+       ry="4.1593032"
+       transform="translate(-387.41463,-542.5412)" />
+    <ellipse
+       cy="792.29773"
+       cx="547.21771"
+       id="ellipse12252"
+       style="display:inline;opacity:1;fill:#ee0000;fill-opacity:1;stroke:#cc0000;stroke-width:0.39663559;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+       rx="4.1581793"
+       ry="4.1593032"
+       transform="translate(-387.41463,-542.5412)" />
+    <ellipse
+       cy="800.12549"
+       cx="566.20697"
+       id="ellipse12282"
+       style="display:inline;opacity:1;fill:#ee0000;fill-opacity:1;stroke:#cc0000;stroke-width:0.39663559;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+       rx="4.1581793"
+       ry="4.1593032"
+       transform="translate(-387.41463,-542.5412)" />
+    <ellipse
+       style="display:inline;opacity:1;fill:#ee0000;fill-opacity:1;stroke:#cc0000;stroke-width:0.39663559;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+       id="ellipse12276"
+       cx="500.64822"
+       cy="751.63794"
+       rx="4.1581793"
+       ry="4.1593032"
+       transform="translate(-387.41463,-542.5412)" />
+    <ellipse
+       cy="751.72632"
+       cx="533.33447"
+       id="ellipse12278"
+       style="display:inline;opacity:1;fill:#ee0000;fill-opacity:1;stroke:#cc0000;stroke-width:0.39663559;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+       rx="4.1581793"
+       ry="4.1593032"
+       transform="translate(-387.41463,-542.5412)" />
+    <ellipse
+       cy="699.83545"
+       cx="450.75012"
+       id="ellipse12262"
+       style="display:inline;opacity:1;fill:#ee0000;fill-opacity:1;stroke:#cc0000;stroke-width:0.39663559;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+       rx="4.1581793"
+       ry="4.1593032"
+       transform="translate(-387.41463,-542.5412)" />
+    <ellipse
+       style="display:inline;opacity:1;fill:#ee0000;fill-opacity:1;stroke:#cc0000;stroke-width:0.39663559;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+       id="ellipse12268"
+       cx="476.07718"
+       cy="700.59174"
+       rx="4.1581793"
+       ry="4.1593032"
+       transform="translate(-387.41463,-542.5412)" />
+    <ellipse
+       cy="719.65314"
+       cx="521.49146"
+       id="ellipse12270"
+       style="display:inline;opacity:1;fill:#ee0000;fill-opacity:1;stroke:#cc0000;stroke-width:0.39663559;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+       rx="4.1581793"
+       ry="4.1593032"
+       transform="translate(-387.41463,-542.5412)" />
+    <ellipse
+       cy="703.87305"
+       cx="500.6362"
+       id="ellipse12274"
+       style="display:inline;opacity:1;fill:#ee0000;fill-opacity:1;stroke:#cc0000;stroke-width:0.39663559;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+       rx="4.1581793"
+       ry="4.1593032"
+       transform="translate(-387.41463,-542.5412)" />
+    <ellipse
+       style="display:inline;opacity:1;fill:#ee0000;fill-opacity:1;stroke:#cc0000;stroke-width:0.39663559;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+       id="ellipse12292"
+       cx="211.9584"
+       cy="134.28851"
+       rx="4.1581793"
+       ry="4.1593032" />
+    <ellipse
+       cy="713.44794"
+       cx="576.62964"
+       id="ellipse12286"
+       style="display:inline;opacity:1;fill:#ee0000;fill-opacity:1;stroke:#cc0000;stroke-width:0.39663559;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+       rx="4.1581793"
+       ry="4.1593032"
+       transform="translate(-387.41463,-542.5412)" />
+    <ellipse
+       style="display:inline;opacity:1;fill:#ee0000;fill-opacity:1;stroke:#cc0000;stroke-width:0.39663559;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+       id="ellipse12260"
+       cx="43.166531"
+       cy="123.16669"
+       rx="4.1581793"
+       ry="4.1593032" />
+    <ellipse
+       cy="129.43542"
+       cx="98.865997"
+       id="ellipse12266"
+       style="display:inline;opacity:1;fill:#ee0000;fill-opacity:1;stroke:#cc0000;stroke-width:0.39663559;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+       rx="4.1581793"
+       ry="4.1593032" />
+    <ellipse
+       style="display:inline;opacity:1;fill:#ee0000;fill-opacity:1;stroke:#cc0000;stroke-width:0.39663559;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+       id="ellipse12296"
+       cx="267.08618"
+       cy="130.05022"
+       rx="4.1581793"
+       ry="4.1593032" />
+    <ellipse
+       cy="686.22339"
+       cx="679.07196"
+       id="ellipse12298"
+       style="display:inline;opacity:1;fill:#ee0000;fill-opacity:1;stroke:#cc0000;stroke-width:0.39663559;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+       rx="4.1581793"
+       ry="4.1593032"
+       transform="translate(-387.41463,-542.5412)" />
+    <ellipse
+       style="display:inline;opacity:1;fill:#ee0000;fill-opacity:1;stroke:#cc0000;stroke-width:0.39663559;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+       id="ellipse12288"
+       cx="577.00763"
+       cy="748.99109"
+       rx="4.1581793"
+       ry="4.1593032"
+       transform="translate(-387.41463,-542.5412)" />
+    <ellipse
+       cy="748.99109"
+       cx="577.00763"
+       id="ellipse12302"
+       style="display:inline;opacity:1;fill:#ee0000;fill-opacity:1;stroke:#cc0000;stroke-width:0.39663559;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+       rx="4.1581793"
+       ry="4.1593032"
+       transform="translate(-387.41463,-542.5412)" />
+    <ellipse
+       style="display:inline;opacity:1;fill:#ee0000;fill-opacity:1;stroke:#cc0000;stroke-width:0.39663559;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+       id="ellipse12304"
+       cx="577.07013"
+       cy="748.99109"
+       rx="4.1581793"
+       ry="4.1593032"
+       transform="translate(-387.41463,-542.5412)" />
+    <ellipse
+       style="display:inline;opacity:1;fill:#ee0000;fill-opacity:1;stroke:#cc0000;stroke-width:0.39663559;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+       id="ellipse12264"
+       cx="22.887779"
+       cy="133.85095"
+       rx="4.1581793"
+       ry="4.1593032"
+       transform="translate(0,-3e-6)" />
+    <ellipse
+       style="display:inline;opacity:1;fill:#ee0000;fill-opacity:1;stroke:#cc0000;stroke-width:0.39663559;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+       id="ellipse12272"
+       cx="462.47165"
+       cy="682.1922"
+       rx="4.1581793"
+       ry="4.1593032"
+       transform="translate(-387.41463,-542.5412)" />
+    <ellipse
+       style="display:inline;opacity:1;fill:#ee0000;fill-opacity:1;stroke:#cc0000;stroke-width:0.39663559;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+       id="ellipse12300"
+       cx="694.58264"
+       cy="647.3053"
+       rx="4.1581793"
+       ry="4.1593032"
+       transform="translate(-387.41463,-542.5412)" />
+    <ellipse
+       cy="628.31934"
+       cx="649.61285"
+       id="ellipse12258-3-0"
+       style="display:inline;opacity:1;fill:#ee0000;fill-opacity:1;stroke:#cc0000;stroke-width:0.39663559;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+       rx="4.1581793"
+       ry="4.1593032"
+       transform="translate(-387.41463,-542.5412)" />
+  </g>
+  <g
+     transform="translate(0,-20)"
+     style="display:none"
+     id="layer6">
+    <ellipse
+       cy="276.32968"
+       cx="159.80099"
+       id="ellipse12282-8-9-0"
+       style="display:inline;opacity:1;fill:#ee0000;fill-opacity:1;stroke:#ee0000;stroke-width:0.39663559;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.97635139"
+       rx="4.1581793"
+       ry="4.1593032" />
+    <ellipse
+       cy="259.99252"
+       cx="159.80099"
+       id="ellipse12282-8-9"
+       style="display:inline;opacity:1;fill:#ee0000;fill-opacity:1;stroke:#ee0000;stroke-width:0.39663559;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.97635139"
+       rx="4.1581793"
+       ry="4.1593032" />
+  </g>
+  <g
+     id="g975"
+     style="display:inline"
+     transform="translate(-387.41463,-609.81931)">
+    <g
+       id="text973"
+       style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:16.53852463px;line-height:125%;font-family:Ubuntu;-inkscape-font-specification:Ubuntu;letter-spacing:0px;word-spacing:0px;display:inline;opacity:1;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1.03365779px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;image-rendering:auto"
+       aria-label="gnu net">
+      <path
+         id="path977"
+         style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:50.66666794px;font-family:'Anonymous Pro';-inkscape-font-specification:'Anonymous Pro Bold';fill:#292929;stroke-width:1.03365779px;fill-opacity:1"
+         d="m 489.62118,868.96318 q 0,2.375 -0.81641,4.23046 -0.81641,1.85547 -2.30078,3.14193 -1.45964,1.28646 -3.46354,1.95443 -1.97917,0.69271 -4.42839,0.69271 -6.01172,0 -10.26693,-3.63672 l 2.42448,-3.95834 q 3.53776,3.04297 7.84245,3.04297 2.64714,0 4.25521,-1.31119 1.63281,-1.28646 1.63281,-4.0573 v -2.47395 q -1.58333,1.36067 -3.04297,2.02864 -1.45963,0.64323 -3.38932,0.64323 -2.22656,0 -4.13151,-0.9401 -1.90495,-0.94011 -3.29037,-2.54818 -1.36067,-1.63281 -2.15234,-3.78516 -0.76693,-2.15234 -0.76693,-4.57682 0,-2.42448 0.76693,-4.57682 0.79167,-2.17709 2.15234,-3.76042 1.38542,-1.60807 3.29037,-2.52344 1.90495,-0.9401 4.13151,-0.9401 1.92969,0 3.4388,0.66797 1.50912,0.64323 2.99349,1.95442 v -2.07812 h 5.1211 z m -5.1211,-16.67448 q -0.91536,-1.01433 -2.375,-1.53386 -1.43489,-0.54427 -2.79557,-0.54427 -2.89453,0 -4.70052,2.02865 -1.78125,2.02864 -1.78125,5.17057 0,1.55859 0.47005,2.89453 0.49479,1.3112 1.33594,2.27604 0.86588,0.96485 2.05338,1.53386 1.21224,0.54427 2.6224,0.54427 1.36068,0 2.79557,-0.54427 1.45964,-0.56901 2.375,-1.58334 z" />
+      <path
+         id="path979"
+         style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:50.66666794px;font-family:'Anonymous Pro';-inkscape-font-specification:'Anonymous Pro Bold';fill:#292929;stroke-width:1.03365779px;fill-opacity:1"
+         d="m 514.82951,869.21057 h -5.12109 v -14.22526 q 0,-2.69661 -1.01433,-3.73568 -1.01432,-1.03906 -2.94401,-1.03906 -2.84505,0 -4.65104,2.30078 -1.78125,2.30078 -1.78125,6.35808 v 10.34114 h -5.12109 v -23.05729 h 5.12109 v 5.78906 q 0.76693,-2.99349 2.84505,-4.65104 2.07813,-1.68229 5.1211,-1.68229 3.53776,0 5.54166,2.30078 2.00391,2.30078 2.00391,7.07552 z" />
+      <path
+         id="path981"
+         style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:50.66666794px;font-family:'Anonymous Pro';-inkscape-font-specification:'Anonymous Pro Bold';fill:#292929;stroke-width:1.03365779px;fill-opacity:1"
+         d="m 518.90503,846.15328 h 5.12109 v 14.25 q 0,2.67187 1.01433,3.71094 1.01432,1.03906 2.94401,1.03906 2.82031,0 4.6263,-2.30078 1.80599,-2.30078 1.80599,-6.35807 v -10.34115 h 5.12109 v 23.05729 h -5.12109 v -5.76432 q -0.76693,2.96875 -2.84505,4.65104 -2.07813,1.68229 -5.1211,1.68229 -3.53776,0 -5.54166,-2.30078 -2.00391,-2.32552 -2.00391,-7.07552 z" />
+      <path
+         id="path983"
+         style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:50.66666794px;font-family:'Anonymous Pro';-inkscape-font-specification:'Anonymous Pro Bold';fill:#292929;stroke-width:1.03365779px;fill-opacity:1"
+         d="m 575.70451,869.21057 h -5.12109 v -14.22526 q 0,-2.69661 -1.01433,-3.73568 -1.01432,-1.03906 -2.94401,-1.03906 -2.84505,0 -4.65104,2.30078 -1.78125,2.30078 -1.78125,6.35808 v 10.34114 h -5.12109 v -23.05729 h 5.12109 v 5.78906 q 0.76693,-2.99349 2.84505,-4.65104 2.07813,-1.68229 5.1211,-1.68229 3.53776,0 5.54167,2.30078 2.0039,2.30078 2.0039,7.07552 z" />
+      <path
+         id="path985"
+         style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:50.66666794px;font-family:'Anonymous Pro';-inkscape-font-specification:'Anonymous Pro Bold';fill:#292929;stroke-width:1.03365779px;fill-opacity:1"
+         d="m 583.76832,859.63635 q 0.37109,2.375 2.2513,3.95834 1.90495,1.55859 5.09635,1.55859 2.4987,0 4.32943,-0.76693 1.85547,-0.79166 3.19141,-2.07812 l 2.62239,3.61198 q -2.22656,2.22656 -4.72526,3.04297 -2.47396,0.8164 -5.41797,0.8164 -2.67187,0 -4.97265,-0.89062 -2.30079,-0.89063 -3.98308,-2.47396 -1.68229,-1.60807 -2.64713,-3.8099 -0.94011,-2.20182 -0.94011,-4.89844 0,-2.62239 0.86589,-4.82421 0.89062,-2.22657 2.47396,-3.83464 1.60807,-1.63281 3.83463,-2.52344 2.22657,-0.91536 4.92318,-0.91536 2.79557,0 5.07161,0.96484 2.27605,0.94011 3.88412,2.7461 1.63281,1.80599 2.54818,4.42838 0.91536,2.59766 0.91536,5.88802 z m 13.53255,-4.5026 q -0.39584,-2.22656 -2.30078,-3.5625 -1.90495,-1.36068 -4.32943,-1.36068 -2.42448,0 -4.35417,1.36068 -1.92968,1.33594 -2.32552,3.5625 z" />
+      <path
+         id="path987"
+         style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:50.66666794px;font-family:'Anonymous Pro';-inkscape-font-specification:'Anonymous Pro Bold';fill:#292929;stroke-width:1.03365779px;fill-opacity:1"
+         d="m 627.08081,861.86291 q -0.39583,3.63672 -2.86979,5.78907 -2.44922,2.1276 -6.13542,2.1276 -2.02864,0 -3.71094,-0.66797 -1.68229,-0.66797 -2.86979,-1.85547 -1.1875,-1.1875 -1.85547,-2.84505 -0.64322,-1.68229 -0.64322,-3.66146 v -9.97005 h -5.22006 v -4.6263 h 5.22006 v -9.22787 h 5.12109 v 9.22787 h 9.67318 v 4.6263 h -9.67318 v 9.97005 q 0,2.22657 1.08854,3.31511 1.08854,1.08854 2.86979,1.08854 2.17709,0 3.24089,-1.26172 1.0638,-1.26172 1.26172,-3.04297 z" />
+    </g>
+  </g>
+</svg>
diff --git a/contrib/branding/logo/lynXified-amirouche-anonymous-v3.png b/contrib/branding/logo/lynXified-amirouche-anonymous-v3.png
new file mode 100644
index 0000000000000000000000000000000000000000..52d7b24fdce1aa41b3ef6287bb01fe4a4a4e4b37
Binary files /dev/null and b/contrib/branding/logo/lynXified-amirouche-anonymous-v3.png differ
diff --git a/contrib/branding/logo/lynXified-amirouche-v3.svg b/contrib/branding/logo/lynXified-amirouche-v3.svg
new file mode 100644
index 0000000000000000000000000000000000000000..b8dd1ac67a332e4e25eab3b5eb6c75fb7b47f4bd
--- /dev/null
+++ b/contrib/branding/logo/lynXified-amirouche-v3.svg
@@ -0,0 +1,918 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+   xmlns:dc="http://purl.org/dc/elements/1.1/"
+   xmlns:cc="http://creativecommons.org/ns#"
+   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+   xmlns:svg="http://www.w3.org/2000/svg"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:xlink="http://www.w3.org/1999/xlink"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   width="400"
+   height="300"
+   id="svg2"
+   version="1.1"
+   inkscape:version="0.92.2 5c3e80d, 2017-08-06"
+   sodipodi:docname="lynXified-amirouche-v3.svg"
+   inkscape:export-filename="lynXified-amirouche-anonymous-v3.png"
+   inkscape:export-xdpi="192"
+   inkscape:export-ydpi="192">
+  <title
+     id="title3310">Guix System Distribution (Logo)</title>
+  <defs
+     id="defs4">
+    <linearGradient
+       id="gnunet">
+      <stop
+         id="stop9516"
+         offset="0"
+         style="stop-color:#ff0000;stop-opacity:0.58431375;" />
+      <stop
+         id="stop9518"
+         offset="1"
+         style="stop-color:#ffcc00;stop-opacity:1;" />
+    </linearGradient>
+    <inkscape:path-effect
+       effect="vonkoch"
+       id="path-effect8912"
+       is_visible="true"
+       ref_path="m 386.97986,1494.3277 h 79.02013"
+       generator="m 386.97986,1552.8408 h 26.34004 m 26.34005,0 h 26.34004"
+       similar_only="false"
+       nbgenerations="1"
+       drawall="true"
+       maxComplexity="1000" />
+    <linearGradient
+       id="linearGradient4094">
+      <stop
+         id="stop4096"
+         offset="0"
+         style="stop-color:#232323;stop-opacity:1;" />
+      <stop
+         id="stop4098"
+         offset="1"
+         style="stop-color:#4d4d4d;stop-opacity:1;" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient4014">
+      <stop
+         id="stop4016"
+         offset="0"
+         style="stop-color:#a0a0a0;stop-opacity:1;" />
+      <stop
+         id="stop4018"
+         offset="1"
+         style="stop-color:#ffffff;stop-opacity:1;" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient4678">
+      <stop
+         id="stop4680"
+         offset="0"
+         style="stop-color:#e5e5e5;stop-opacity:1;" />
+      <stop
+         id="stop4682"
+         offset="1"
+         style="stop-color:#d3cdcd;stop-opacity:1;" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient4341">
+      <stop
+         style="stop-color:#333333;stop-opacity:1;"
+         offset="0"
+         id="stop4343" />
+      <stop
+         style="stop-color:#484848;stop-opacity:1;"
+         offset="1"
+         id="stop4345" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient4696-5">
+      <stop
+         style="stop-color:#ffb638;stop-opacity:1;"
+         offset="0"
+         id="stop4698-6" />
+      <stop
+         style="stop-color:#f0ae26;stop-opacity:1;"
+         offset="1"
+         id="stop4700-2" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient4702-3-6">
+      <stop
+         style="stop-color:#ff0000;stop-opacity:0.58431375;"
+         offset="0"
+         id="stop4704-1" />
+      <stop
+         style="stop-color:#ffcc00;stop-opacity:1;"
+         offset="1"
+         id="stop4706-8" />
+    </linearGradient>
+    <color-profile
+       id="color-profile26"
+       xlink:href="/usr/share/color/icc/ghostscript/ps_cmyk.icc"
+       name="Artifex-PS-CMYK-Profile" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient4702-3-6"
+       id="linearGradient3138"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(-0.88803314,0,0,0.88803314,595.57001,1106.9291)"
+       x1="142.96875"
+       y1="63.65625"
+       x2="177.04297"
+       y2="69.791016" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient4696-5"
+       id="linearGradient3141"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(-0.49726789,0,0,0.49726789,555.31016,722.70088)"
+       x1="108.08774"
+       y1="1025.709"
+       x2="80.655251"
+       y2="1043.709" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient4702-3-6"
+       id="linearGradient3144"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(0.88803314,0,0,0.88803314,415.18739,350.00262)"
+       x1="113.5146"
+       y1="1004.8033"
+       x2="78.000107"
+       y2="922.07178" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient4702-3-6"
+       id="linearGradient3148"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(0.88803314,0,0,0.88803314,415.2161,1106.9294)"
+       x1="142.96875"
+       y1="63.65625"
+       x2="176.60477"
+       y2="70.667412" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient4702-3-6"
+       id="linearGradient3780"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(0.88803314,0,0,0.88803314,415.2161,1106.9294)"
+       x1="142.96875"
+       y1="63.65625"
+       x2="176.60477"
+       y2="70.667412" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient4702-3-6"
+       id="linearGradient3782"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(0.88803314,0,0,0.88803314,415.18739,350.00262)"
+       x1="113.5146"
+       y1="1004.8033"
+       x2="78.000107"
+       y2="922.07178" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient4696-5"
+       id="linearGradient3784"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(-0.49726789,0,0,0.49726789,555.31016,722.70088)"
+       x1="108.08774"
+       y1="1025.709"
+       x2="80.655251"
+       y2="1043.709" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient4702-3-6"
+       id="linearGradient3786"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(-0.88803314,0,0,0.88803314,595.57001,1106.9291)"
+       x1="142.96875"
+       y1="63.65625"
+       x2="177.04297"
+       y2="69.791016" />
+    <filter
+       style="color-interpolation-filters:sRGB"
+       inkscape:label="Cross Blur"
+       id="filter9204">
+      <feColorMatrix
+         in="SourceGraphic"
+         values="1 0 0 0 0 0 1 0 0 0 0 0 1 0 0 -0.2125 -0.7154 -0.0721 1 0 "
+         result="colormatrix"
+         id="feColorMatrix9194" />
+      <feComposite
+         in="SourceGraphic"
+         in2="colormatrix"
+         operator="arithmetic"
+         k2="1"
+         k3="0"
+         k4="0"
+         result="composite"
+         id="feComposite9196"
+         k1="0" />
+      <feGaussianBlur
+         stdDeviation="5 0.01"
+         result="blur1"
+         id="feGaussianBlur9198" />
+      <feGaussianBlur
+         in="composite"
+         stdDeviation="0.01 5"
+         result="blur2"
+         id="feGaussianBlur9200" />
+      <feBlend
+         in="blur2"
+         in2="blur1"
+         mode="darken"
+         result="blend"
+         id="feBlend9202" />
+    </filter>
+    <filter
+       style="color-interpolation-filters:sRGB"
+       inkscape:label="Blur"
+       id="filter9330">
+      <feGaussianBlur
+         stdDeviation="2 2"
+         result="blur"
+         id="feGaussianBlur9328" />
+    </filter>
+  </defs>
+  <sodipodi:namedview
+     id="base"
+     pagecolor="#ffffff"
+     bordercolor="#e73520"
+     borderopacity="1"
+     inkscape:pageopacity="0.0"
+     inkscape:pageshadow="2"
+     inkscape:zoom="2"
+     inkscape:cx="185.65271"
+     inkscape:cy="142.71577"
+     inkscape:document-units="px"
+     inkscape:current-layer="g950"
+     showgrid="true"
+     inkscape:window-width="1600"
+     inkscape:window-height="835"
+     inkscape:window-x="0"
+     inkscape:window-y="0"
+     inkscape:window-maximized="1"
+     inkscape:showpageshadow="false"
+     showborder="true"
+     borderlayer="true"
+     inkscape:object-nodes="true"
+     inkscape:snap-global="true"
+     showguides="true"
+     inkscape:guide-bbox="true"
+     objecttolerance="20"
+     inkscape:snap-tangential="true"
+     inkscape:snap-perpendicular="true"
+     inkscape:pagecheckerboard="true"
+     fit-margin-top="10"
+     fit-margin-left="10"
+     fit-margin-right="10"
+     fit-margin-bottom="10"
+     inkscape:snap-path-clip="true"
+     inkscape:snap-path-mask="true">
+    <sodipodi:guide
+       position="-307.43549,820.27825"
+       orientation="1,0"
+       id="guide5092"
+       inkscape:locked="false" />
+    <inkscape:grid
+       type="xygrid"
+       id="grid8783"
+       originx="0"
+       originy="0"
+       spacingx="5"
+       spacingy="5" />
+    <sodipodi:guide
+       position="-280.81043,809.79316"
+       orientation="0,1"
+       id="guide8844"
+       inkscape:locked="false" />
+    <sodipodi:guide
+       position="-297.44255,799.75126"
+       orientation="1,0"
+       id="guide8846"
+       inkscape:locked="false" />
+    <sodipodi:guide
+       position="-286.44639,799.75126"
+       orientation="0,1"
+       id="guide8864"
+       inkscape:locked="false" />
+    <sodipodi:guide
+       position="-227.46698,708.44981"
+       orientation="1,0"
+       id="guide8874"
+       inkscape:locked="false" />
+    <sodipodi:guide
+       position="-217.47047,677.79384"
+       orientation="1,0"
+       id="guide8876"
+       inkscape:locked="false" />
+    <sodipodi:guide
+       position="-219.46978,729.7757"
+       orientation="0,1"
+       id="guide8878"
+       inkscape:locked="false" />
+    <sodipodi:guide
+       position="-158.75928,719.78633"
+       orientation="0,1"
+       id="guide8896"
+       inkscape:locked="false" />
+    <sodipodi:guide
+       position="-147.49491,703.61816"
+       orientation="1,0"
+       id="guide8922"
+       inkscape:locked="false" />
+    <sodipodi:guide
+       position="-213.42311,880.00792"
+       orientation="0,1"
+       id="guide8924"
+       inkscape:locked="false" />
+    <sodipodi:guide
+       position="-357.88081,649.83162"
+       orientation="0,1"
+       id="guide8926"
+       inkscape:locked="false" />
+    <sodipodi:guide
+       position="-137.55348,605.74624"
+       orientation="1,0"
+       id="guide8991"
+       inkscape:locked="false" />
+    <sodipodi:guide
+       position="-231.80147,639.67552"
+       orientation="0,1"
+       id="guide8993"
+       inkscape:locked="false" />
+    <sodipodi:guide
+       position="-285.31397,844.81632"
+       orientation="0,1"
+       id="guide9013"
+       inkscape:locked="false" />
+    <sodipodi:guide
+       position="200,352"
+       orientation="1,0"
+       id="guide5070"
+       inkscape:locked="false" />
+    <sodipodi:guide
+       position="50,215"
+       orientation="1,0"
+       id="guide5335"
+       inkscape:locked="false" />
+    <sodipodi:guide
+       position="350,137"
+       orientation="1,0"
+       id="guide5337"
+       inkscape:locked="false" />
+    <sodipodi:guide
+       position="10,275.5"
+       orientation="1,0"
+       id="guide5354"
+       inkscape:locked="false" />
+    <sodipodi:guide
+       position="203.46998,66.733203"
+       orientation="0,1"
+       id="guide5358"
+       inkscape:locked="false" />
+  </sodipodi:namedview>
+  <metadata
+     id="metadata7">
+    <rdf:RDF>
+      <cc:Work
+         rdf:about="">
+        <dc:format>image/svg+xml</dc:format>
+        <dc:type
+           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+        <dc:title>Guix System Distribution (Logo)</dc:title>
+        <dc:date>2015-02-07</dc:date>
+        <dc:creator>
+          <cc:Agent>
+            <dc:title>Luis Felipe López Acevedo</dc:title>
+          </cc:Agent>
+        </dc:creator>
+        <dc:rights>
+          <cc:Agent>
+            <dc:title>Luis Felipe López Acevedo</dc:title>
+          </cc:Agent>
+        </dc:rights>
+        <cc:license
+           rdf:resource="http://creativecommons.org/licenses/by-sa/4.0/" />
+        <dc:description />
+      </cc:Work>
+      <cc:License
+         rdf:about="http://creativecommons.org/licenses/by-sa/4.0/">
+        <cc:permits
+           rdf:resource="http://creativecommons.org/ns#Reproduction" />
+        <cc:permits
+           rdf:resource="http://creativecommons.org/ns#Distribution" />
+        <cc:requires
+           rdf:resource="http://creativecommons.org/ns#Notice" />
+        <cc:requires
+           rdf:resource="http://creativecommons.org/ns#Attribution" />
+        <cc:permits
+           rdf:resource="http://creativecommons.org/ns#DerivativeWorks" />
+        <cc:requires
+           rdf:resource="http://creativecommons.org/ns#ShareAlike" />
+      </cc:License>
+    </rdf:RDF>
+  </metadata>
+  <g
+     inkscape:groupmode="layer"
+     id="layer5"
+     inkscape:label="ramen"
+     sodipodi:insensitive="true">
+    <rect
+       style="fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:1.45544064;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+       id="rect942"
+       width="400"
+       height="300"
+       x="-3.7303494e-14"
+       y="1.7330311e-15" />
+  </g>
+  <g
+     inkscape:groupmode="layer"
+     id="layer4"
+     inkscape:label="bg"
+     style="display:inline"
+     transform="translate(0,-47.278107)"
+     sodipodi:insensitive="true">
+    <rect
+       style="display:inline;opacity:1;vector-effect:none;fill:#421111;fill-opacity:1;stroke:none;stroke-width:1.47144902;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.97635139"
+       id="rect12062"
+       width="380"
+       height="279.99997"
+       x="10"
+       y="57.278107" />
+  </g>
+  <g
+     inkscape:groupmode="layer"
+     id="layer1"
+     inkscape:label="head"
+     style="display:none;opacity:1"
+     transform="translate(0,-47.278107)"
+     sodipodi:insensitive="true">
+    <g
+       transform="matrix(0.40699717,0,0,0.40699717,31.535627,27.300788)"
+       id="layer1-6"
+       inkscape:label="Layer 1"
+       style="fill:#ff0000">
+      <g
+         transform="translate(126.95974,19.57999)"
+         id="Layer_1"
+         style="fill:#ff0000">
+        <g
+           id="g2490"
+           style="fill:#ff0000">
+          <path
+             style="fill:#ff0000;fill-rule:evenodd"
+             d="m 112.993,304.372 c -3.634,0.247 -8.365,1.875 -11.539,7.564 -2.591,4.646 -8.661,5.387 -11.495,4.451 -4.721,-1.56 -10.755,-2.642 -16.6,1.523 -5.845,4.164 -12.157,1.015 -11.05,-6.576 1.107,-7.59 3.849,-14.351 11.127,-18.538 15.895,-9.144 4.848,-15.508 13.572,-24.685 8.741,-9.195 6.81,-12.009 6.52,-24.497 C 63.985,239.176 47.241,230.661 28.544,207.301 9.847,183.94 2.599,164.711 0.661,135.423 -1.277,106.135 0.403,87.154 13.057,62.843 25.711,38.532 39.034,26.829 62.122,14.69 85.21,2.553 107.832,-0.354 128.742,0 c 20.91,0.353 34.843,1.885 46.658,8.626 11.814,6.741 22.622,15.224 29.512,15.285 6.891,0.061 11.582,-1.744 14.931,-4.31 0.894,22.703 -19.539,24.675 -37.819,25.155 -18.281,0.479 -29.514,-7.083 -46.351,-4.27 -16.837,2.813 -44.404,10.475 -57.833,33.85 -13.429,23.375 -13.887,31.638 -12.771,51.24 1.116,19.603 17.988,34.228 27.512,34.387 9.523,0.159 11.649,-2.599 19.985,-8.036 8.337,-5.438 50.896,-58.122 65.418,-69.956 14.523,-11.834 28.854,-15.488 44.328,-15.678 15.474,-0.19 19.428,0.335 31.908,5.45 12.48,5.114 20.149,14.533 30.211,20.291 5.143,-3.027 8.338,-7.547 13.057,-10.996 16.877,-12.335 25.646,-15.659 45.705,-13.707 11.529,1.122 26.066,7.708 34.74,15.25 15.445,13.429 28.205,32.125 38.516,46.328 8.029,11.061 17.477,24.295 30.965,28.432 14.727,4.515 25.809,-14.559 27.436,-25.139 0.922,-5.995 2.125,-11.249 2.135,-17.847 0.01,-6.599 -0.664,-14.607 -2.566,-21.484 -1.902,-6.877 -5.16,-13.72 -8.688,-19.394 -5.742,-9.235 -15.137,-18.899 -24.912,-23.871 -5.486,-2.79 -18.393,-7.863 -26.529,-8.041 -9.969,-0.216 -17.564,3.133 -26.781,3.761 -11.156,0.761 -31.084,3.269 -39.83,-5.35 -5.566,-5.485 -6.266,-9.144 -7.217,-16.296 2.459,2.026 5.898,3.358 8.959,3.617 6.986,0.59 13.527,-5.114 19.166,-8.419 4.645,-2.723 11.223,-7.589 17.324,-10.048 15.676,-6.32 34.932,-6.138 51.48,-4.445 13.264,1.356 30.461,7.257 42.094,13.84 11.688,6.612 22.951,17.761 31.201,28.271 10.379,13.224 16.053,24.57 19.812,41.063 4.805,21.062 6.137,52.702 0.328,73.469 -4.578,16.365 -19.779,41.504 -32.719,53.827 -12.762,12.155 -27.498,18.022 -44.256,21.231 0.656,3.382 0.764,6.536 1.631,9.309 1.232,3.936 3.588,8.324 8.428,6.936 1.93,-0.553 2.963,-1.032 5.508,1.194 2.543,2.226 1.219,10.825 -5.938,14.684 -3.629,1.957 -7.459,2.382 -13.271,2.498 -5.812,0.116 -14.883,0.141 -21.193,-0.964 -6.309,-1.104 -10.078,-6.111 -17.066,-6.895 -10.799,-1.208 -19.068,-9.01 -27.727,-14.59 -3.613,-2.329 -4.832,-2.353 -6.914,-3.53 1.125,3.444 2.625,7.021 3.373,10.332 0.75,3.311 0.43,6.378 0.828,9.028 0.396,2.648 1.131,4.707 1.559,6.855 1.73,1.547 2.283,3.9 5.189,4.64 2.908,0.739 7.461,-0.412 10.436,-0.812 2.975,-0.4 4.969,-2.021 7.303,-1.577 2.336,0.443 4.549,2.115 6.506,3.682 1.957,1.567 3.639,1.796 5.223,5.706 1.584,3.91 3.037,11.917 3.254,17.269 0.217,5.352 -0.383,10.183 -1.969,14.43 -1.586,4.247 -2.98,6.13 -7.275,10.336 -4.295,4.207 -11.289,10.38 -18.268,14.68 1.285,1.903 1.855,3.645 3.859,5.71 2.004,2.066 6.182,4.381 8.041,6.56 1.857,2.179 2.799,3.742 2.826,6.186 0.029,2.443 -0.09,5.619 -2.074,8.283 -4.941,6.633 -10.785,7.821 -17.891,10.941 1.195,7.462 2.17,12.793 0.443,20.244 -0.705,3.036 -2.271,9.92 -6.016,11.686 -3.746,1.766 -10.969,0.911 -15.541,1.637 -4.572,0.727 -7.131,1.417 -10.695,2.125 -2.166,3.131 -5.391,6.586 -6.496,9.392 -1.107,2.807 -0.773,3.813 0.156,6.679 0.929,2.866 4.092,7.039 4.988,10.395 0.896,3.356 1.07,6.969 0.234,10.334 -0.838,3.365 -2.271,5.807 -5.139,8.795 -2.867,2.989 -8.508,5.336 -11.318,7.758 -2.812,2.423 -5.611,2.714 -4.844,6.723 1.055,5.506 9.1,14.436 14.92,16.562 3.488,1.275 8.17,0.873 12.406,-0.915 -0.287,4.703 -4.357,7.873 -7.016,10.996 7.201,-2.059 14.184,-6.001 19.014,-11.226 -1.498,4.538 -6.652,11.823 -14.361,18.22 -7.709,6.397 -7.662,5.088 -11.494,7.633 6.992,1.405 13.494,1.025 18.91,0.052 -2.969,1.637 -7.836,3.939 -14.283,4.616 -6.447,0.676 -10.422,0.198 -16.232,-1.213 -5.811,-1.412 -11.115,-6.694 -18.156,-10.335 0.686,2.612 1.174,5.753 4.135,8.439 2.961,2.686 7.441,4.052 12.203,6.375 -6.062,-0.688 -12.432,-0.896 -18.389,-2.209 -4.41,-0.973 -7.373,-2.005 -10.6,-3.603 -3.225,-1.598 -5.715,-3.929 -8.572,-5.893 1.369,2.615 1.775,5.691 4.105,7.847 2.33,2.156 6.117,2.959 9.18,4.44 -3.195,-0.07 -6.268,0.623 -9.58,-0.21 -3.314,-0.833 -6.422,-2.142 -9.867,-4.68 -3.445,-2.538 -6.998,-5.663 -9.938,-8.858 -2.938,-3.195 -6.566,-7.337 -7.664,-10.283 -1.1,-2.947 0.66,-5.008 0.99,-7.509 -2.029,1.333 -4.525,2.067 -6.084,4.002 -1.559,1.935 -2.941,3.702 -2.251,7.075 0.691,3.373 3.804,7.496 6.005,11.248 -6.568,-5.371 -10.236,-7.439 -11.799,-13.918 -1.463,-6.066 2.322,-11.572 5.199,-16.159 1.429,-2.278 3.567,-4.398 4.903,-6.597 -2.967,-2.903 -6.358,-5.398 -8.901,-8.709 -2.542,-3.31 -3.61,-7.79 -6.205,-10.957 -2.596,-3.168 -6.088,-5.173 -9.129,-7.756 2.673,5.742 7.066,12.785 8.02,17.229 0.953,4.444 -1.069,7.164 -2.646,9.563 -1.578,2.399 -4.124,2.934 -6.539,4.408 -2.415,1.475 -6.171,0.312 -7.61,2.501 -1.438,2.188 -1.824,5.48 -0.449,7.648 l 5.64,8.902 c -2.078,-1.049 -5.658,-4.1 -7.272,-6.264 -1.614,-2.164 -4.09,-4.163 -4.429,-7.089 -0.339,-2.925 -0.504,-5.464 1.391,-8.07 1.896,-2.605 7.086,-3.477 9.409,-5.48 2.323,-2.003 3.626,-3.307 3.493,-5.896 -0.132,-2.589 -2.661,-4.441 -4.835,-6.073 -6.637,-4.978 -15.151,-9.565 -20.787,-15.565 -3.184,-3.39 -4.712,-6.127 -5.352,-8.466 -0.639,-2.338 0.037,-4.162 1.619,-7.038 1.582,-2.877 7.007,-6.718 7.667,-9.843 0.659,-3.124 -2.081,-3.795 -4.554,-4.897 -2.473,-1.102 -7.17,0.565 -9.464,-1.352 -2.293,-1.917 0.674,-5.945 -1.911,-8.154 -2.584,-2.209 -8.499,-0.976 -11.552,-3.352 -3.053,-2.377 -4.315,-5.327 -5.367,-8.775 -1.052,-3.448 -1.171,-7.225 -0.458,-9.722 0.713,-2.497 2.855,-2.934 4.147,-4.228 1.292,-1.294 2.413,-2.367 0.691,-4.297 -1.722,-1.929 -7.365,0.108 -10.609,-2.369 -3.244,-2.477 -1.258,-8.41 -3.552,-10.911 -2.293,-2.501 -6.409,-1.522 -8.581,-2.321 -2.171,-0.799 -3.023,2.02 -4.355,-2.438 -1.332,-4.459 -1.368,-17.75 -3.16,-22.71 -1.792,-4.96 -5.311,-0.335 -6.945,-5.265 -1.634,-4.929 -0.085,-12.812 -0.821,-20.257 l -3.335,-20.257 c -11.634,7.815 -19.314,10.269 -31.813,12.477 -1.043,30.582 -3.916,48.591 6.464,82.52 10.38,33.928 31.387,53.924 59.726,82.649 -37.395,-28.016 -55.248,-50.792 -66.422,-79.97 -11.176,-29.182 -9.03,-53.586 -7.906,-81.686 z M 311.701,292.08 c 2.877,0.129 6.373,0.859 8.393,2.171 2.021,1.312 4.166,2.384 6,4.251 4.576,4.66 8.008,10.28 9.525,16.738 0.967,4.117 1.111,9.397 1.463,14.231 -1.385,-4.468 -2.316,-9.127 -4.289,-13.13 -3.111,-6.312 -8.396,-12.473 -14.959,-15.31 -2.166,-0.938 -3.611,-0.764 -4.803,-0.598 0.533,0.895 1.426,1.645 1.465,2.956 0.039,1.311 -0.254,3.876 -2.477,4.954 -3.584,1.739 -7.568,0.516 -10.336,-1.931 -2.791,-2.466 -3.742,-6.638 -2.281,-10.223 1.741,-4.272 8.375,-4.283 12.299,-4.109 z M 275.629,286 c 0.361,-7.345 3.012,-13.539 9.594,-17.141 3.404,-1.862 8.648,-4.27 13.467,-4.836 4.629,-0.543 15.889,-0.146 22.662,2.945 5.201,2.374 8.744,6.07 13.311,8.771 4.566,2.702 7.814,4.513 12.162,7.543 6.674,4.651 10.586,9.772 15.213,12.842 2.225,1.475 5.355,1.256 8.309,2.158 -2.297,0.682 -5.299,1.434 -7.777,0.642 -3.09,-0.988 -7.41,-3.813 -9.807,-5.838 -4.236,-3.578 -6.432,-5.324 -11.055,-8.023 -2.76,-1.608 -7.305,-3.503 -10.338,-5.481 -3.035,-1.978 -8.303,-6.318 -11.219,-7.787 -3.707,-1.866 -10.381,-2.904 -14.508,-2.783 -5.686,0.166 -13.916,1.104 -18.316,5.096 -4.371,3.968 -6.031,7.459 -5.045,12.612 1.646,-1.896 2.742,-4.278 4.391,-5.688 3.416,-2.918 7.336,-3.059 11.588,-2.506 4.777,0.622 7.182,3.381 8.76,7.916 -1.062,-0.78 -3.014,-2.493 -4.555,-3.024 -3.617,-1.248 -6.352,-0.864 -9.74,0.953 -4,2.146 -2.912,5.322 -3.488,8.854 -0.264,1.629 -0.879,2.941 -1.318,4.412 -1.504,-0.398 -2.895,-1.024 -4.033,-2.152 0.047,1.65 -0.193,3.093 0.145,4.949 0.336,1.855 1.24,4.059 1.859,6.088 -2.785,-2.786 -5.635,-5.38 -7.434,-8.977 -1.801,-3.599 -3.021,-7.593 -2.828,-11.545 z m 4.82,-53.46 c 2.053,-3.047 2.654,-7.721 3.92,-11.521 -0.506,4.813 0.467,10.106 -1.883,13.592 -2.35,3.486 -6.477,2.875 -9.896,3.889 2.66,-2.028 5.805,-2.913 7.859,-5.96 z m -49.151,71.368 c 2.636,-2.134 9.75,-0.428 15.071,-0.047 -3.824,0.979 -7.648,1.959 -11.472,2.938 -0.356,1.301 -0.195,2.792 -1.068,3.901 -0.874,1.11 -2.534,1.521 -3.8,2.28 0.125,-3.418 -1.367,-6.939 1.269,-9.072 z m 37.491,-148.22 c 3.176,1.71 7.207,3.971 10.012,4.041 2.805,0.07 3.539,-1.834 5.189,-2.933 2.596,8.465 5.576,17.766 9.996,25.447 1.852,3.218 3.033,1.722 4.441,4.956 1.406,3.233 2.031,9.812 3.365,13.943 1.336,4.131 3.078,7.171 4.617,10.756 -3.908,-5.537 -8.957,-12.597 -11.135,-17.205 -2.176,-4.607 -0.783,-5.008 -2.545,-9.396 -1.762,-4.388 -5.324,-11.228 -7.986,-16.842 -1.906,0.253 -4.266,0.6 -5.715,0.153 -1.449,-0.447 -1.16,-1.988 -2.469,-2.984 -1.311,-0.996 -3.514,-0.61 -5.35,-2.2 -1.836,-1.589 -2.254,-4.85 -2.42,-7.736 z m -17.101,41.769 c 2.989,-0.262 6.701,0.539 9.5,0.38 2.799,-0.159 4.797,-0.885 7.196,-1.328 -0.445,-4.216 -0.023,-11.962 -3.915,-14.777 -2.514,-1.818 -12.839,-0.449 -15.597,0.146 -6.206,1.338 -13.433,5.042 -19.435,7.358 5.752,-4.018 10.721,-7.742 17.62,-9.816 4.147,-1.247 13.825,-2.868 18.105,-1.712 1.954,0.527 2.349,1.336 3.534,2.992 4.074,5.688 4.062,10.604 5.119,17.23 1.039,1.619 2.146,2.699 2.988,4.369 0.84,1.67 1.316,4.298 1.551,6.446 -1.066,-1.546 -0.414,-3.485 -3.367,-4.636 -2.955,-1.151 -7.479,-0.076 -11.46,0.34 2.902,2.094 4.344,4.111 4.455,8.538 0.13,5.198 -4.271,8.939 -8.866,9.295 -6.379,0.495 -9.668,-0.906 -12.248,-6.358 -1.13,-2.388 -0.311,-5.261 -0.405,-7.589 -7.665,0.533 -7.54,0.283 -13.142,4.954 3.045,4.461 4.963,7.026 9.995,9.695 2.822,1.498 6.017,2.954 9.514,3.549 3.498,0.595 9.235,1.17 12.909,0.606 3.675,-0.564 5.757,-1.613 8.481,-4.132 2.725,-2.52 2.975,-6.128 4.039,-8.98 -0.242,2.745 -0.557,6.241 -1.576,8.232 -3.1,6.053 -8.461,7.847 -14.862,7.867 -6.144,0.02 -13.744,-1.397 -19.46,-3.767 -4.57,-1.894 -12.146,-7.258 -13.944,-11.918 -1.229,-3.184 -0.256,-7.091 -0.385,-10.637 6.328,-4.208 7.894,-3.173 15.381,-4.405 3.132,-0.516 5.286,-1.679 8.275,-1.942 z m -36.861,-28.501 c 0.178,-2.521 0.457,-2.467 0.686,-3.701 -5.765,-1.542 -8.077,2.198 -11.457,9.144 -1.265,2.599 -0.013,4.146 -1.37,5.857 -1.355,1.711 -3.539,1.471 -5.74,3.114 -2.201,1.642 -4.382,4.787 -6.44,6.488 -4.223,3.491 -9.931,5.622 -14.829,7.971 3.345,-2.468 9.836,-6.211 11.936,-9.797 1.114,-1.901 0.949,-5.486 2.683,-7.195 1.733,-1.71 2.34,-2.893 4.578,-3.329 2.238,-0.436 1.338,-3.03 2.06,-5.092 0.722,-2.062 2.16,-3.526 3.69,-5.586 1.53,-2.06 3.46,-5.153 6.481,-6.276 3.021,-1.124 7.732,0.091 10.019,-0.556 2.286,-0.647 0.973,-2.309 2.634,-3.307 1.663,-0.998 4.896,-0.558 7.117,-1.625 3.937,-1.893 5.82,-5.053 8.188,-8.436 0.344,7.282 0.26,12.525 -2.357,19.376 -2.947,7.711 -5.934,12.253 -14.298,16.995 -2.882,1.633 -5.75,2.2 -8.139,3.057 1.393,-1.9 3.387,-2.725 4.18,-5.7 0.791,-2.977 0.2,-8.88 0.378,-11.402 z m 135.038,35.507 c -3.977,0.259 -4.92,-0.264 -8.102,1.98 1.725,2.684 3.449,5.368 5.172,8.052 -0.152,-5.298 0.364,-6.36 2.93,-10.032 z m -10.42,-3.85 c 5.508,-2.346 10.307,-4.244 16.299,-4.619 2.402,-0.151 6.131,0.221 8.557,0.331 2.066,-3.042 4.699,-5.441 5.664,-8.913 0.639,-2.303 0.324,-12.992 -0.807,-15.767 -3.295,-8.076 -6.498,-8.417 -11.033,-13.043 -3.291,-3.355 -3.422,-8.464 -4.406,-14.189 -0.361,-2.103 -1.393,-4.764 -1.877,-6.934 -5.928,-0.999 -12.303,-1.328 -19.123,-0.987 3.307,-3.172 6.504,-6.07 7.453,-10.832 0.947,-4.762 0.176,-10.617 -2.531,-14.887 -2.707,-4.27 -7.031,-7.99 -11,-11.469 -3.971,-3.479 -9.662,-6.351 -13.424,-9.197 4.893,-1.752 9.889,-4.326 14.682,-5.255 12.486,-2.422 23.244,1.282 35.287,8.563 7.002,4.235 12.793,8.258 20.113,15.921 7.318,7.662 16.395,21.717 23.48,30.052 7.085,8.335 12.805,14.927 18.986,19.898 6.182,4.972 11.777,6.388 17.664,9.581 l 9.176,9.744 7.426,-9.189 11.949,1.351 2.469,-13.412 10.967,-3.005 -1.789,-18.08 7.885,-5.596 -5.926,-11.249 6.021,-12.292 -7.85,-14.051 3.027,-13.529 -9.088,-7.745 -1.186,-14.377 -12.678,-4.836 -5.086,-12.508 -14.254,-0.16 -6.992,-9.285 -9.596,0.672 -10.697,-1.165 -6.049,-4.466 -8.779,5.828 -10.623,-5.539 -21.117,8.017 13.766,-11.972 14.262,-2.278 10.926,-2.785 14.756,4.846 12.988,-3.29 12.523,7.403 13.252,-0.733 6.51,11.681 13.195,1.523 7.139,12.987 8.299,4.531 2.203,16.637 7.391,7.01 -3.25,14.557 8.707,11.024 -8.164,11.812 8.73,7.383 -11.16,9.891 11.303,11.771 -13.65,4.402 8.891,12.625 -11.15,1.924 7.312,13.882 -12.566,-0.167 6.33,10.398 -13.783,-1.659 3.297,14.959 -10.416,-9.163 -3.568,18.13 -7.188,-13.018 -3.893,16.237 -8.873,-11.973 0.242,17.026 -9.807,-15.309 c 2.068,8.686 1.654,18.197 7.359,26.386 17.676,-2.392 29.229,-6.846 42.771,-19.877 12.334,-11.868 27.076,-36.613 31.068,-52.308 4.555,-17.91 4.695,-50.85 0.209,-69.084 C 522.282,71.848 516.67,63.462 506.643,49.136 497.059,38.957 487.633,28.204 475.469,20.945 457.613,10.29 434.717,7.417 414.367,7.694 c -11.268,0.154 -18.816,2.318 -25.553,4.768 -11.781,4.284 -21.203,13.629 -33.18,18.247 -3.906,1.505 -7.037,1.552 -10.113,-0.091 3.012,6.026 6.289,8.729 13.801,10.922 5.434,1.586 18.4,0.583 27.326,-0.241 9.582,-0.885 14.58,-3.734 27.621,-3.555 12.736,0.175 22.828,5.013 28.346,8.168 11.385,6.51 19.549,13.732 26.643,25.172 3.896,6.282 6.625,13.37 8.547,20.603 1.922,7.233 2.764,15.334 2.887,22.415 0.123,7.081 -0.418,13.402 -2.15,19.774 -4.051,14.918 -12.988,30.098 -31.346,27.753 -11.234,-1.436 -28.17,-22.522 -33.842,-30.258 C 401.909,115.758 390.133,98.481 375.752,85.479 366.984,77.554 354.979,72.1 343.19,71.021 c -22.117,-2.024 -28.676,2.177 -45.324,15.899 3.387,1.08 6.693,1.676 10.164,3.24 7.703,3.471 14.748,7.957 20.893,13.711 6.439,6.031 9.328,9.848 9.557,18.484 0.152,5.735 -4.566,10.333 -8.891,14.469 -2.646,2.533 -6.148,4.852 -8.291,6.818 -2.84,2.609 -6.357,5.463 -2.789,9.619 1.342,1.562 3.672,2.74 5.637,4.199 3.119,2.315 1.691,10.919 -2.418,13.201 -5.258,2.917 -11.541,2.591 -15.877,-1.314 5.473,-0.819 8.949,-1.545 8.807,-6.022 -0.082,-2.595 -3.381,-4.751 -6.619,-6.227 -7.809,-3.56 -13.707,-3.035 -21.479,-8.627 -7.85,-5.651 -8.023,-8.745 -10.145,-17.617 -3.785,0.396 -7.27,0.483 -12.331,2.159 -5.061,1.675 -10.654,5.663 -15.249,6.65 -11.572,2.49 -13.878,1.752 -20.211,0.113 -11.15,-2.886 -25.668,2.055 -40.09,6.668 -2.398,0.767 -12.097,0.026 -18.626,2.317 -10.084,3.538 -24.233,12.106 -32.405,18.988 -12.382,10.429 -28.654,41.64 -37.848,77.464 -0.966,10.89 2.131,18.227 -4.729,23.546 -6.86,5.319 -6.67,18.946 -8.996,22.768 -2.326,3.821 -5.019,2.132 -10.026,7.499 -5.007,5.367 -7.556,4.47 -7.43,14.618 4.315,-2.837 10.606,-6.135 16.13,-6.334 4.892,-0.177 4.944,6.264 17.5,-6.149 6.715,-6.641 19.616,-6.844 28.567,-9.773 8.952,-2.929 25.083,-8.965 41.239,-27.027 16.156,-18.062 23.887,-37.077 27.02,-64.567 0.499,4.874 1.365,10.371 -0.722,23.816 -2.087,13.445 -6.585,28.546 2.891,46.634 l 5.904,11.269 c -3.515,-4.797 -10.381,-12.622 -12.448,-18.198 l -4.768,-12.863 c -10.667,16.748 -13.119,19.744 -27.937,31.743 -0.59,7.444 -0.735,15.208 1.698,22.331 2.433,7.122 -1.445,15.332 0.406,20.023 1.851,4.691 6.132,2.021 7.53,6.77 1.398,4.749 -0.73,14.138 1.438,18.767 2.168,4.629 7.487,1.82 10.065,3.315 2.578,1.496 3.421,3.546 4.8,5.513 1.378,1.966 -0.539,6.614 2.265,8.123 2.803,1.51 7.176,0.231 10.093,1.68 2.917,1.449 3.36,4.932 2.661,8.053 -0.7,3.121 -3.817,4.553 -5.186,7.726 -1.368,3.174 -1.215,5.383 0.429,8.297 1.644,2.915 5.284,4.52 8.912,5.991 3.628,1.471 8.726,0.645 12.47,2.679 3.744,2.034 7.109,6.087 9.086,9.033 1.977,2.945 2.526,5.023 2.425,8.12 -0.102,3.096 -1.358,6.663 -3.011,9.654 -1.653,2.991 -5.3,6.631 0.394,12.343 5.694,5.711 5.484,3.249 8.746,6.954 -0.355,-6.409 -3.003,-11.63 -1.067,-16.455 1.937,-4.825 7.752,-5.664 10.817,-7.834 3.065,-2.171 4.83,-5.153 7.246,-7.729 -0.035,3.315 0.32,6.879 -0.057,9.375 -0.768,5.075 -2.266,9.58 5.297,10.394 3.407,0.366 6.642,-1.843 10.227,-3.169 -1.878,3.363 -5.144,6.067 -5.635,10.092 -0.491,4.023 0.099,8.443 2.885,12.436 2.787,3.991 7.599,6.955 11.125,9.301 3.525,2.347 5.414,2.535 8.123,3.804 0.133,3.956 -0.646,8.143 -0.195,11.869 0.451,3.726 1.625,7.024 3.779,10.104 2.156,3.081 5.613,4.848 8.869,7.126 -1.785,-4.157 -5.406,-8.101 -5.357,-12.471 0.049,-4.369 1.359,-7.466 5.621,-11.343 4.262,-3.878 14.24,-7.241 18.945,-11.011 4.705,-3.771 6.223,-6.081 7.912,-9.742 1.689,-3.661 1.219,-9.559 1.531,-12.85 1.549,4.61 1.77,6.043 2.273,10.866 0.506,4.824 -2.811,11.59 -4.215,15.161 5.82,-2.811 9.514,-7.304 11.379,-11.695 1.248,0.74 0.619,2.769 1.078,6.679 2.074,-2.064 4.432,-3.652 6.52,-5.6 2.09,-1.946 4.379,-3.658 5.416,-6.375 1.035,-2.717 0.611,-5.606 -0.16,-8.763 -0.771,-3.157 -4.299,-6.818 -6.199,-10.271 -1.898,-3.452 0.336,-6.841 0.207,-11.001 -3.801,-0.653 -7.029,-2.589 -11.398,-1.96 -4.371,0.628 -9.377,5.533 -13.844,5.59 -4.467,0.057 -6.975,-4.128 -10.637,-5.278 -3.662,-1.15 -7.367,-1.024 -11.049,-1.536 4.664,-4.468 22.766,-6.596 35.148,-8.615 10.895,-1.777 21.707,-2.804 32.746,-2.959 4.93,-0.07 11.266,1.558 14.689,0.574 3.426,-0.982 2.695,-3.315 3.711,-5.858 2.842,-7.108 1.441,-13.438 -0.105,-20.596 -9.91,-1.162 -20.236,-2.584 -30.221,-1.817 -9.762,0.75 -21.322,5.391 -31.391,5.705 -8.754,0.272 -21.717,-1.677 -29.234,-6.259 -9.186,-5.599 -16.293,-17.624 -18.816,-21.485 -4.109,-6.289 -9.292,-18.627 -12.446,-24.268 -3.152,-5.641 -3.847,-7.219 -6.47,-9.574 -2.623,-2.354 -6.216,-2.536 -9.323,-3.805 3.582,0.366 7.493,-0.768 10.747,1.098 4.889,2.805 10.361,14.431 13.403,19.49 3.223,-10.804 2.471,-15.052 11.797,-21.144 -7.516,8.424 -7.703,14.805 -9.535,24.723 6.25,10.258 14.939,26.598 26.309,31.132 4.107,1.639 11.16,2.667 15.6,3.216 13.818,1.711 27.146,-2.668 40.717,-6.019 9.92,-2.45 19.986,-1.463 32.051,-0.754 4.096,0.24 13.754,-2.224 15.754,-6.367 1.08,-2.235 1,-4.921 -0.551,-7.303 -1.553,-2.382 -5.689,-3.534 -7.906,-5.678 -2.217,-2.144 -3.492,-4.689 -5.238,-7.034 -9.215,1.768 -16.795,2.447 -23.635,2.633 4.906,-2.021 9.613,-3.174 14.719,-5.171 5.106,-1.997 10.904,-5.275 15.025,-7.995 4.121,-2.721 6.752,-4.299 9.734,-7.465 2.98,-3.168 6.803,-6.431 9,-10.303 2.199,-3.872 2.539,-8.203 2.662,-12.995 0.123,-4.791 -0.084,-11.514 -1.932,-15.374 -1.846,-3.859 -5.406,-5.03 -8.266,-5.943 -2.861,-0.913 -4.82,1.396 -7.795,1.708 -2.977,0.312 -5.758,2.188 -10.062,0.164 -4.304,-2.024 -9.406,-6.144 -13.758,-12.259 -4.35,-6.116 -7.461,-16.112 -11.896,-23.802 -7.645,-13.256 -17.172,-25.639 -26.283,-37.922 -0.75,-3.029 -1.877,-7.215 -2.252,-11.324 -0.654,-7.16 -0.777,-14.598 1.445,-21.578 1.703,-5.347 4.18,-10.995 9.779,-13.188 2.24,-0.878 5.074,-1.226 7.076,-0.484 2.004,0.741 3.969,3.002 3.182,5.614 -0.865,2.872 -2.855,2.95 -4.207,4.4 -2.295,2.46 -3.213,4.265 -4.08,7.332 2.48,-0.04 5.832,-0.229 7.869,0.307 2.658,0.7 5.133,2.462 6.482,6.228 -3.172,-2.813 -4.748,-4.104 -8.707,-4.204 -1.814,-0.045 -4.018,0.604 -6.025,0.906 -0.75,2.44 -1.191,5.432 -2.25,7.32 -1.059,1.888 -3.121,1.435 -3.895,3.641 -0.774,2.202 -0.819,5.788 -0.429,8.683 z m 27.715,-3.307 c 1.215,0.479 1.678,0.584 3.217,1.755 1.539,1.171 3.662,2.34 4.881,5.138 1.221,2.799 1.164,7.127 0.904,8.89 -1.07,-0.314 -2.529,-0.102 -3.639,-1.051 -1.107,-0.949 -1.768,-3.098 -3.188,-4.018 -1.422,-0.919 -2.607,-0.718 -4.178,-0.917 0.807,2.296 1.199,4.593 0.824,6.675 -0.814,4.545 -3.486,6.847 -7.812,7.391 -1.889,0.237 -4.889,-0.385 -6.533,-0.684 0.762,1.702 2.053,3.193 2.816,4.895 3.658,-0.529 6.369,-0.454 8.336,-1.374 1.967,-0.92 4.076,-2.981 6.6,-3.854 2.525,-0.873 4.777,-0.859 7.539,-1.29 -2.176,1.875 -3.604,3.751 -5.777,5.626 1.594,4.633 3.188,9.265 4.781,13.897 3.379,2.114 6.549,3.228 10.807,5.838 4.26,2.611 9.367,7.281 14.914,9.828 5.547,2.547 8.85,3.933 14.646,5.026 5.795,1.093 10.406,5.787 16.109,6.55 5.703,0.763 16.355,0.917 20.75,0.488 4.99,-0.487 11.473,-3.062 12.055,-8.533 -4.184,1.032 -10.574,0.106 -13.801,-7.767 -1.432,-3.496 -0.73,-9.925 -2.922,-14.059 -2.191,-4.135 -5.246,-5.462 -8.896,-10.556 -3.65,-5.094 -9.621,-13.129 -12.973,-19.954 -3.35,-6.824 -4.139,-14.554 -6.973,-20.669 -2.834,-6.114 -7.109,-11.053 -10.422,-15.766 -7.234,-10.3 -13.068,-17.339 -24.986,-22.535 -5.732,-2.499 -12.258,-3.165 -18.387,-4.748 -2.494,1.117 -5.914,2.351 -6.521,5.268 -0.607,2.917 0.559,7.225 2.676,9.415 3.543,3.661 8.793,7.618 10.857,13.437 1.326,3.734 1.711,16.252 0.562,19.649 -1.192,3.527 -3.963,5.66 -6.266,8.009 z m 1.154,29.629 c -1.107,0.955 -1.951,1.936 -3.732,2.729 -1.779,0.793 -4.209,0.998 -6.57,1.588 3.311,5.154 6.789,10.362 9.961,15.781 3.174,5.418 5.924,11.351 8.953,17.025 -0.143,-3.252 0.049,-6.719 -0.424,-9.758 -0.473,-3.038 -1.85,-5.697 -3.215,-10.258 -1.363,-4.561 -3.041,-10.766 -4.973,-17.107 z M 279.229,113.611 c -0.467,5.07 0.391,12.996 1.441,17.96 1.258,5.942 2.469,9.023 7.291,12.603 8.83,6.555 14.467,5.45 21.26,9.251 3.232,1.809 7.328,4.841 8.523,8.046 1.195,3.205 -0.789,6.685 -3.24,8.053 4.287,0.638 9.094,-4.195 7.088,-9.157 -0.988,-2.442 -5.691,-3.53 -7.133,-5.994 -1.439,-2.463 -1.436,-4.999 -0.758,-7.501 1.225,-4.51 10.148,-8.608 13.301,-12.173 4.852,-5.486 6.715,-10.075 3.967,-17.14 -3.859,-9.925 -18.768,-17.889 -27.691,-21.784 -4.086,-1.783 -6.377,-1.91 -9.564,-2.865 6.525,3.824 13.404,6.87 16.705,15.418 2.756,7.139 0.369,9.829 0.461,16.045 0.043,2.882 3.838,4.323 5.523,6.144 1.467,1.583 1.348,2.758 0.176,4.943 -0.129,-1.971 -0.971,-3.442 -2.484,-4.513 -2.498,-1.771 -5.189,-1.39 -6.52,-5.021 -2.02,-5.52 1.986,-10.748 -2.518,-16.946 -3.369,-4.637 -7.85,-9.827 -13.895,-9.963 -2.861,-0.065 -5.012,0.367 -8.068,1.271 l -4.074,-4.903 -0.094,-0.064 C 270.639,87.758 264.969,81.525 253.344,76.327 241.719,71.13 235.99,70.343 222.661,70.639 c -13.329,0.295 -26.557,1.41 -41.995,14.723 -15.437,13.313 -55.224,64.292 -64.873,70.744 -9.648,6.452 -11.785,8.638 -23.841,8.641 C 79.896,164.75 61.08,147.697 60.343,126.385 59.605,105.072 59.309,97.497 74.124,71.822 88.94,46.146 115.78,38.262 135.694,35.6 c 19.915,-2.662 31.882,4.352 46.613,4.385 14.73,0.034 29.288,-2.509 33.581,-14.224 -2.101,1.251 -4.916,2.661 -12.832,2.246 C 195.14,27.592 184.164,18.427 171.817,12.286 159.47,6.146 145.73,5.427 128.107,5.094 110.484,4.761 88.494,6.108 66.708,17.869 44.922,29.63 30.051,42.109 17.415,65.127 4.779,88.146 2.891,106.94 4.928,134.811 c 2.037,27.871 10.633,48.599 27.184,68.998 16.551,20.399 33.092,30.38 62.918,34.091 l 6.279,-27.696 -11.209,16.086 0.277,-17.891 -10.139,12.581 -4.447,-17.062 -8.214,13.679 -4.08,-19.05 -11.903,9.627 3.768,-15.719 -15.75,1.743 7.235,-10.926 -14.361,0.175 L 40.842,168.86 28.1,166.837 38.26,153.57 22.66,148.945 35.576,136.577 22.823,126.184 32.798,118.426 23.47,106.014 33.42,94.431 29.706,79.135 38.155,71.77 40.67,54.289 50.152,49.527 58.31,35.881 73.389,34.28 l 7.44,-12.274 15.145,0.771 14.312,-7.779 14.843,3.457 16.86,-5.092 12.487,2.926 16.296,2.395 15.733,12.58 -24.133,-8.424 -12.14,5.821 -10.035,-6.125 -6.909,4.693 -12.225,1.224 -10.963,-0.708 -7.992,9.756 -16.291,0.168 -5.811,13.143 -14.486,5.082 -1.355,15.107 -10.388,8.138 3.461,14.216 -8.971,14.765 6.882,12.915 -6.773,11.82 9.011,5.88 -2.044,18.998 12.532,3.158 2.823,14.093 13.656,-1.419 8.484,9.656 10.486,-10.239 c 19.116,-9.532 26.988,-14.864 41.886,-30.977 16.959,-18.343 26.679,-35.302 49.269,-47.861 16.202,-9.008 29.417,-12.25 47.617,-9.105 17.088,2.952 22.81,13.202 35.395,24 1.334,-2.415 1.605,-3.055 3.803,-4.833 -0.69,3.136 -1.786,6.389 -2.065,9.405 z"
+             id="path2492"
+             inkscape:connector-curvature="0" />
+        </g>
+      </g>
+    </g>
+  </g>
+  <g
+     inkscape:label="gnu:net grunge"
+     id="g12308"
+     inkscape:groupmode="layer"
+     style="display:none"
+     transform="translate(-387.41463,-589.81931)">
+    <text
+       xml:space="preserve"
+       style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:16.53852463px;line-height:125%;font-family:Ubuntu;-inkscape-font-specification:Ubuntu;letter-spacing:0px;word-spacing:0px;display:inline;opacity:1;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1.03365779px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+       x="478.95114"
+       y="859.00549"
+       id="text12220"><tspan
+         sodipodi:role="line"
+         id="tspan12218"
+         x="478.95114"
+         y="859.00549"
+         style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:36px;font-family:ReservoirGrunge;-inkscape-font-specification:ReservoirGrunge;fill:#ffffff;stroke-width:1.03365779px"
+         dx="0 2.5 2.5 0 -4 2.5 2.5">gnu net</tspan></text>
+  </g>
+  <g
+     transform="translate(-387.41463,-589.81931)"
+     style="display:none"
+     inkscape:groupmode="layer"
+     id="g5346"
+     inkscape:label="gnu:net ubuntu">
+    <text
+       id="text5344"
+       y="859.96057"
+       x="493.95291"
+       style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:16.53852463px;line-height:125%;font-family:Ubuntu;-inkscape-font-specification:Ubuntu;letter-spacing:0px;word-spacing:0px;display:inline;opacity:1;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1.03365779px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+       xml:space="preserve"><tspan
+         dx="0 0 0"
+         style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:49.33333206px;font-family:'Ubuntu Bold';-inkscape-font-specification:'Ubuntu Bold, ';fill:#ffffff;stroke-width:1.03365779px"
+         y="859.96057"
+         x="493.95291"
+         id="tspan5342"
+         sodipodi:role="line">gnu net</tspan></text>
+  </g>
+  <g
+     inkscape:label="gnu:net anonymous"
+     id="g950"
+     inkscape:groupmode="layer"
+     style="display:inline"
+     transform="translate(-387.41463,-589.81931)">
+    <text
+       xml:space="preserve"
+       style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:16.53852463px;line-height:125%;font-family:Ubuntu;-inkscape-font-specification:Ubuntu;letter-spacing:0px;word-spacing:0px;display:inline;opacity:1;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1.03365779px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+       x="507.95291"
+       y="858.71057"
+       id="text948"><tspan
+         sodipodi:role="line"
+         id="tspan946"
+         x="507.95291"
+         y="858.71057"
+         style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:50.66666794px;font-family:'Anonymous Pro';-inkscape-font-specification:'Anonymous Pro Bold';fill:#ffffff;stroke-width:1.03365779px"
+         dx="0 -2.5 -3 0 -19.25 -2.5 -3">gnu net</tspan></text>
+  </g>
+  <g
+     inkscape:groupmode="layer"
+     id="layer3"
+     inkscape:label="vertices 2"
+     style="display:inline"
+     transform="translate(0,-47.278107)"
+     sodipodi:insensitive="true">
+    <path
+       style="display:inline;fill:none;fill-rule:evenodd;stroke:#3498db;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+       d="m 51.98603,94.74526 63.6227,34.91188 23.31802,-11.09978 -35.03955,28.74946 11.86161,-17.77468 -53.18435,-5.79678 40.95076,23.69646 25.32406,0.49689 24.19305,3.02495 v 48.02104 l 21.04995,-32.14943 -20.559,-15.87161 32.52749,48.02104 -8.06937,31.38386 -24.94907,-31.76198 24.94907,77.51429 22.25436,-36.69889 21.97354,37.07701 -43.59987,-0.37188 41.32877,-28.87448 22.05899,-21.17152 -19.90986,50.171 -3.71591,-29.60613 -8.57843,-31.7682 -9.69437,24.71516 54.37611,-52.19866 -24.96716,8.94671 -18.39175,19.15282 18.27579,-55.07718 25.20812,27.362 20.66591,-41.35238 -46.00204,14.12783 22.94304,-37.07431 23.05297,23.0777 31.8814,-26.48075 40.07874,-25.58708 -15.26372,39.20869 -24.69305,-13.74039 -55.05634,4.03119 79.62738,9.58108 -56.57441,12.73416"
+       id="path9316"
+       inkscape:connector-curvature="0"
+       sodipodi:nodetypes="ccccccccccccccccccccccccccccccccccccccccc" />
+    <path
+       style="display:inline;fill:none;fill-rule:evenodd;stroke:#3498db;stroke-width:1.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+       d="m 139.04572,118.81358 37.0456,48.02106"
+       id="path9318"
+       inkscape:connector-curvature="0" />
+    <path
+       style="display:inline;fill:none;fill-rule:evenodd;stroke:#3498db;stroke-width:1.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+       d="m 128.46126,147.9287 10.96248,-29.11512 12.47454,32.51819"
+       id="path12058"
+       inkscape:connector-curvature="0" />
+    <path
+       style="display:inline;fill:none;fill-rule:evenodd;stroke:#3498db;stroke-width:3;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+       d="m 252.31652,123.28236 54.69043,-3.64603 -31.75647,27.04795"
+       id="path12250"
+       inkscape:connector-curvature="0"
+       sodipodi:nodetypes="ccc" />
+    <ellipse
+       ry="4.1593032"
+       rx="4.1581793"
+       cy="112.66669"
+       cx="83.343307"
+       id="ellipse12260"
+       style="display:inline;opacity:1;fill:#3498db;fill-opacity:1;stroke:#3498db;stroke-width:0.39663559;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.97635139" />
+    <ellipse
+       ry="4.1593032"
+       rx="4.1581793"
+       cy="123.35095"
+       cx="63.064556"
+       id="ellipse12264"
+       style="display:inline;opacity:1;fill:#3498db;fill-opacity:1;stroke:#3498db;stroke-width:0.39663559;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.97635139" />
+    <ellipse
+       ry="4.1593032"
+       rx="4.1581793"
+       style="display:inline;opacity:1;fill:#3498db;fill-opacity:1;stroke:#3498db;stroke-width:0.39663559;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.97635139"
+       id="ellipse12266"
+       cx="139.04277"
+       cy="118.93542" />
+    <ellipse
+       ry="4.1593032"
+       rx="4.1581793"
+       inkscape:transform-center-y="-10.724852"
+       inkscape:transform-center-x="9.5305947"
+       cy="123.78851"
+       cx="252.13518"
+       id="ellipse12292"
+       style="display:inline;opacity:1;fill:#3498db;fill-opacity:1;stroke:#3498db;stroke-width:0.39663559;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.97635139" />
+    <ellipse
+       ry="4.1593032"
+       rx="4.1581793"
+       inkscape:transform-center-y="-10.724835"
+       inkscape:transform-center-x="9.5305988"
+       cy="119.55022"
+       cx="307.26297"
+       id="ellipse12296"
+       style="display:inline;opacity:1;fill:#3498db;fill-opacity:1;stroke:#3498db;stroke-width:0.39663559;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.97635139" />
+    <path
+       style="fill:none;stroke:#3498db;stroke-width:2.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:0.97647059"
+       d="m 52.875,94.278107 10,29.000003 21,-10.5 v 0 0"
+       id="path5311"
+       inkscape:connector-curvature="0" />
+    <path
+       style="fill:none;stroke:#3498db;stroke-width:1.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:0.97647059"
+       d="m 102.875,75.278107 -39.5,48.000003 v 0 l -1,2"
+       id="path5313"
+       inkscape:connector-curvature="0" />
+    <path
+       style="fill:none;stroke:#3498db;stroke-width:1.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+       d="m 229.75,196.02811 -44,2.625 25.375,17.125 v 0"
+       id="path5331"
+       inkscape:connector-curvature="0" />
+  </g>
+  <g
+     inkscape:groupmode="layer"
+     id="layer2"
+     inkscape:label="vertices 0"
+     style="display:inline;opacity:1"
+     transform="translate(-387.41463,-589.81931)"
+     sodipodi:insensitive="true">
+    <path
+       style="display:inline;fill:none;fill-rule:evenodd;stroke:#3498db;stroke-width:3;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+       d="m 515.87589,689.71367 24.57107,51.42411"
+       id="path9320"
+       inkscape:connector-curvature="0" />
+    <path
+       style="display:inline;fill:none;fill-rule:evenodd;stroke:#3498db;stroke-width:1.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+       d="m 574.46842,741.13778 12.85257,40.08057"
+       id="path9322"
+       inkscape:connector-curvature="0" />
+    <path
+       style="display:inline;fill:none;fill-rule:evenodd;stroke:#3498db;stroke-width:1.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+       d="m 565.39603,772.52162 0.37803,45.75234"
+       id="path9324"
+       inkscape:connector-curvature="0" />
+    <path
+       style="display:inline;fill:none;fill-rule:evenodd;stroke:#3498db;stroke-width:1.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+       d="m 642.13335,732.06293 -12.09653,36.6775"
+       id="path9326"
+       inkscape:connector-curvature="0" />
+    <path
+       style="display:inline;fill:none;fill-rule:evenodd;stroke:#3498db;stroke-width:1.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+       d="m 515.87589,690.09178 46.98395,22.0278 10.85256,28.26194"
+       id="path12060"
+       inkscape:connector-curvature="0"
+       sodipodi:nodetypes="ccc" />
+    <path
+       style="display:inline;fill:none;fill-rule:evenodd;stroke:#3498db;stroke-width:1.58654225px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+       d="m 450.10106,666.64844 54.05634,6.0499"
+       id="path12214"
+       inkscape:connector-curvature="0" />
+    <path
+       style="display:inline;fill:#729fcf;fill-rule:evenodd;stroke:#3498db;stroke-width:1.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+       d="m 641.75532,730.92859 -2.26809,-64.28015"
+       id="path12206"
+       inkscape:connector-curvature="0" />
+    <path
+       style="display:inline;fill:none;fill-rule:evenodd;stroke:#3498db;stroke-width:1.58654225px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+       d="m 629.28078,768.36231 -12.85255,-66.17074 v 36.6775 z"
+       id="path12208"
+       inkscape:connector-curvature="0" />
+    <path
+       style="display:inline;fill:none;fill-rule:evenodd;stroke:#3498db;stroke-width:1.58654225px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+       d="m 597.52742,757.77501 31.75336,10.5873"
+       id="path12210"
+       inkscape:connector-curvature="0" />
+    <path
+       style="display:inline;fill:none;fill-rule:evenodd;stroke:#3498db;stroke-width:1.58654225px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+       d="m 540.44696,693.87298 v 48.77728 l 24.57105,30.2495 23.81505,9.45293"
+       id="path12212"
+       inkscape:connector-curvature="0" />
+    <path
+       style="display:inline;fill:none;fill-rule:evenodd;stroke:#3498db;stroke-width:3;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+       d="m 564.64001,819.03019 44.98392,-0.37812"
+       id="path12216"
+       inkscape:connector-curvature="0" />
+    <ellipse
+       ry="4.1593032"
+       rx="4.1581793"
+       style="display:inline;opacity:1;fill:#3498db;fill-opacity:1;stroke:#3498db;stroke-width:0.39663559;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.97635139"
+       id="ellipse12252"
+       cx="587.39447"
+       cy="781.79773" />
+    <ellipse
+       ry="4.1593032"
+       rx="4.1581793"
+       cy="818.74042"
+       cx="609.15759"
+       id="ellipse12254"
+       style="display:inline;opacity:1;fill:#3498db;fill-opacity:1;stroke:#3498db;stroke-width:0.39663559;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.97635139" />
+    <ellipse
+       ry="4.1593032"
+       rx="4.1581793"
+       style="display:inline;opacity:1;fill:#3498db;fill-opacity:1;stroke:#3498db;stroke-width:0.39663559;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.97635139"
+       id="ellipse12256"
+       cx="565.97528"
+       cy="818.74042" />
+    <ellipse
+       ry="4.1593032"
+       rx="4.1581793"
+       style="display:inline;opacity:1;fill:#3498db;fill-opacity:1;stroke:#3498db;stroke-width:0.39663559;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.97635139"
+       id="ellipse12262"
+       cx="490.92691"
+       cy="689.33545" />
+    <ellipse
+       ry="4.1593032"
+       rx="4.1581793"
+       cy="690.09174"
+       cx="516.25397"
+       id="ellipse12268"
+       style="display:inline;opacity:1;fill:#3498db;fill-opacity:1;stroke:#3498db;stroke-width:0.39663559;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.97635139" />
+    <ellipse
+       ry="4.1593032"
+       rx="4.1581793"
+       style="display:inline;opacity:1;fill:#3498db;fill-opacity:1;stroke:#3498db;stroke-width:0.39663559;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.97635139"
+       id="ellipse12270"
+       cx="561.66821"
+       cy="709.15314" />
+    <ellipse
+       ry="4.1593032"
+       rx="4.1581793"
+       cy="671.6922"
+       cx="502.64844"
+       id="ellipse12272"
+       style="display:inline;opacity:1;fill:#3498db;fill-opacity:1;stroke:#3498db;stroke-width:0.39663559;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.97635139" />
+    <ellipse
+       ry="4.1593032"
+       rx="4.1581793"
+       style="display:inline;opacity:1;fill:#3498db;fill-opacity:1;stroke:#3498db;stroke-width:0.39663559;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.97635139"
+       id="ellipse12274"
+       cx="540.81299"
+       cy="693.37305" />
+    <ellipse
+       ry="4.1593032"
+       rx="4.1581793"
+       cy="741.13794"
+       cx="540.82501"
+       id="ellipse12276"
+       style="display:inline;opacity:1;fill:#3498db;fill-opacity:1;stroke:#3498db;stroke-width:0.39663559;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.97635139" />
+    <ellipse
+       ry="4.1593032"
+       rx="4.1581793"
+       style="display:inline;opacity:1;fill:#3498db;fill-opacity:1;stroke:#3498db;stroke-width:0.39663559;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.97635139"
+       id="ellipse12278"
+       cx="573.51123"
+       cy="741.22632" />
+    <ellipse
+       ry="4.1593032"
+       rx="4.1581793"
+       cy="772.52173"
+       cx="565.39612"
+       id="ellipse12280"
+       style="display:inline;opacity:1;fill:#3498db;fill-opacity:1;stroke:#3498db;stroke-width:0.39663559;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.97635139" />
+    <ellipse
+       ry="4.1593032"
+       rx="4.1581793"
+       style="display:inline;opacity:1;fill:#3498db;fill-opacity:1;stroke:#3498db;stroke-width:0.39663559;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.97635139"
+       id="ellipse12282"
+       cx="606.38373"
+       cy="789.62549"
+       inkscape:transform-center-x="9.5306006"
+       inkscape:transform-center-y="-10.72485" />
+    <ellipse
+       ry="4.1593032"
+       rx="4.1581793"
+       inkscape:transform-center-y="-10.724822"
+       inkscape:transform-center-x="9.5305654"
+       cy="730.17249"
+       cx="641.75543"
+       id="ellipse12284"
+       style="display:inline;opacity:1;fill:#3498db;fill-opacity:1;stroke:#3498db;stroke-width:0.39663559;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.97635139" />
+    <ellipse
+       ry="4.1593032"
+       rx="4.1581793"
+       style="display:inline;opacity:1;fill:#3498db;fill-opacity:1;stroke:#3498db;stroke-width:0.39663559;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.97635139"
+       id="ellipse12286"
+       cx="616.8064"
+       cy="702.94794"
+       inkscape:transform-center-x="9.5305633"
+       inkscape:transform-center-y="-10.724851" />
+    <ellipse
+       ry="4.1593032"
+       rx="4.1581793"
+       inkscape:transform-center-y="-10.724843"
+       inkscape:transform-center-x="9.5305819"
+       cy="738.49109"
+       cx="617.18439"
+       id="ellipse12288"
+       style="display:inline;opacity:1;fill:#3498db;fill-opacity:1;stroke:#3498db;stroke-width:0.39663559;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.97635139" />
+    <ellipse
+       ry="4.1593032"
+       rx="4.1581793"
+       style="display:inline;opacity:1;fill:#3498db;fill-opacity:1;stroke:#3498db;stroke-width:0.39663559;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.97635139"
+       id="ellipse12290"
+       cx="629.03088"
+       cy="768.17493"
+       inkscape:transform-center-x="9.5305949"
+       inkscape:transform-center-y="-10.724827" />
+    <ellipse
+       ry="4.1593032"
+       rx="4.1581793"
+       style="display:inline;opacity:1;fill:#3498db;fill-opacity:1;stroke:#3498db;stroke-width:0.39663559;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.97635139"
+       id="ellipse12294"
+       cx="662.54626"
+       cy="688.95752"
+       inkscape:transform-center-x="9.5306048"
+       inkscape:transform-center-y="-10.724823" />
+    <ellipse
+       ry="4.1593032"
+       rx="4.1581793"
+       style="display:inline;opacity:1;fill:#3498db;fill-opacity:1;stroke:#3498db;stroke-width:0.39663559;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.97635139"
+       id="ellipse12298"
+       cx="719.24872"
+       cy="675.72339"
+       inkscape:transform-center-x="9.5305824"
+       inkscape:transform-center-y="-10.724798" />
+    <ellipse
+       ry="4.1593032"
+       rx="4.1581793"
+       style="display:inline;opacity:1;fill:#3498db;fill-opacity:1;stroke:#3498db;stroke-width:0.39663559;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.97635139"
+       id="ellipse12302"
+       cx="617.18439"
+       cy="738.49109"
+       inkscape:transform-center-x="9.5305819"
+       inkscape:transform-center-y="-10.724843" />
+    <ellipse
+       ry="4.1593032"
+       rx="4.1581793"
+       inkscape:transform-center-y="-10.724843"
+       inkscape:transform-center-x="9.5305819"
+       cy="738.49109"
+       cx="617.24689"
+       id="ellipse12304"
+       style="display:inline;opacity:1;fill:#3498db;fill-opacity:1;stroke:#3498db;stroke-width:0.39663559;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.97635139" />
+    <ellipse
+       ry="4.1593032"
+       rx="4.1581793"
+       style="display:inline;opacity:1;fill:#3498db;fill-opacity:1;stroke:#3498db;stroke-width:0.39663559;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.97635139"
+       id="ellipse12306"
+       cx="598.0033"
+       cy="758.21582"
+       inkscape:transform-center-x="9.5306167"
+       inkscape:transform-center-y="-10.724797" />
+    <ellipse
+       ry="4.1593032"
+       rx="4.1581793"
+       style="display:inline;opacity:1;fill:#3498db;fill-opacity:1;stroke:#3498db;stroke-width:0.39663559;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.97635139"
+       id="ellipse12258"
+       cx="440.27264"
+       cy="636.84271" />
+    <ellipse
+       ry="4.1593032"
+       rx="4.1581793"
+       inkscape:transform-center-y="-10.724829"
+       inkscape:transform-center-x="9.5306165"
+       cy="636.8053"
+       cx="734.7594"
+       id="ellipse12300"
+       style="display:inline;opacity:1;fill:#3498db;fill-opacity:1;stroke:#3498db;stroke-width:0.39663559;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.97635139" />
+    <ellipse
+       ry="4.1593032"
+       rx="4.1581793"
+       style="display:inline;opacity:1;fill:#3498db;fill-opacity:1;stroke:#3498db;stroke-width:0.39663559;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.97635139"
+       id="ellipse12258-3"
+       cx="490.28964"
+       cy="617.81934" />
+    <ellipse
+       ry="4.1593032"
+       rx="4.1581793"
+       style="display:inline;opacity:1;fill:#3498db;fill-opacity:1;stroke:#3498db;stroke-width:0.39663559;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.97635139"
+       id="ellipse12258-3-0"
+       cx="689.78961"
+       cy="617.81934" />
+    <path
+       style="display:inline;fill:none;fill-opacity:1;stroke:#3498db;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:0.97647059"
+       d="m 439.28963,637.81931 50.5,-19.5 -14.05,28.1 0.925,-1.725 -5.875,11.75 -0.25,-0.75"
+       id="path5161"
+       inkscape:connector-curvature="0"
+       sodipodi:nodetypes="cccccc" />
+    <path
+       style="display:inline;fill:none;stroke:#3498db;stroke-width:2.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:0.97647059"
+       d="m 734.78963,636.81931 -40.285,-17.00922 -4.715,-1.99078 29,57.5 v -0.5 0 h 0.5 v 0"
+       id="path5163"
+       inkscape:connector-curvature="0"
+       sodipodi:nodetypes="cccccccc" />
+  </g>
+  <g
+     inkscape:groupmode="layer"
+     id="layer6"
+     inkscape:label="no:des"
+     style="display:inline"
+     sodipodi:insensitive="true">
+    <ellipse
+       transform="translate(-387.41463,-589.81931)"
+       ry="4.1593032"
+       rx="4.1581793"
+       style="display:inline;opacity:1;fill:#3498db;fill-opacity:1;stroke:#3498db;stroke-width:0.39663559;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.97635139"
+       id="ellipse12282-8-9-0"
+       cx="587.3924"
+       cy="855.64899"
+       inkscape:transform-center-x="9.5306006"
+       inkscape:transform-center-y="-10.72485" />
+    <ellipse
+       transform="translate(-387.41463,-589.81931)"
+       ry="4.1593032"
+       rx="4.1581793"
+       style="display:inline;opacity:1;fill:#3498db;fill-opacity:1;stroke:#3498db;stroke-width:0.39663559;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.97635139"
+       id="ellipse12282-8-9"
+       cx="587.3924"
+       cy="839.31183"
+       inkscape:transform-center-x="9.5306006"
+       inkscape:transform-center-y="-10.72485" />
+  </g>
+</svg>
diff --git a/contrib/ci/buildbot/buildbot-update.sh b/contrib/ci/buildbot/buildbot-update.sh
new file mode 100755
index 0000000000000000000000000000000000000000..6c9d28b2546565b4d0e1cd96af761e95b64fb5bc
--- /dev/null
+++ b/contrib/ci/buildbot/buildbot-update.sh
@@ -0,0 +1,27 @@
+#!/bin/sh
+
+COMMAND='svn up; cp -v gauger-cli.py `which gauger-cli.py`'
+
+#debian-amd64-grothoff.gnunet.org
+echo debian-amd64-grothoff
+BASEPATH='/home/buildslave/gauger'
+ssh root@buildslave "cd $BASEPATH; $COMMAND"
+echo
+
+#ubuntu-armv71-evans
+echo ubuntu-armv71-evans
+BASEPATH='/home/oem/gauger'
+ssh root@efikamx "cd $BASEPATH; $COMMAND"
+echo
+
+#freebsd7-amd64-wachs
+echo freebsd7-amd64-wachs
+BASEPATH='/home/gnunet/gauger'
+ssh root@gnunet.org -p 2220 "cd $BASEPATH; $COMMAND"
+echo
+
+#wachs-lenny-powerpc
+echo wachs-lenny-powerpc
+BASEPATH='/home/gnunet/gauger'
+ssh root@powerbot "cd $BASEPATH; $COMMAND"
+echo
diff --git a/contrib/ci/buildbot/ssh-config b/contrib/ci/buildbot/ssh-config
new file mode 100644
index 0000000000000000000000000000000000000000..857354bf338844af03a2a15dce5f3ebc058c0845
--- /dev/null
+++ b/contrib/ci/buildbot/ssh-config
@@ -0,0 +1,33 @@
+# ~/.ssh/config for buildbots
+
+Host *.buildbot.gnunet
+  User root
+
+Host debian-amd64-grothoff.buildbot.gnunet
+  Hostname gnunet.org
+  Port 20004
+
+Host debian-i686-wachs.buildbot.gnunet
+  Hostname gnunet.org
+  Port 20000
+
+Host ubuntu-amd64-wachs.buildbot.gnunet
+  Hostname gnunet.org
+  Port 20003
+
+Host opensuse-amd64-wachs.buildbot.gnunet
+  Hostname gnunet.org
+  Port 20002
+
+Host freebsd-amd64-wachs.buildbot.gnunet
+  Hostname gnunet.org
+  Port 20006
+
+Host debian-powerpc-wachs.buildbot.gnunet
+  Hostname powerpcbot.decentralise.rennes.inria.fr
+
+Host debian-armv7l-evans.buildbot.gnunet
+  Hostname efikamxbot.decentralise.rennes.inria.fr
+
+Host debian-sparc64-wachs.buildbot.gnunet
+  Hostname sparcbot.decentralise.rennes.inria.fr
diff --git a/contrib/ci/buildbot/ssh-keys b/contrib/ci/buildbot/ssh-keys
new file mode 100644
index 0000000000000000000000000000000000000000..6fa51071b916f828be5a2dbde727a3d45ebf376e
--- /dev/null
+++ b/contrib/ci/buildbot/ssh-keys
@@ -0,0 +1,22 @@
+ssh-dss AAAAB3NzaC1kc3MAAAIBAPmoUwxO5VkAR2j7AJh1/UfySsvtqPJWlzZ4i33LoNis6KpaHn7JO9dEL/psg10ZAqqqFahcTvqFDeXjS5DBzOHWA/u0TgXj58i1rOO2TgmxKF3UatYfD51omlPvw3IcnTPIX+Dsiq/cDkJAHxBdAYo9KjFGu9hM090UN7rY/ykBP/VwKbA/9fg0ASPgGrRF7JRylpMu424c8CbvM/iMZCew2BeE21g1u6WgewJjLgWcdGH2r4GO2FPvHSUlVJJ/wXdCDweboPsB+CuiEmBVruKcbG+DJddRWe4L7aUnIHTL6/i85bNwyjQ/toS2PFBx0jp04OcMyF7PxcIeEYI1+cimH//XIo3eOESGjRWpOKJR+yWlxcg2rKTFuHDO1tTTgqC+e2Kcvp7XrQPf4RuBWtD2YRGUMtEhQhvt2+Qd7KDQuuYR8TPXhHEh/sh7pQkCR/I9ijkxiPTCINjwkLD9X6tdYhT0XtG13dweog6EDrxXjtiIM1XY+jfTYvXVmDIn/lzvEfnhMkErTu/ZXt8bGVIRC5THDASFdQTnsCnVc1OU6AH3xVKa3F9CzOCwhrJ2EpQQMc8022ltmBYu9wFF0HPDoe56mqKdNnHDeaLp8CCuf9pLMeih9csYJlAQ3GsOzX9WR044+JqbS+b/++lOZjJdFlUlONZu0F+166rX4pipAAAAFQCA2XLNDkiQ93HpAFgZmBbavTVdxQAAAgA8cpggPUORDfTcgWgcdrJCQz4bIaGKdD/KhiLu15FqF02WkBYC8xsySK8DHkS41bHiqLB8vM5Yh2FiTjpwIzpQ9QH74JSdncUMxYncEcHrlHulASQZ7fuNMFK5vK7XVY2zAjrsjP+/H3vLrEOBoiI625gpGMTLB8QILBBbkGTpQ3Ks6LSJqEQfsCHmGYUhtkIQjgWIzDyzvvAOCjKMjNpkFyEKLkUYIWajt5y8AaFW5uNeXBqk5ejV4Y4pUg67zOJt92moqK5TQWIEjL0kKM7lFMXZDZow+DQQ47q9NYPLWVAwgWGbCdvvewWkJ5+xMTbxfTZgcUmvXz1zc/yGXoeSLoL+iJKyqQgEi6Jv8a+TnnTZivoxIgWYd/uByUvsxZrMXNlc1MUTKNI5CnEz3Dprb+qHw36SXKymnhSgC2948YRTWqU9emR8qNG8EKOoisHX9EPq+Ex5/IJQh2UlSScpnt2xANtoAZuEt/P5W6Djq6UtwMyI8E6yycEP+myKR/JKnydzjtxWEQV9ytfIQQkndPCr49N3RnrVA47aoBzhUQfiLyWbYFpc/oTZRhL5X86Sm9dXDhIyaPslSM8/C0DqzfhqOw53XxROj2IAAu3Aqsg4mkSEwuPzv2PTj0KjagGIuz3J/71CpUOz+6CUWh+tCzkYC3joLYXh0v/MUVZ5JgAAAgEA9IO/Nv4zdZtHSN2RN1lEyGGi+Oi5mFS5Wjo/tsw3VM53H7HiyxVCE8mcLWT/UOEcG4uitonxTUypZGhNra7sTkbje5tuLVKF99e3W4/wV6aWwLpryeZL5BOhlnmTJsZPgTuu3A7eNnh+C45L5SW7qmXLgS8jl3CKqGdzl3XO+eB5oN8EIjWGk+VbD0iPVYobDEUOo1TCj5ZGUENw4R6lRXKsPtHDqa+iMGSUa6hQXaM13oJTI+P4Dr9WcUjqbceHT3LPoYs8dCT9rrqHDX4HGIJr9A6aV/djPVoloPgONQVfqW+xci+yUVYLp8Xdj2zC8P0NCOWiFzke1v7fFvDzs2stotAfXtLvCHje2W4rbpz6InKfbysOEc/o2ybeb2Pu9F6oIamd9qiZhCGog422YyNh1+w1sAvUCBHuF38zPHxDB2YgF4tf2K4kU++PAuZOxnsYLErZly9Nxm2uGKvgKAEgaeMEYR1jK1llRmiGPIapJZIk3cav8tLEP6MNTrjDB52D56DeLdPrgL3cUfLtGcZOJhyBTcz5W07kyGQyT7VZiqlErsg6KQxRzEda6DWNYCAMc32yj8kgEY5hCt7ei1cfyL1Wox61rrdchjGgBDxikVeUL/Sw5H8Yuh8o7j6sT1RHfui5kW5M0ykCjKMniDiOE4sBtVSHFouERamDKA0= grothoff@gnunet.org
+ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAgEArczTGb2rBEUa6mamO6jx5CILCMcF3ZWYlDOk7J0OavsqFV0bnpwKQVypW1TEXwFXgzXJvg6dKenpmWW3EPPN6S6mxxyA6O8dlBwRKLtaFQ5L1KBK1sGt9/1jN5UlyciYxoyKCpkb8RPqcb0u+uzO1o8LIiBbJc/52iiNv2FdgLIOFntWytoV63uXQ3gC1sMJWX/AgbifZpSAijYJEOOU3d1s2944EKT0ZmyC8mKm2lAq8/OoJGM0er3pD7jmd+5CLoiEQWUiOlNaJ14a1Pqv9DoqqsIsnJSrvigAX1JIdgD21BmD6nqwbzzE5SQUatC2yErRFHX0MZAJRpt+T1x56Gqt/+VUvVEB9dW0q5ZCBf18knlROjR8kXHyzbibiXk46W44oP3Uf21/MeoIEzhiXxODXMKuJnqDcxJHWN7/bHbEBDPdfucpLSChlx2F9tKRhfJhLJ/YItC9qUb800PXcAVW25un6KfRALlFSQuEhFoOCq8K5Eje5U/9RMvC0eFV/6V0bmlnDzicjC1XgBfjKL3oCvIxjZizKgrKgU+WT4Y1eT8oP2D8+HYAyYsEGhPYkMUY4Aqan+UcGJppeKA/3xFDEP/fa0Usvi1r9cMKgL3zt/23FTGCDz52cNq50sZgrkIQEUIfk4qGZi36L5GvZtGVU/oIGr7hwBmpAt/PefE= grothoff@gnunet.org
+ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEAxpjDxPCAVHRmn/D4u7DtR+P6DUhSOiVXUMTC7VPcBpfBzdiEjsdlME1MBvlYJ5kXUENnB/zpPGNPVj6OCk0nQLEK6nX8diaJ+U4T13EiT7+HAQjBsvil+lWIsbKzZ6CyRulkcextFgi5kd/VM7QL+oRTdrP6Pleky/MvrcUEz2W7z4vLM7SZXnkMvIN19qhEW5HTkVzi8XhPQLplWYL4QdzvL/VGsPRmFY7/lRCRp2iHgJuxBSnGT/S9HjgbC4VlsSuO+I4ee6GgR7A0WcoCFXAkxXu43IcDnceRcWSY0e6vJlg59T4QardVBfRdxmp0g7YSft+ilrBdCD3y4T68Sw== mwachs TUM key
+ssh-rsa AAAAB3NzaC1yc2EAAAABJQAAAgB78mdEOXz5qMmxtNlsazJTvMkLc9GCO1Hnp6sNvQCecsXs85aEiGHDiJsJAVH808KLqfZ5cFN5as/6JZx5bAc3WhWJFXi8oGJT3iOiPXVtdu3yPjNAN34eW18fzYGs4QkDvj6Xf/BZZmAivK/hebhlgG/knNWaOPpSzQIexqcXbDT/hkD1Izr8W/ObGA8uben2ucOM7uuKEGPQAZn901RwRanKdFIiBE6TRbXbhaR23/ygjNMmG20kRpIGriWJ95wrw8E7ZnYnAnXzzg/4GWgzf5gSGeB2LopZ474Wz1OqZsmzSONIKrQ8AI7e2R0mfnfU9NG18m2GrS5l6zuplbQNECrZf2fTROpT8fAaKqlQ0iXfFI8tZuOPT/j8hB3RlZFPsa1mdyZwzCvON/hJ9nBtLNhIuXO/QWydQ+smJxgBBdtF+q3EdEn++0RV7lJ+RrGoexNyzLDVuOQX/1HPWjQR7GzxGmbIL4IhJ4QSvrOLMMrWGZ3JwAbDgxT58WfOFWGEzdeAESCaTo/OHS3zm6K3qmyY+doa1cVrdoyPV9+L32iP1cmRQF5j6P3it6TdtxStXDjvyMd0j9wsR0+DL5Hmxt/0mjXScTuv3slwGan1gs/MaViLXY3E4zSLnHS4YkNA2DpHND475VYOEECLgZrR16zIhsl4C6FpPp3m/mdKyQ== ndurner@web.de
+ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQDWlt7hcFgIHyvCuCw/4S+iP6TFi7aHs1RCT7FzePK4KWoxqnrTYRNhtJsAOHFXCUw8U0V884P9e7SaglCuwrxEQ77CVDDJViI0CwJd3WqB4ehJEbzZYrQmexyaJ0rKSUvL0QW0pQpDuVJswmGK/sRAoEHyTZA9L9b76RdJO0NWqx4tAZau/2AMaxpsJQ3uePeZbabNIbEWdfX+35zCg8hDJfkk13vva68y88y4cPeuNxBti0K9LunhQAWZGzB0Is5pOMzWJ21rNF9ZVXn7kwdFX9gR1DZUEnTe7byj/GbGe2NLIfLxTARUcS6sJbAKrd5xqQH2FbZFiyUU5HDGZxFkRMIPbjypF2Q5fHT8UAc7UADy548nMWUuCXkL/Ji0vpVFZgFzjPQk28v2DAN4vh/L91Gwsd+LwHkW1EKTwq1wbzjeplNc2+vu6knFNf5zhdwlW8EMTvbg8+GnWD/PJEmmY5ci6b5f5WeR8a7YW7UKrDOS1yyUHyXSQ//gXxbelgCSwJnASTU2O/7uNcMh6/c7tpQ9n532hK3t9/zp40whqFJofkJcOYsaJHF8tY54efFPQcQKiwi6U2s2FJMis5yM2+LvOvDmfpiU4DkfR2F8dkhDLnUmZ+CfyoKmRTuDXSQiW7lQPnmPiexfy6XHlen19vFHF5cSxRgClFYJmxz0Rw== bart@ranger
+ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEAxcmXWIGT3szxGyBDHJhORmCsAmfFYGjt3eFDPLcVgAQ26ug35zwtYT7CAeYrEzroau+7t2655Rj3TUkyZcibbhYCsst/46/Qz0beOVsS+GNtRjJu55jbaFrIxbvdidNUV4IL/cBgd/+yXiqyAD9zl3UO4l6yeCL5yXimkgsiyq2/c6LXPcdZRrwSYuJnUwqgiFIz55vOyF+kJfIc3LrbqoEBJZmxMYqxd2ymoNVaMr47/qHnries0a+/p9YBYlxoBBMIQzn+eq5XXkOsAcEkDQGpTJ46hC7JgcyKmSou+KCmilj+bL1b2L8lJt3KGFqPjShGeNx6838kMMfiLG8xVw== totakura@in.tum.de
+ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDCwY5XSDyXVqobwR+UfQ0+lPJTVj8MchnOYAJWNC9xvks4s7ZapBkzbpxcnCi27hb31NBtXECgMCfbDI4HuaaphgbGZjOoIWQeMLn8yHCgo7WJT0KDm4o7nODl/6drgab9XmQKhobTtrzmM+MY+MPCSXNDGRk53rM8knT+8cuPsdafEUa67mTC0p/VQJOgX0JVUF45MfVUtl1914Uot22AMHChGGg+7EMPge9QV3z5ZlP9tzXLUkw28+dkeqkXhGgAtBu2alaAy+sxiRbVHVgedOQzYCmhfQZBly8wMBvlnnTNLK023jT9FAp6j2h9/mnfGaXncElzZqkqMTXTkLe1 dold@dold-ThinkPad-T400
+ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCw/lnVcAoYrMhfRpr6iXlpyVWoFpbJG7sxaNmNKR6qxASNg5tI3/+yPZ/UVL6H8AjEkPhGq/4+Km22ofolNsNtsANJn94B7va8eAyPrY097MV33srTNXpylaFRH6JUq4wxgLTFnG13FQ9eyzr2NPwlJqTtosdzvn2pRfhxG5phYt0ZXPE4jozUgPhxlrWMsORHzlDyhoyYjRMvXHo/U5dXPbq0t5SIdPJnj1poJqKzB9wZGk3vgDiYNKUuWW2h9lqDqUqZa445UZH4Rib2Bll45zJYsfLNj+iqU71djKVfUoUlj8lRQXjyiDhsUgFnBMCJrEYzkCKMYznZrHUp/9NV lrn
+ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC9oQC+WndedWTKdjLPJGiyiOrlSStLBaLOSNLWKso3xH24MCD4ga55Tf0ZkKFCwalC/LLoftD/z0nnyxbTgoIKrtDjSycet08HL+2p/+e1Xl0kbqLYy+e7PmUdkxgBuIPMXHpFexcn0O44oCDsP9VE28GUJcjWXL/l07wvS7tvIip8sxxz0nf5AJ/Ixa+pjFbTD2ivh06KfuRJNeyxrS1yBtL7nA3LOgZahcX13WReJM6zZapO/hyX24eU+cQJqN9Hgji1qBYRqtRhFrl3/7w5fpv0pV0Dzjh75PKhThAUV8Le8X0pCTGlooMD989ToXi/m3vj9BHXx30XedEp6NM5 harsha@nautophone.net.in.tum.de
+ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCyWni+1l6L4tMhdhlEe5+yVv9Hr03tvtKJkmjqOpJV37gLisdxxWhfGYGNycccpqn7lZhsU1eCqnfEuhhEHZWcWUKdY3Wx8xKzBt5E2wo0Kk/oyxasLxSv542fP9HlKY0/GVXJG8wf8XkiPdOAU9aMVeDi+qrQc61SF1Zyx2I5QyfuJR72lmOdzHFyUUTT0YL/ug3+HBoHFqk8NfgOEQe/O5/Ppj6n7iUc+LOJokq6eFeg7m7uszfYpy9IWrVelPG2YxH4t4TXpKpdnRkg1asNqHrWDS/COoCx+OlIknAEVr0P2I5YlUp9dDYU6qPVO9G2PQAuv36UEVOwahaXcru9 tarabai@devegypt.com
+ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQCRm+/pobQVbTqfosN3eahouoKmOMCAxfNM/nQT7ELJWIGlKHYAgmwiCQcYzFZvUEqqfLhIOQ6WgeLvl0sqiCkzvz2LuFHhePqQ9QmmP1zple+9GEqP86RUOarrJZTkx5HPszfn+ak1lpYLD2XoBItKUkTPL6nRNLX9mSPX+N0w7UapuM42QrAeGWv8Lv+U0idJ9akpNb4kRgW8DTeG01EM7h+Tw0iSKA8J9QKe7Sz4X/jTD2zZuCmIzK4/PhvypCcyEfn/e0E84qcPMkH2YulxSDtnSD3UkLgyI/KeW2K0HzKoyRs51x62L9xuNbFwaqVkKgU0Lx+t1II1RU2MsyCQHMR7lqFGna2j0U6aYsn/fubxgh9yiuqHEaK3MbjKlHeMOGAptyDUJXzR8lTrQFW/dF22KhA6gvb+S2uI/MEMlvS/7xLCpoOHMPr72k+R/W4bVhNfFx+msUt0PB+F/WLpuHRmPETOijNempQsspKEIexC0zVIngMXeNtH4w/ZyUa4LAsKWnaJQGm5Z5148DMMJbk0P8wTncy5F+mSngupwBs3LzPzDfdGYqUT/W5QV5yFrHJq4qYT7rf0nzNU1KsUIrpJVpul5jW5bzgJH4uUAiUpzXiTp7pZZpwCzJWvNJT2ttvYTODHxAGBcvGlM5v0UUrKgqiGvOCnTGr9H/jgTQ== cfuchs 
+ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDEKm10NKw0pdcJRBfO3o32KdhEiRVvu34cNyiobYFFVX7wBPyeqveFD5NxuRbIibPnZh62aw9areWwlZydot3jZHHD8XqgIJH32WdvOoIqYSwtL9iPePk+yzJ4mSAgzYe1v/FmI7yGTWj42SK5gpDME7qPClmP28vJyc3TB6KkvPZFnjRTeeaVIAhdIYZCxItxiCFQcJELvmeoAhHPtM6ug2OHEOdHR12Rc+phXPCD1F87vnHyWuDvqHgcpiIFncce0kPscFsjt8o9nWzG7lH6KuMT8wIio/ybKRYCC9kVmE8gjEIh56HCL2BlOoQo//h7thVLJZJTOSwyoloNzvuv oehlmann@in.tum.de
+ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCZfH/w+XKNgMasTaqs6BqX8IbzA10gD4on0jsYV35CqW/wwmHEwj/7EmThY/yLnzUeNMcHFs3B11p7ZTZvlZ2WZJ5FZr/0FMoWXp5uMN9i6ykVa4D5WoO+VyxGhZEtrHb8+lAl1ekXep+gTwViKNmSiu+ogJ2f49h+losbEsLFBV0FDTUPChFYpSB3OGTuAkTuUJ6qxDsK7NpY4nXTLG3Iyke7LjCw9uTkSP8a2q2xzheXrOG8o13F8CBL7hGFc6laZG3TfmM1WheJJQ+CkY11s0sRvddEhKlB7Ru8u23Crw5cJEkHiKUOyFln3+tvyLCb5ETlbMlHxhZVPblsYN8L martin@nietzsche
+ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQCud/+43em7FFIm81c7POZ5TwheiO2w+ZNajKn0sDTBgCd2kf1bKn3bancbYC3kp574iFVmy91NaGJY9XZ5tLHrchFZjppM3x6KVwxY3BTm5ABSmvgNYWZIM2eIbLDWFinOV2QIJrxYY6XEdIOG6ZyQ/lqyITopmvRw2tqvdnz0PaSjAQpoLwY8HxfgNSNeCTbh2xQC+UYEiMOmANJ5FjNA27ZpLPZB+RYpAFu4H5EU1uVMUwjFP8GI9AD1DcnNsVn714IhqS3U9xjB8GzYvZg/KgeniUCliUYfHdrxyNcvgcWClDvVpdy7vuYdZObiBJjs2a5AXEXUoW5AEeu6/ODBGCTL45IpHSR6wB5s2pSU3IwAxbyH6fPB0mwbijYZmHLvNtD3Ka1+dessUrVyVBHSoteWyCuhmTr0r9QUsonS4BDr808SitJ6DXWheSupckdpCWo8c+UnMkvHTXEGCU6YZVaGyZAXEIF8iO6bYLV+IJU2BnoRgWi394NHRf/OIK99Tgxwqlclautm5A6q6gSshg8rgvLgt2tj7dmIqDFdjk/foyd7BEAXMBv4QjJGOJQu0w1i4igFNw3Kg9W5pDmhRgERttjkbXeqJA4C8t90TKigLeJ+gz198tCf4XI6+YtTld5cOTpyzI9h3G3mSCIrUG1Ik7gDcibAu8uKThyEbQ== tg
+ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCqlkUztOQ65gRvfxI6gwkP+095eEEc5DtHzZd1x9e7AWM4yF+vK/LkQPC8Mq9fwSlN17oFFM/07CeY8LV3RQ3wck1JgDECobk6kByUtxhFpuKlViVz3sTD5KqeQHzoQXwxb5fZWuWkXs2NmalpEMCaSNDnDQdyL/PRNiWF6FsNDCSVa8hhHcSzizrF/RL0bfhzQVCSMl5RxsOQ6VEqtUNeImEyQYQ0ijlk/NErcHKipjVkj9Sa4DMKKztcccj8AEFYoqPoJrZ3pEg6puUiJ2UlPllQf7ba6+Z+U91kN4i3m8PwcuuUh5ky3cnQe2D1njUdnYg0Vamug2xrAebNSHdT supritisingh08@gmail.com
+ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDQ2JbS5dNBxiSRGeNIE+VvvJBUStgndjduH2HmGyy7Z7VGNrykSDgjkcLj1+808zWzkniUZTUKvH5uT4rjSYrc8Au2l65e+J6gYypaOhn7oQKW9KQ3P7K8VpHSc407iQk0fM6bmpRKcd5GK0U6mlpi3nKvPhd9JttwfeNF6HWo4goCuYXdnLmWIimP6BBg6dZRBqO0y00bjSlMJmHnlQXI3YUBvceB3tBe6hOaEx5X3pCpE9CPaAUp6pAohHv97k6Dq7OcXeJulDaHKYvEGTCOq5v3V4zSYH4tJCrAO5OL83fsoAwn70l2qy+BkuThhiud2cff/jL1gB1+oU06s42N bart@voyager
+ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQC4/0jIkaaWtGolhWJPijpaPA1QHeQNlaZTc3wlCr/PGnFxY/TfXMKwEFX+JBvtYAuBsD+NXshKUssFtDSSQ5ljqbjGfA1SFv7ueRcuEVfg8MSTic7crHo23afjYWC9GND0LFDwy8IGrT6QtmbOV1cACTDk3GRcFT3wK2ZsTYAlsq7o+TTfD6A2OncqQGyIrgZl+eNx3je19xQ6OK+RTOXhvsNx77IdOluNkItAS8XEJpqnrYAqrqrtX5eyzHkwmPvu/gxrjO55YuXXXj4yramy5j++SkjH1y1XXMdAl1zNsDwT4U0/bNLm/0vvMQ8qgEVOak6vq+Qw0iyIyJP6RFI/J2S/mISCGyasAWULynhFP0DaCwFkFOnn3tv+A+caoxYKUU3nD+zD2q04FaIaOastTbDfeUSseHeKX08mSHxcPd/alYKcXA+Qm9SWsHGHJ8PAMPJNOcMwtkgGDKKzKJLW6CTUIEgl9BZXs0GXv1erAYu7zqNCRU/PWIKV2J509sk65dkykDRDkHMJ1esG+2Rg094hbNHsB4uoRZjlibS/9WYEOdn1eLt2xAvMXa1Vs8RpysMfv98zJabz8+mADf5u1prLGk9zSQA7akVoFe6OLqnQBVJr1E5simMZaCqZBYbYfgTveo8xtPZw7NDcH6/xrV2j0sN2xGHfkRFpuMpnCQ== burdges@gmail.com
+ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC4UL53uXZCis1C9VNWJjVXTtyRHVmzFmg3vajTXrRF6LBYpEtDRA3OCtzCsj88AlL2VEtIiBWBqZrntE0TKDia1Czru3sM1ieKCra1F1GlSj4Yk+7VaRSS1hGwMBUb0zyaiIHjizGH45+zL5TXeAiGbeiF/iiRJJG/qQ+txTXVg51QLuMv9W5wKs9Dz+o+vbbUwVaauJo/TmhVz1VFjqhQBOt9N/CtaTe84B1716/d/YTZLH1bmjxMja+a6aCyABaPM5JcMNYEZT2UMCP5fTyJRUpfNlimpdRkcxaA5/K8AKTW7R35cQpLrngnnOChUB+KT6683omDr2edXGqkWNsZ grothoff@firefly
+ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQCvbeMnZGlujN9IsLxUSTuHBUESoN6ZTXmEFi/GkBKp9RQ7xZAS84JDcV0GFddiCfTHGQL04mkeYXkof5d9NkMWjtTvQ9QFtUgGOqI3PbGCGW83vSwJHsqVbfbv5uqFCODjpTx4/WiJNkEpN/HgE2eIYFcm+Dcpo1vTgC26LjdMfqUaAGv/OTmKWmaMqyOzc4MXuUiBQT83oTfn2zSWDEOJG67yULqg5jMzaXqzPbhsaokBIPehks0bJR/q7OWNwDQJyM1oTKeRIh0ZmC0qYwGu/vlc3rYW4cp//ErAXG5iPfCXXUySUc0DTFHazzkNzUStuUwugznxuUCgbvg2tu5WEnrh/PpzIMuvNaUk2ZSDq00hHDrpVJyKKCih2d1cGV+qs9XFjDoD6Ch2NiSdPnG7fSsTxVw1SB7/APuMqfXWrQDfT5ee5xOKGzKOxQckGihQi39kmqf4WjNESOw4tmhNFZOee9dpC7ESYSpG/3zK8WG6FDln1nU6rHGjVgaSK6HwZUOsneS2fntiQZR2olzEY9+ybL1vh1fk6pkhS78X/PiwS3cSiu4q7JWJ4tUiB0T/cHAFBaODDKHXmEaGefLrPBWLLFRdjbnepWo1d0k1z/NLVovXDCGlF4IOBKqcImIffods/jTpH0hjU/vBjIQHH3Ii0J6vtGJw9whcNAGQfw== t3sserakt@posteo.de
+ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQDRzeeUMJKn/9lY8FJIuU6HuQpWZozerTtbgsoGUNW0n0P/RsPYMQjweURDlJyKQisSZt+xRzRorSr0j9P016L8N13wGR9wtJwoJOi8DpwqEMxleYwPAZOu1zsA1Qty3ftNu6c3xB2wnlSPC0oZ2RYBOlxvIGtSGoNcDY43MKmsJ+IPsNpKOOS3x1J+xE7jOnQ0LHvxt4b54Sdr0uruTbHupwBbzBIxMFzS9hzEN6gL5cYp2fggZM8Qt707UlzIUuNzsU50qM6A8UJ+0Kun1GhKhK2J7T4Dok7M6m8ZtaKGexMfZwCl4luXlP/r1Kn48kXx/EtoQ/OcR23ymxZ95X+X8TB0ZdYcj17M7B+kk7OFz/2SVdJqYDqnMIOmXtAEdUsmSAmI7YxWyYOutRnEIkzQvHfW0h3D2pSA6EApR5huLOi40N5Ga3XLSBJC1yC8+qdiNE/t+5nGGxdlLvJ7VuzkwTEKQs33LNUdS4qKVBcIppZ7yUMjqJ5VzFk6xwEqGPCYcEWzYpNmzBiE/EFvwVSNV15Rknyieq7RB/gY/DNKX7yuC7lRZdEgGG6xu7l34c1ZhtIFhUGCnEtYsx5kJQFGMMP7bi/LNVnm+M7YZGp+uKgsnmWzrYw+YORzLwqBncs6N1tvwOG9DRKJ00S3JqSEDJ5FH/VDIUlWWbIgNwtAIQ== lurchi
+ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC1WzIhCxeYQzjAHvwkSN7oQ3hhakwLzrTC6fXqnGUn71sQQKe4Rb2lmcUqVepnuKx2wEw3GLev89rVBSXwneiiVHwOEPNqFJXKHV5AsQbLYBvt9qlkK0Wff71Ptc9xB+M1qDVluA/4ieLDOemXYvkcK/6fqimyIdBMSlXSs2PKQkpjkAvE3qh0c41HKlagq7Y4rHV/chs1XPWCWX19ZO2EnZoVx6KeZHouc/FoE/lC7X1FudJxSKf5ZIcy3CIiYTQsL//hb6DT/mCgssCL+NtTDDXNsYiuIlj8Oi+nCpW/GkisIeyTZpbPiokDP+r0V3T8jcMbbGCVN6Um33lG2/LR amatus@atom
+ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAILL6PhAcMxsc4GhRuQYRMwchcig5qTDQQFZBQzxFTmxI dvn.me
diff --git a/contrib/ci/docker/Dockerfile b/contrib/ci/docker/Dockerfile
new file mode 100644
index 0000000000000000000000000000000000000000..b9f019c4392ee2885dec0c0dfd14bebadb1489fd
--- /dev/null
+++ b/contrib/ci/docker/Dockerfile
@@ -0,0 +1,32 @@
+FROM ubuntu:18.04
+
+# Install the required build tools
+RUN apt update && apt install -y apt git autopoint automake texinfo gettext autoconf libtool libidn11-dev libunistring-dev gnutls-dev libgcrypt20 libgcrypt20-dev libjansson-dev libsqlite3-dev wget flex bison libglib2.0-dev libgmp3-dev libmicrohttpd-dev libglpk-dev libextractor-dev
+
+# Install gnurl from source at version gnurl-7.54.0
+WORKDIR /usr/src
+RUN git clone https://git.taler.net/gnurl.git --branch gnurl-7.57.0
+RUN cd /usr/src/gnurl && autoreconf -i && ./configure --prefix=/usr --disable-ntlm-wb && make install
+
+# Install libpbc
+WORKDIR /usr/src
+RUN wget https://crypto.stanford.edu/pbc/files/pbc-0.5.14.tar.gz && tar xvzpf pbc-0.5.14.tar.gz && cd /usr/src/pbc-0.5.14 && ./configure --prefix=/usr && make install
+
+# Install libbswabe
+WORKDIR /usr/src
+RUN git clone https://github.com/schanzen/libgabe.git && cd /usr/src/libgabe && ./configure --prefix=/usr && make install
+
+WORKDIR /usr/src
+RUN git clone git://gnunet.org/gnunet.git
+RUN cd /usr/src/gnunet && ./bootstrap && ./configure --enable-experimental --prefix=/usr && make && make install
+
+RUN addgroup gnunetdns && addgroup gnunet && adduser --system --home /var/lib/gnunet gnunet
+RUN chown gnunet:gnunet /var/lib/gnunet
+RUN echo '[arm]\nSTART_SYSTEM_SERVICES = YES\nSTART_USER_SERVICES = NO\n' > /etc/gnunet.conf
+
+ADD docker-entrypoint.sh .
+
+RUN rm -rf /usr/src/*
+#RUN apt remove gcc
+
+CMD ["sh", "docker-entrypoint.sh"]
diff --git a/contrib/ci/docker/docker-entrypoint.sh b/contrib/ci/docker/docker-entrypoint.sh
new file mode 100644
index 0000000000000000000000000000000000000000..db916cce708a7d506b4b665167e59f9411dfdecc
--- /dev/null
+++ b/contrib/ci/docker/docker-entrypoint.sh
@@ -0,0 +1,3 @@
+#!/bin/bash
+gnunet-arm -s > $HOME/gnunet.log 2>&1
+exec bash
diff --git a/contrib/conf/editors/clang-format b/contrib/conf/editors/clang-format
new file mode 100644
index 0000000000000000000000000000000000000000..aa6c2aa17fe4544c395f61c12ca0d2b5ff7a6456
--- /dev/null
+++ b/contrib/conf/editors/clang-format
@@ -0,0 +1,123 @@
+---
+Language:        Cpp
+# BasedOnStyle:  LLVM
+AccessModifierOffset: -2
+AlignAfterOpenBracket: Align
+AlignConsecutiveAssignments: false
+AlignConsecutiveDeclarations: false
+AlignEscapedNewlines: Left
+AlignOperands:   true
+AlignTrailingComments: false
+AllowAllArgumentsOnNextLine: false
+AllowAllParametersOfDeclarationOnNextLine: false
+AllowShortBlocksOnASingleLine: false
+AllowShortCaseLabelsOnASingleLine: false
+AllowShortFunctionsOnASingleLine: All
+AllowShortIfStatementsOnASingleLine: false
+AllowShortLoopsOnASingleLine: false
+AlwaysBreakAfterDefinitionReturnType: None
+AlwaysBreakAfterReturnType: TopLevel
+AlwaysBreakBeforeMultilineStrings: false
+AlwaysBreakTemplateDeclarations: MultiLine
+BinPackArguments: false
+BinPackParameters: false
+BraceWrapping:
+  AfterClass:      false
+  AfterControlStatement: true
+  AfterEnum:       true
+  AfterFunction:   true
+  AfterNamespace:  false
+  AfterObjCDeclaration: false
+  AfterStruct:     true
+  AfterUnion:      true
+  AfterExternBlock: false
+  BeforeCatch:     false
+  BeforeElse:      true
+  IndentBraces:    false
+  SplitEmptyFunction: true
+  SplitEmptyRecord: true
+  SplitEmptyNamespace: true
+BreakBeforeBinaryOperators: None
+BreakBeforeBraces: Custom
+BreakBeforeInheritanceComma: false
+BreakInheritanceList: BeforeColon
+BreakBeforeTernaryOperators: true
+BreakConstructorInitializersBeforeComma: false
+BreakConstructorInitializers: BeforeColon
+BreakAfterJavaFieldAnnotations: false
+BreakStringLiterals: false
+ColumnLimit:     80
+CommentPragmas:  '^ IWYU pragma:'
+CompactNamespaces: false
+ConstructorInitializerAllOnOneLineOrOnePerLine: false
+ConstructorInitializerIndentWidth: 2
+ContinuationIndentWidth: 2
+Cpp11BracedListStyle: true
+DerivePointerAlignment: false
+DisableFormat:   false
+ExperimentalAutoDetectBinPacking: true
+FixNamespaceComments: true
+ForEachMacros:   
+  - foreach
+  - Q_FOREACH
+  - BOOST_FOREACH
+IncludeBlocks:   Preserve
+IncludeCategories: 
+  - Regex:           '^"(llvm|llvm-c|clang|clang-c)/'
+    Priority:        2
+  - Regex:           '^(<|"(gtest|gmock|isl|json)/)'
+    Priority:        3
+  - Regex:           '.*'
+    Priority:        1
+IncludeIsMainRegex: '(Test)?$'
+IndentCaseLabels: false
+IndentPPDirectives: None
+IndentWidth:     2
+IndentWrappedFunctionNames: false
+JavaScriptQuotes: Leave
+JavaScriptWrapImports: true
+KeepEmptyLinesAtTheStartOfBlocks: true
+MacroBlockBegin: ''
+MacroBlockEnd:   ''
+MaxEmptyLinesToKeep: 2
+NamespaceIndentation: None
+ObjCBinPackProtocolList: Auto
+ObjCBlockIndentWidth: 2
+ObjCSpaceAfterProperty: false
+ObjCSpaceBeforeProtocolList: true
+PenaltyBreakAssignment: 2
+PenaltyBreakBeforeFirstCallParameter: 9999999
+PenaltyBreakComment: 300
+PenaltyBreakFirstLessLess: 120
+PenaltyBreakString: 1000
+PenaltyBreakTemplateDeclaration: 10
+PenaltyExcessCharacter: 1000000
+PenaltyReturnTypeOnItsOwnLine: 60
+PointerAlignment: Right
+ReflowComments:  false
+SortIncludes:    false
+SortUsingDeclarations: true
+SpaceAfterCStyleCast: true
+SpaceAfterLogicalNot: true
+SpaceAfterTemplateKeyword: true
+SpaceBeforeAssignmentOperators: true
+SpaceBeforeCpp11BracedList: false
+SpaceBeforeCtorInitializerColon: true
+SpaceBeforeInheritanceColon: true
+SpaceBeforeParens: Always
+SpaceBeforeRangeBasedForLoopColon: true
+SpaceInEmptyParentheses: false
+SpacesBeforeTrailingComments: 1
+SpacesInAngles:  false
+SpacesInContainerLiterals: true
+SpacesInCStyleCastParentheses: false
+SpacesInParentheses: false
+SpacesInSquareBrackets: false
+Standard:        Cpp11
+StatementMacros:
+  - Q_UNUSED
+  - QT_REQUIRE_VERSION
+TabWidth:        2
+UseTab:          Never
+...
+
diff --git a/contrib/conf/tox.ini b/contrib/conf/tox.ini
new file mode 100644
index 0000000000000000000000000000000000000000..aee00e3b72733ce7cdd4b483e22f1dc1f0d0456e
--- /dev/null
+++ b/contrib/conf/tox.ini
@@ -0,0 +1,4 @@
+[flake8]
+max-line-length = 160
+exclude = .git *.bak
+filename = *.py*
\ No newline at end of file
diff --git a/contrib/conf/uncrustify.cfg b/contrib/conf/uncrustify.cfg
new file mode 100644
index 0000000000000000000000000000000000000000..8c9df2c4316b5d6813b825e9683795c37747ca99
--- /dev/null
+++ b/contrib/conf/uncrustify.cfg
@@ -0,0 +1,95 @@
+input_tab_size = 2
+output_tab_size = 2
+
+indent_columns = 2
+indent_with_tabs = 0
+indent_case_brace = 2
+indent_label=-16
+
+code_width=80
+#cmd_width=80
+
+# Leave most comments alone for now
+cmt_indent_multi=false
+sp_cmt_cpp_start=add
+
+sp_not=add
+
+sp_func_call_user_paren_paren=remove
+sp_inside_fparen=remove
+sp_after_cast=add
+
+ls_for_split_full=true
+ls_func_split_full=true
+ls_code_width=true
+
+# Arithmetic operations in wrapped expressions should be at the start
+# of the line.
+pos_arith=lead
+
+# Fully parenthesize boolean exprs
+mod_full_paren_if_bool=true
+
+# Braces should be on their own line
+nl_fdef_brace=add
+nl_enum_brace=add
+nl_struct_brace=add
+nl_union_brace=add
+nl_if_brace=add
+nl_brace_else=add
+nl_elseif_brace=add
+nl_while_brace=add
+nl_switch_brace=add
+
+# no newline between "else" and "if"
+nl_else_if=remove
+
+nl_func_paren=remove
+nl_assign_brace=remove
+
+# No extra newlines that cause noisy diffs
+nl_start_of_file=remove
+nl_after_func_proto = 2
+nl_after_func_body = 3
+# If there's no new line, it's not a text file!
+nl_end_of_file=add
+nl_max_blank_in_func = 3
+nl_max = 3
+
+sp_inside_paren = remove
+
+sp_arith = add
+sp_arith_additive = add
+
+# We want spaces before and after "="
+sp_before_assign = add
+sp_after_assign = add
+
+# we want "char *foo;"
+sp_after_ptr_star = remove
+sp_between_ptr_star = remove
+
+# we want "if (foo) { ... }"
+sp_before_sparen = add
+
+sp_inside_fparen = remove
+sp_inside_sparen = remove
+
+# add space before function call and decl: "foo (x)"
+sp_func_call_paren = add
+sp_func_proto_paren = add
+sp_func_proto_paren_empty = add
+sp_func_def_paren = add
+sp_func_def_paren_empty = add
+
+# We'd want it for "if ( (foo) || (bar) )", but not for "if (m())",
+# so as uncrustify doesn't give exactly what we want => ignore
+sp_paren_paren = ignore
+sp_inside_paren = remove
+sp_bool = force
+
+nl_func_type_name = force
+#nl_branch_else = add
+nl_else_brace = add
+nl_elseif_brace = add
+nl_for_brace = add
diff --git a/contrib/conf/uncrustify_precommit b/contrib/conf/uncrustify_precommit
new file mode 100755
index 0000000000000000000000000000000000000000..fd29998c3ca781d25466e82241ad9ea741ff05d5
--- /dev/null
+++ b/contrib/conf/uncrustify_precommit
@@ -0,0 +1,35 @@
+#!/bin/sh
+
+# use as .git/hooks/pre-commit
+
+exec 1>&2
+
+RET=0
+changed=$(git diff --cached --name-only)
+crustified=""
+
+for f in $changed;
+do
+ if echo $f | grep \\.[c,h]\$ > /dev/null
+ then
+    # compare result of uncrustify with changes
+    #
+    # only change any of the invocations here if
+    # they are portable across all cmp and shell
+    # implementations !
+    uncrustify -q -c uncrustify.cfg -f $f | cmp -s $f -
+    if test $? = 1 ;
+    then
+      crustified=" $crustified $f"
+      RET=1
+    fi
+  fi
+done
+
+if [ $RET = 1 ];
+then
+  echo "Run"
+  echo "uncrustify --no-backup -c uncrustify.cfg ${crustified}"
+  echo "before commiting."
+fi
+exit $RET
diff --git a/contrib/docker/Dockerfile b/contrib/docker/Dockerfile
new file mode 100644
index 0000000000000000000000000000000000000000..adcd7132c7025ed57a8206334f40a46efa0d817a
--- /dev/null
+++ b/contrib/docker/Dockerfile
@@ -0,0 +1,101 @@
+FROM ubuntu:18.04
+
+ENV DEBIAN_FRONTEND noninteractive
+
+# Install tools and dependencies
+RUN apt-get update && \
+    apt-get -y install --no-install-recommends \
+      ca-certificates \
+      libsasl2-modules \
+      git \
+      automake \
+      autopoint \
+      autoconf \
+      texinfo \
+      libtool \
+      libltdl-dev \
+      libgpg-error-dev \
+      libidn11-dev \
+      libunistring-dev \
+      libglpk-dev \
+      libbluetooth-dev \
+      libextractor-dev \
+      libmicrohttpd-dev \
+      libgnutls28-dev \
+      libgcrypt20-dev \
+      libpq-dev \
+      libsqlite3-dev \
+      wget && \
+    apt-get clean all && \
+    apt-get -y autoremove && \
+    rm -rf \
+      /var/lib/apt/lists/* \
+      /tmp/*
+
+# Install GNUrl
+ENV GNURL_VERSION=7.57.0
+
+RUN wget -O /tmp/gnurl.tar.xz https://ftpmirror.gnu.org/gnu/gnunet/gnurl-${GNURL_VERSION}.tar.xz
+RUN cd /tmp && \
+      tar xvf gnurl.tar.xz && \
+      cd gnurl-${GNURL_VERSION} && \
+      autoreconf -i && \
+      ./configure \
+        --enable-ipv6 \
+        --with-gnutls \
+        --without-libssh2 \
+        --without-libmetalink \
+        --without-winidn \
+        --without-librtmp \
+        --without-nghttp2 \
+        --without-nss \
+        --without-cyassl \
+        --without-polarssl \
+        --without-ssl \
+        --without-winssl \
+        --without-darwinssl \
+        --disable-sspi \
+        --disable-ntlm-wb \
+        --disable-ldap \
+        --disable-rtsp \
+        --disable-dict \
+        --disable-telnet \
+        --disable-tftp \
+        --disable-pop3 \
+        --disable-imap \
+        --disable-smtp \
+        --disable-gopher \
+        --disable-file \
+        --disable-ftp \
+        --disable-smb && \
+      make install && \
+    cd - && \
+    rm -rf /tmp/gnurl*
+
+# Install GNUnet
+ENV GNUNET_PREFIX /usr/local/gnunet
+ENV CFLAGS '-g -Wall -O0'
+
+COPY . /gnunet
+
+RUN cd /gnunet && \
+      ./bootstrap && \
+      ./configure \
+        --with-nssdir=/lib \
+        --prefix="$GNUNET_PREFIX" \
+        --enable-logging=verbose && \
+      make -j3 && \
+      make install && \
+      ldconfig && \
+    cd - && \
+    rm -fr /gnunet
+
+# Configure GNUnet
+COPY ./contrib/docker/gnunet.conf /etc/gnunet.conf
+COPY ./contrib/docker/docker-entrypoint.sh /usr/local/bin/docker-entrypoint
+RUN chmod 755 /usr/local/bin/docker-entrypoint
+
+ENV LOCAL_PORT_RANGE='40001 40200'
+ENV PATH "$GNUNET_PREFIX/bin:/usr/local/bin:$PATH"
+
+ENTRYPOINT ["docker-entrypoint"]
diff --git a/contrib/docker/README.md b/contrib/docker/README.md
new file mode 100644
index 0000000000000000000000000000000000000000..ce05012fcfa9a31e63abc5254a34d783564b2411
--- /dev/null
+++ b/contrib/docker/README.md
@@ -0,0 +1,138 @@
+# gnunet-docker
+A Dockerfile (and maybe later docker-compose.yml) for getting a running GNUnet docker container.
+
+> This README and parts of the Dockerfile were adapted from https://github.com/compiaffe/gnunet-docker
+
+
+## Build it
+This will take quite a while and will consume a bit of data.
+
+First you need to go to the root of this repo.
+
+```bash
+cd ..
+```
+
+Now you can build the image.
+
+```bash
+docker build -t gnunet .
+```
+
+## Start it from the newly created gnunet image
+Start a container from `gnunet` image, which can access /dev/net/tun, has access to the host network. We are going to name it `gnunet1`.
+
+Note the `--rm` that will delete the container as soon as you stop it and `-ti` gives you an interactive terminal.
+
+#### Linux Users
+```bash
+docker run \
+  --rm \
+  -ti \
+  --privileged \
+  --name gnunet1 \
+  --net=host \
+  -v /dev/net/tun:/dev/net/tun \
+  gnunet
+```
+
+#### Mac Users
+```bash
+docker run \
+  --rm \
+  -it \
+  --privileged \
+  --name gnunet1 \
+  -e LOCAL_PORT_RANGE='40001 40200' \
+  -e GNUNET_PORT=2086 \
+  -p 2086:2086 \
+  -p 2086:2086/udp \
+  -p40001-40200:40001-40200 \
+  -p40001-40200:40001-40200/udp \
+  gnunet
+```
+
+This terminal will keep on printing to screen at the moment. So go on in a new terminal please.
+
+Don't worry about warnings too much...
+
+## Check if you are connected
+Open a new terminal and connect to the container we just started:
+
+```bash
+docker exec -it gnunet1 gnunet-peerinfo -i
+```
+
+If you get a list of peers, all is good.
+
+## Multiple containers on the same host
+### Running
+#### Run Container 1
+```bash
+export GPORT=2086 LPORT='40001-40200' GNAME=gnunet1
+docker run \
+  --rm \
+  -it \
+  --privileged \
+  -e GNUNET_PORT=$GPORT \
+  -e LOCAL_PORT_RANGE="${LPORT/-/ }" \
+  -p $GPORT:$GPORT \
+  -p $GPORT:$GPORT/udp \
+  -p$LPORT:$LPORT \
+  -p$LPORT:$LPORT/udp \
+  --name $GNAME \
+  gnunet
+```
+
+#### Run Container 2
+```bash
+export GPORT=2087 LPORT='40201-40400' GNAME=gnunet2
+docker run \
+  --rm \
+  -it \
+  --privileged \
+  -e GNUNET_PORT=$GPORT \
+  -e LOCAL_PORT_RANGE="${LPORT/-/ }" \
+  -p $GPORT:$GPORT \
+  -p $GPORT:$GPORT/udp \
+  -p$LPORT:$LPORT \
+  -p$LPORT:$LPORT/udp \
+  --name $GNAME \
+  gnunet
+```
+
+### Testing cadet example
+#### Container 1
+```bash
+$ docker exec -it gnunet1 bash
+$ gnunet-peerinfo -s
+I am peer `VWPN1NZA6YMM866EJ5J2NY47XG692MQ6H6WASVECF0M18A9SCMZ0'.
+$ gnunet-cadet -o asdasd
+```
+
+#### Container 2
+```bash
+$ docker exec -it gnunet2 bash
+$ gnunet-cadet VWPN1NZA6YMM866EJ5J2NY47XG692MQ6H6WASVECF0M18A9SCMZ0 asdasd
+```
+
+### Testing file sharing example
+#### Container 1
+```bash
+$ docker exec -it gnunet1 bash
+$ echo 'test' > test.txt
+$ gnunet-publish test.txt
+Publishing `/test.txt' done.
+URI is `gnunet://fs/chk/1RZ7A8TAQHMF8DWAGTSZ9CSA365T60C4BC6DDS810VM78D2Q0366CRX8DGFA29EWBT9BW5Y9HYD0Z1EAKNFNJQDJ04QQSGTQ352W28R.7MYB03GYXT17Z93ZRZRVV64AH9KPWFSVDEZGVE84YHD63XZFJ36B86M48KHTZVF87SZ05HBVB44PCXE8CVWAH72VN1SKYPRK1QN2C98.5'.
+```
+
+#### Container 2
+```bash
+$ docker exec -it gnunet2 bash
+$ gnunet-download -o out.file "gnunet://fs/chk/1RZ7A8TAQHMF8DWAGTSZ9CSA365T60C4BC6DDS810VM78D2Q0366CRX8DGFA29EWBT9BW5Y9HYD0Z1EAKNFNJQDJ04QQSGTQ352W28R.7MYB03GYXT17Z93ZRZRVV64AH9KPWFSVDEZGVE84YHD63XZFJ36B86M48KHTZVF87SZ05HBVB44PCXE8CVWAH72VN1SKYPRK1QN2C98.5"
+100% [============================================================]
+Downloading `out.file' done (0 b/s).
+$ cat out.file
+test
+```
+
diff --git a/contrib/docker/docker-entrypoint.sh b/contrib/docker/docker-entrypoint.sh
new file mode 100644
index 0000000000000000000000000000000000000000..7f98ef68bb512c70ffdc5c1207128983ca3b997e
--- /dev/null
+++ b/contrib/docker/docker-entrypoint.sh
@@ -0,0 +1,15 @@
+#!/bin/bash -e
+
+echo "${LOCAL_PORT_RANGE:-49152 65535}" > /proc/sys/net/ipv4/ip_local_port_range
+sed -i 's/$GNUNET_PORT/'${GNUNET_PORT:-2086}'/g' /etc/gnunet.conf
+
+if [[ $# -eq 0 ]]; then
+  exec gnunet-arm \
+    --config=/etc/gnunet.conf \
+    --start \
+    --monitor
+elif [[ -z $1 ]] || [[ ${1:0:1} == '-' ]]; then
+  exec gnunet-arm "$@"
+else
+  exec "$@"
+fi
diff --git a/contrib/docker/gnunet.conf b/contrib/docker/gnunet.conf
new file mode 100644
index 0000000000000000000000000000000000000000..c8299ef46eb6ee77343ef2c808f44dbadb191e25
--- /dev/null
+++ b/contrib/docker/gnunet.conf
@@ -0,0 +1,21 @@
+[arm]
+SYSTEM_ONLY = NO
+USER_ONLY = NO
+
+[fs]
+FORCESTART = NO
+
+[nat]
+ENABLE_UPNP = NO
+BEHIND_NAT = YES
+
+[transport-tcp]
+PORT = $GNUNET_PORT
+ADVERTISED_PORT = $GNUNET_PORT
+
+[transport-udp]
+PORT = $GNUNET_PORT
+BROADCAST = YES
+
+[cadet]
+TESTING_IGNORE_KEYS = ACCEPT_FROM;
diff --git a/contrib/gns/bootstrap.min.css b/contrib/gns/bootstrap.min.css
new file mode 100644
index 0000000000000000000000000000000000000000..c547283bbda8533f4a19931b112c282fda789891
--- /dev/null
+++ b/contrib/gns/bootstrap.min.css
@@ -0,0 +1,7 @@
+/*!
+ * Bootstrap v3.0.3 (http://getbootstrap.com)
+ * Copyright 2013 Twitter, Inc.
+ * Licensed under http://www.apache.org/licenses/LICENSE-2.0
+ */
+
+/*! normalize.css v2.1.3 | MIT License | git.io/normalize */article,aside,details,figcaption,figure,footer,header,hgroup,main,nav,section,summary{display:block}audio,canvas,video{display:inline-block}audio:not([controls]){display:none;height:0}[hidden],template{display:none}html{font-family:sans-serif;-webkit-text-size-adjust:100%;-ms-text-size-adjust:100%}body{margin:0}a{background:transparent}a:focus{outline:thin dotted}a:active,a:hover{outline:0}h1{margin:.67em 0;font-size:2em}abbr[title]{border-bottom:1px dotted}b,strong{font-weight:bold}dfn{font-style:italic}hr{height:0;-moz-box-sizing:content-box;box-sizing:content-box}mark{color:#000;background:#ff0}code,kbd,pre,samp{font-family:monospace,serif;font-size:1em}pre{white-space:pre-wrap}q{quotes:"\201C" "\201D" "\2018" "\2019"}small{font-size:80%}sub,sup{position:relative;font-size:75%;line-height:0;vertical-align:baseline}sup{top:-0.5em}sub{bottom:-0.25em}img{border:0}svg:not(:root){overflow:hidden}figure{margin:0}fieldset{padding:.35em .625em .75em;margin:0 2px;border:1px solid #c0c0c0}legend{padding:0;border:0}button,input,select,textarea{margin:0;font-family:inherit;font-size:100%}button,input{line-height:normal}button,select{text-transform:none}button,html input[type="button"],input[type="reset"],input[type="submit"]{cursor:pointer;-webkit-appearance:button}button[disabled],html input[disabled]{cursor:default}input[type="checkbox"],input[type="radio"]{padding:0;box-sizing:border-box}input[type="search"]{-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box;-webkit-appearance:textfield}input[type="search"]::-webkit-search-cancel-button,input[type="search"]::-webkit-search-decoration{-webkit-appearance:none}button::-moz-focus-inner,input::-moz-focus-inner{padding:0;border:0}textarea{overflow:auto;vertical-align:top}table{border-collapse:collapse;border-spacing:0}@media print{*{color:#000!important;text-shadow:none!important;background:transparent!important;box-shadow:none!important}a,a:visited{text-decoration:underline}a[href]:after{content:" (" attr(href) ")"}abbr[title]:after{content:" (" attr(title) ")"}a[href^="javascript:"]:after,a[href^="#"]:after{content:""}pre,blockquote{border:1px solid #999;page-break-inside:avoid}thead{display:table-header-group}tr,img{page-break-inside:avoid}img{max-width:100%!important}@page{margin:2cm .5cm}p,h2,h3{orphans:3;widows:3}h2,h3{page-break-after:avoid}select{background:#fff!important}.navbar{display:none}.table td,.table th{background-color:#fff!important}.btn>.caret,.dropup>.btn>.caret{border-top-color:#000!important}.label{border:1px solid #000}.table{border-collapse:collapse!important}.table-bordered th,.table-bordered td{border:1px solid #ddd!important}}*,*:before,*:after{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}html{font-size:62.5%;-webkit-tap-highlight-color:rgba(0,0,0,0)}body{font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;font-size:14px;line-height:1.428571429;color:#333;background-color:#fff}input,button,select,textarea{font-family:inherit;font-size:inherit;line-height:inherit}a{color:#428bca;text-decoration:none}a:hover,a:focus{color:#2a6496;text-decoration:underline}a:focus{outline:thin dotted;outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}img{vertical-align:middle}.img-responsive{display:block;height:auto;max-width:100%}.img-rounded{border-radius:6px}.img-thumbnail{display:inline-block;height:auto;max-width:100%;padding:4px;line-height:1.428571429;background-color:#fff;border:1px solid #ddd;border-radius:4px;-webkit-transition:all .2s ease-in-out;transition:all .2s ease-in-out}.img-circle{border-radius:50%}hr{margin-top:20px;margin-bottom:20px;border:0;border-top:1px solid #eee}.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);border:0}h1,h2,h3,h4,h5,h6,.h1,.h2,.h3,.h4,.h5,.h6{font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;font-weight:500;line-height:1.1;color:inherit}h1 small,h2 small,h3 small,h4 small,h5 small,h6 small,.h1 small,.h2 small,.h3 small,.h4 small,.h5 small,.h6 small,h1 .small,h2 .small,h3 .small,h4 .small,h5 .small,h6 .small,.h1 .small,.h2 .small,.h3 .small,.h4 .small,.h5 .small,.h6 .small{font-weight:normal;line-height:1;color:#999}h1,h2,h3{margin-top:20px;margin-bottom:10px}h1 small,h2 small,h3 small,h1 .small,h2 .small,h3 .small{font-size:65%}h4,h5,h6{margin-top:10px;margin-bottom:10px}h4 small,h5 small,h6 small,h4 .small,h5 .small,h6 .small{font-size:75%}h1,.h1{font-size:36px}h2,.h2{font-size:30px}h3,.h3{font-size:24px}h4,.h4{font-size:18px}h5,.h5{font-size:14px}h6,.h6{font-size:12px}p{margin:0 0 10px}.lead{margin-bottom:20px;font-size:16px;font-weight:200;line-height:1.4}@media(min-width:768px){.lead{font-size:21px}}small,.small{font-size:85%}cite{font-style:normal}.text-muted{color:#999}.text-primary{color:#428bca}.text-primary:hover{color:#3071a9}.text-warning{color:#8a6d3b}.text-warning:hover{color:#66512c}.text-danger{color:#a94442}.text-danger:hover{color:#843534}.text-success{color:#3c763d}.text-success:hover{color:#2b542c}.text-info{color:#31708f}.text-info:hover{color:#245269}.text-left{text-align:left}.text-right{text-align:right}.text-center{text-align:center}.page-header{padding-bottom:9px;margin:40px 0 20px;border-bottom:1px solid #eee}ul,ol{margin-top:0;margin-bottom:10px}ul ul,ol ul,ul ol,ol ol{margin-bottom:0}.list-unstyled{padding-left:0;list-style:none}.list-inline{padding-left:0;list-style:none}.list-inline>li{display:inline-block;padding-right:5px;padding-left:5px}.list-inline>li:first-child{padding-left:0}dl{margin-top:0;margin-bottom:20px}dt,dd{line-height:1.428571429}dt{font-weight:bold}dd{margin-left:0}@media(min-width:768px){.dl-horizontal dt{float:left;width:160px;overflow:hidden;clear:left;text-align:right;text-overflow:ellipsis;white-space:nowrap}.dl-horizontal dd{margin-left:180px}.dl-horizontal dd:before,.dl-horizontal dd:after{display:table;content:" "}.dl-horizontal dd:after{clear:both}.dl-horizontal dd:before,.dl-horizontal dd:after{display:table;content:" "}.dl-horizontal dd:after{clear:both}}abbr[title],abbr[data-original-title]{cursor:help;border-bottom:1px dotted #999}.initialism{font-size:90%;text-transform:uppercase}blockquote{padding:10px 20px;margin:0 0 20px;border-left:5px solid #eee}blockquote p{font-size:17.5px;font-weight:300;line-height:1.25}blockquote p:last-child{margin-bottom:0}blockquote small,blockquote .small{display:block;line-height:1.428571429;color:#999}blockquote small:before,blockquote .small:before{content:'\2014 \00A0'}blockquote.pull-right{padding-right:15px;padding-left:0;border-right:5px solid #eee;border-left:0}blockquote.pull-right p,blockquote.pull-right small,blockquote.pull-right .small{text-align:right}blockquote.pull-right small:before,blockquote.pull-right .small:before{content:''}blockquote.pull-right small:after,blockquote.pull-right .small:after{content:'\00A0 \2014'}blockquote:before,blockquote:after{content:""}address{margin-bottom:20px;font-style:normal;line-height:1.428571429}code,kbd,pre,samp{font-family:Menlo,Monaco,Consolas,"Courier New",monospace}code{padding:2px 4px;font-size:90%;color:#c7254e;white-space:nowrap;background-color:#f9f2f4;border-radius:4px}pre{display:block;padding:9.5px;margin:0 0 10px;font-size:13px;line-height:1.428571429;color:#333;word-break:break-all;word-wrap:break-word;background-color:#f5f5f5;border:1px solid #ccc;border-radius:4px}pre code{padding:0;font-size:inherit;color:inherit;white-space:pre-wrap;background-color:transparent;border-radius:0}.pre-scrollable{max-height:340px;overflow-y:scroll}.container{padding-right:15px;padding-left:15px;margin-right:auto;margin-left:auto}.container:before,.container:after{display:table;content:" "}.container:after{clear:both}.container:before,.container:after{display:table;content:" "}.container:after{clear:both}@media(min-width:768px){.container{width:750px}}@media(min-width:992px){.container{width:970px}}@media(min-width:1200px){.container{width:1170px}}.row{margin-right:-15px;margin-left:-15px}.row:before,.row:after{display:table;content:" "}.row:after{clear:both}.row:before,.row:after{display:table;content:" "}.row:after{clear:both}.col-xs-1,.col-sm-1,.col-md-1,.col-lg-1,.col-xs-2,.col-sm-2,.col-md-2,.col-lg-2,.col-xs-3,.col-sm-3,.col-md-3,.col-lg-3,.col-xs-4,.col-sm-4,.col-md-4,.col-lg-4,.col-xs-5,.col-sm-5,.col-md-5,.col-lg-5,.col-xs-6,.col-sm-6,.col-md-6,.col-lg-6,.col-xs-7,.col-sm-7,.col-md-7,.col-lg-7,.col-xs-8,.col-sm-8,.col-md-8,.col-lg-8,.col-xs-9,.col-sm-9,.col-md-9,.col-lg-9,.col-xs-10,.col-sm-10,.col-md-10,.col-lg-10,.col-xs-11,.col-sm-11,.col-md-11,.col-lg-11,.col-xs-12,.col-sm-12,.col-md-12,.col-lg-12{position:relative;min-height:1px;padding-right:15px;padding-left:15px}.col-xs-1,.col-xs-2,.col-xs-3,.col-xs-4,.col-xs-5,.col-xs-6,.col-xs-7,.col-xs-8,.col-xs-9,.col-xs-10,.col-xs-11,.col-xs-12{float:left}.col-xs-12{width:100%}.col-xs-11{width:91.66666666666666%}.col-xs-10{width:83.33333333333334%}.col-xs-9{width:75%}.col-xs-8{width:66.66666666666666%}.col-xs-7{width:58.333333333333336%}.col-xs-6{width:50%}.col-xs-5{width:41.66666666666667%}.col-xs-4{width:33.33333333333333%}.col-xs-3{width:25%}.col-xs-2{width:16.666666666666664%}.col-xs-1{width:8.333333333333332%}.col-xs-pull-12{right:100%}.col-xs-pull-11{right:91.66666666666666%}.col-xs-pull-10{right:83.33333333333334%}.col-xs-pull-9{right:75%}.col-xs-pull-8{right:66.66666666666666%}.col-xs-pull-7{right:58.333333333333336%}.col-xs-pull-6{right:50%}.col-xs-pull-5{right:41.66666666666667%}.col-xs-pull-4{right:33.33333333333333%}.col-xs-pull-3{right:25%}.col-xs-pull-2{right:16.666666666666664%}.col-xs-pull-1{right:8.333333333333332%}.col-xs-pull-0{right:0}.col-xs-push-12{left:100%}.col-xs-push-11{left:91.66666666666666%}.col-xs-push-10{left:83.33333333333334%}.col-xs-push-9{left:75%}.col-xs-push-8{left:66.66666666666666%}.col-xs-push-7{left:58.333333333333336%}.col-xs-push-6{left:50%}.col-xs-push-5{left:41.66666666666667%}.col-xs-push-4{left:33.33333333333333%}.col-xs-push-3{left:25%}.col-xs-push-2{left:16.666666666666664%}.col-xs-push-1{left:8.333333333333332%}.col-xs-push-0{left:0}.col-xs-offset-12{margin-left:100%}.col-xs-offset-11{margin-left:91.66666666666666%}.col-xs-offset-10{margin-left:83.33333333333334%}.col-xs-offset-9{margin-left:75%}.col-xs-offset-8{margin-left:66.66666666666666%}.col-xs-offset-7{margin-left:58.333333333333336%}.col-xs-offset-6{margin-left:50%}.col-xs-offset-5{margin-left:41.66666666666667%}.col-xs-offset-4{margin-left:33.33333333333333%}.col-xs-offset-3{margin-left:25%}.col-xs-offset-2{margin-left:16.666666666666664%}.col-xs-offset-1{margin-left:8.333333333333332%}.col-xs-offset-0{margin-left:0}@media(min-width:768px){.col-sm-1,.col-sm-2,.col-sm-3,.col-sm-4,.col-sm-5,.col-sm-6,.col-sm-7,.col-sm-8,.col-sm-9,.col-sm-10,.col-sm-11,.col-sm-12{float:left}.col-sm-12{width:100%}.col-sm-11{width:91.66666666666666%}.col-sm-10{width:83.33333333333334%}.col-sm-9{width:75%}.col-sm-8{width:66.66666666666666%}.col-sm-7{width:58.333333333333336%}.col-sm-6{width:50%}.col-sm-5{width:41.66666666666667%}.col-sm-4{width:33.33333333333333%}.col-sm-3{width:25%}.col-sm-2{width:16.666666666666664%}.col-sm-1{width:8.333333333333332%}.col-sm-pull-12{right:100%}.col-sm-pull-11{right:91.66666666666666%}.col-sm-pull-10{right:83.33333333333334%}.col-sm-pull-9{right:75%}.col-sm-pull-8{right:66.66666666666666%}.col-sm-pull-7{right:58.333333333333336%}.col-sm-pull-6{right:50%}.col-sm-pull-5{right:41.66666666666667%}.col-sm-pull-4{right:33.33333333333333%}.col-sm-pull-3{right:25%}.col-sm-pull-2{right:16.666666666666664%}.col-sm-pull-1{right:8.333333333333332%}.col-sm-pull-0{right:0}.col-sm-push-12{left:100%}.col-sm-push-11{left:91.66666666666666%}.col-sm-push-10{left:83.33333333333334%}.col-sm-push-9{left:75%}.col-sm-push-8{left:66.66666666666666%}.col-sm-push-7{left:58.333333333333336%}.col-sm-push-6{left:50%}.col-sm-push-5{left:41.66666666666667%}.col-sm-push-4{left:33.33333333333333%}.col-sm-push-3{left:25%}.col-sm-push-2{left:16.666666666666664%}.col-sm-push-1{left:8.333333333333332%}.col-sm-push-0{left:0}.col-sm-offset-12{margin-left:100%}.col-sm-offset-11{margin-left:91.66666666666666%}.col-sm-offset-10{margin-left:83.33333333333334%}.col-sm-offset-9{margin-left:75%}.col-sm-offset-8{margin-left:66.66666666666666%}.col-sm-offset-7{margin-left:58.333333333333336%}.col-sm-offset-6{margin-left:50%}.col-sm-offset-5{margin-left:41.66666666666667%}.col-sm-offset-4{margin-left:33.33333333333333%}.col-sm-offset-3{margin-left:25%}.col-sm-offset-2{margin-left:16.666666666666664%}.col-sm-offset-1{margin-left:8.333333333333332%}.col-sm-offset-0{margin-left:0}}@media(min-width:992px){.col-md-1,.col-md-2,.col-md-3,.col-md-4,.col-md-5,.col-md-6,.col-md-7,.col-md-8,.col-md-9,.col-md-10,.col-md-11,.col-md-12{float:left}.col-md-12{width:100%}.col-md-11{width:91.66666666666666%}.col-md-10{width:83.33333333333334%}.col-md-9{width:75%}.col-md-8{width:66.66666666666666%}.col-md-7{width:58.333333333333336%}.col-md-6{width:50%}.col-md-5{width:41.66666666666667%}.col-md-4{width:33.33333333333333%}.col-md-3{width:25%}.col-md-2{width:16.666666666666664%}.col-md-1{width:8.333333333333332%}.col-md-pull-12{right:100%}.col-md-pull-11{right:91.66666666666666%}.col-md-pull-10{right:83.33333333333334%}.col-md-pull-9{right:75%}.col-md-pull-8{right:66.66666666666666%}.col-md-pull-7{right:58.333333333333336%}.col-md-pull-6{right:50%}.col-md-pull-5{right:41.66666666666667%}.col-md-pull-4{right:33.33333333333333%}.col-md-pull-3{right:25%}.col-md-pull-2{right:16.666666666666664%}.col-md-pull-1{right:8.333333333333332%}.col-md-pull-0{right:0}.col-md-push-12{left:100%}.col-md-push-11{left:91.66666666666666%}.col-md-push-10{left:83.33333333333334%}.col-md-push-9{left:75%}.col-md-push-8{left:66.66666666666666%}.col-md-push-7{left:58.333333333333336%}.col-md-push-6{left:50%}.col-md-push-5{left:41.66666666666667%}.col-md-push-4{left:33.33333333333333%}.col-md-push-3{left:25%}.col-md-push-2{left:16.666666666666664%}.col-md-push-1{left:8.333333333333332%}.col-md-push-0{left:0}.col-md-offset-12{margin-left:100%}.col-md-offset-11{margin-left:91.66666666666666%}.col-md-offset-10{margin-left:83.33333333333334%}.col-md-offset-9{margin-left:75%}.col-md-offset-8{margin-left:66.66666666666666%}.col-md-offset-7{margin-left:58.333333333333336%}.col-md-offset-6{margin-left:50%}.col-md-offset-5{margin-left:41.66666666666667%}.col-md-offset-4{margin-left:33.33333333333333%}.col-md-offset-3{margin-left:25%}.col-md-offset-2{margin-left:16.666666666666664%}.col-md-offset-1{margin-left:8.333333333333332%}.col-md-offset-0{margin-left:0}}@media(min-width:1200px){.col-lg-1,.col-lg-2,.col-lg-3,.col-lg-4,.col-lg-5,.col-lg-6,.col-lg-7,.col-lg-8,.col-lg-9,.col-lg-10,.col-lg-11,.col-lg-12{float:left}.col-lg-12{width:100%}.col-lg-11{width:91.66666666666666%}.col-lg-10{width:83.33333333333334%}.col-lg-9{width:75%}.col-lg-8{width:66.66666666666666%}.col-lg-7{width:58.333333333333336%}.col-lg-6{width:50%}.col-lg-5{width:41.66666666666667%}.col-lg-4{width:33.33333333333333%}.col-lg-3{width:25%}.col-lg-2{width:16.666666666666664%}.col-lg-1{width:8.333333333333332%}.col-lg-pull-12{right:100%}.col-lg-pull-11{right:91.66666666666666%}.col-lg-pull-10{right:83.33333333333334%}.col-lg-pull-9{right:75%}.col-lg-pull-8{right:66.66666666666666%}.col-lg-pull-7{right:58.333333333333336%}.col-lg-pull-6{right:50%}.col-lg-pull-5{right:41.66666666666667%}.col-lg-pull-4{right:33.33333333333333%}.col-lg-pull-3{right:25%}.col-lg-pull-2{right:16.666666666666664%}.col-lg-pull-1{right:8.333333333333332%}.col-lg-pull-0{right:0}.col-lg-push-12{left:100%}.col-lg-push-11{left:91.66666666666666%}.col-lg-push-10{left:83.33333333333334%}.col-lg-push-9{left:75%}.col-lg-push-8{left:66.66666666666666%}.col-lg-push-7{left:58.333333333333336%}.col-lg-push-6{left:50%}.col-lg-push-5{left:41.66666666666667%}.col-lg-push-4{left:33.33333333333333%}.col-lg-push-3{left:25%}.col-lg-push-2{left:16.666666666666664%}.col-lg-push-1{left:8.333333333333332%}.col-lg-push-0{left:0}.col-lg-offset-12{margin-left:100%}.col-lg-offset-11{margin-left:91.66666666666666%}.col-lg-offset-10{margin-left:83.33333333333334%}.col-lg-offset-9{margin-left:75%}.col-lg-offset-8{margin-left:66.66666666666666%}.col-lg-offset-7{margin-left:58.333333333333336%}.col-lg-offset-6{margin-left:50%}.col-lg-offset-5{margin-left:41.66666666666667%}.col-lg-offset-4{margin-left:33.33333333333333%}.col-lg-offset-3{margin-left:25%}.col-lg-offset-2{margin-left:16.666666666666664%}.col-lg-offset-1{margin-left:8.333333333333332%}.col-lg-offset-0{margin-left:0}}table{max-width:100%;background-color:transparent}th{text-align:left}.table{width:100%;margin-bottom:20px}.table>thead>tr>th,.table>tbody>tr>th,.table>tfoot>tr>th,.table>thead>tr>td,.table>tbody>tr>td,.table>tfoot>tr>td{padding:8px;line-height:1.428571429;vertical-align:top;border-top:1px solid #ddd}.table>thead>tr>th{vertical-align:bottom;border-bottom:2px solid #ddd}.table>caption+thead>tr:first-child>th,.table>colgroup+thead>tr:first-child>th,.table>thead:first-child>tr:first-child>th,.table>caption+thead>tr:first-child>td,.table>colgroup+thead>tr:first-child>td,.table>thead:first-child>tr:first-child>td{border-top:0}.table>tbody+tbody{border-top:2px solid #ddd}.table .table{background-color:#fff}.table-condensed>thead>tr>th,.table-condensed>tbody>tr>th,.table-condensed>tfoot>tr>th,.table-condensed>thead>tr>td,.table-condensed>tbody>tr>td,.table-condensed>tfoot>tr>td{padding:5px}.table-bordered{border:1px solid #ddd}.table-bordered>thead>tr>th,.table-bordered>tbody>tr>th,.table-bordered>tfoot>tr>th,.table-bordered>thead>tr>td,.table-bordered>tbody>tr>td,.table-bordered>tfoot>tr>td{border:1px solid #ddd}.table-bordered>thead>tr>th,.table-bordered>thead>tr>td{border-bottom-width:2px}.table-striped>tbody>tr:nth-child(odd)>td,.table-striped>tbody>tr:nth-child(odd)>th{background-color:#f9f9f9}.table-hover>tbody>tr:hover>td,.table-hover>tbody>tr:hover>th{background-color:#f5f5f5}table col[class*="col-"]{position:static;display:table-column;float:none}table td[class*="col-"],table th[class*="col-"]{display:table-cell;float:none}.table>thead>tr>.active,.table>tbody>tr>.active,.table>tfoot>tr>.active,.table>thead>.active>td,.table>tbody>.active>td,.table>tfoot>.active>td,.table>thead>.active>th,.table>tbody>.active>th,.table>tfoot>.active>th{background-color:#f5f5f5}.table-hover>tbody>tr>.active:hover,.table-hover>tbody>.active:hover>td,.table-hover>tbody>.active:hover>th{background-color:#e8e8e8}.table>thead>tr>.success,.table>tbody>tr>.success,.table>tfoot>tr>.success,.table>thead>.success>td,.table>tbody>.success>td,.table>tfoot>.success>td,.table>thead>.success>th,.table>tbody>.success>th,.table>tfoot>.success>th{background-color:#dff0d8}.table-hover>tbody>tr>.success:hover,.table-hover>tbody>.success:hover>td,.table-hover>tbody>.success:hover>th{background-color:#d0e9c6}.table>thead>tr>.danger,.table>tbody>tr>.danger,.table>tfoot>tr>.danger,.table>thead>.danger>td,.table>tbody>.danger>td,.table>tfoot>.danger>td,.table>thead>.danger>th,.table>tbody>.danger>th,.table>tfoot>.danger>th{background-color:#f2dede}.table-hover>tbody>tr>.danger:hover,.table-hover>tbody>.danger:hover>td,.table-hover>tbody>.danger:hover>th{background-color:#ebcccc}.table>thead>tr>.warning,.table>tbody>tr>.warning,.table>tfoot>tr>.warning,.table>thead>.warning>td,.table>tbody>.warning>td,.table>tfoot>.warning>td,.table>thead>.warning>th,.table>tbody>.warning>th,.table>tfoot>.warning>th{background-color:#fcf8e3}.table-hover>tbody>tr>.warning:hover,.table-hover>tbody>.warning:hover>td,.table-hover>tbody>.warning:hover>th{background-color:#faf2cc}@media(max-width:767px){.table-responsive{width:100%;margin-bottom:15px;overflow-x:scroll;overflow-y:hidden;border:1px solid #ddd;-ms-overflow-style:-ms-autohiding-scrollbar;-webkit-overflow-scrolling:touch}.table-responsive>.table{margin-bottom:0}.table-responsive>.table>thead>tr>th,.table-responsive>.table>tbody>tr>th,.table-responsive>.table>tfoot>tr>th,.table-responsive>.table>thead>tr>td,.table-responsive>.table>tbody>tr>td,.table-responsive>.table>tfoot>tr>td{white-space:nowrap}.table-responsive>.table-bordered{border:0}.table-responsive>.table-bordered>thead>tr>th:first-child,.table-responsive>.table-bordered>tbody>tr>th:first-child,.table-responsive>.table-bordered>tfoot>tr>th:first-child,.table-responsive>.table-bordered>thead>tr>td:first-child,.table-responsive>.table-bordered>tbody>tr>td:first-child,.table-responsive>.table-bordered>tfoot>tr>td:first-child{border-left:0}.table-responsive>.table-bordered>thead>tr>th:last-child,.table-responsive>.table-bordered>tbody>tr>th:last-child,.table-responsive>.table-bordered>tfoot>tr>th:last-child,.table-responsive>.table-bordered>thead>tr>td:last-child,.table-responsive>.table-bordered>tbody>tr>td:last-child,.table-responsive>.table-bordered>tfoot>tr>td:last-child{border-right:0}.table-responsive>.table-bordered>tbody>tr:last-child>th,.table-responsive>.table-bordered>tfoot>tr:last-child>th,.table-responsive>.table-bordered>tbody>tr:last-child>td,.table-responsive>.table-bordered>tfoot>tr:last-child>td{border-bottom:0}}fieldset{padding:0;margin:0;border:0}legend{display:block;width:100%;padding:0;margin-bottom:20px;font-size:21px;line-height:inherit;color:#333;border:0;border-bottom:1px solid #e5e5e5}label{display:inline-block;margin-bottom:5px;font-weight:bold}input[type="search"]{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}input[type="radio"],input[type="checkbox"]{margin:4px 0 0;margin-top:1px \9;line-height:normal}input[type="file"]{display:block}select[multiple],select[size]{height:auto}select optgroup{font-family:inherit;font-size:inherit;font-style:inherit}input[type="file"]:focus,input[type="radio"]:focus,input[type="checkbox"]:focus{outline:thin dotted;outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}input[type="number"]::-webkit-outer-spin-button,input[type="number"]::-webkit-inner-spin-button{height:auto}output{display:block;padding-top:7px;font-size:14px;line-height:1.428571429;color:#555;vertical-align:middle}.form-control{display:block;width:100%;height:34px;padding:6px 12px;font-size:14px;line-height:1.428571429;color:#555;vertical-align:middle;background-color:#fff;background-image:none;border:1px solid #ccc;border-radius:4px;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);-webkit-transition:border-color ease-in-out .15s,box-shadow ease-in-out .15s;transition:border-color ease-in-out .15s,box-shadow ease-in-out .15s}.form-control:focus{border-color:#66afe9;outline:0;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 8px rgba(102,175,233,0.6);box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 8px rgba(102,175,233,0.6)}.form-control:-moz-placeholder{color:#999}.form-control::-moz-placeholder{color:#999;opacity:1}.form-control:-ms-input-placeholder{color:#999}.form-control::-webkit-input-placeholder{color:#999}.form-control[disabled],.form-control[readonly],fieldset[disabled] .form-control{cursor:not-allowed;background-color:#eee}textarea.form-control{height:auto}.form-group{margin-bottom:15px}.radio,.checkbox{display:block;min-height:20px;padding-left:20px;margin-top:10px;margin-bottom:10px;vertical-align:middle}.radio label,.checkbox label{display:inline;margin-bottom:0;font-weight:normal;cursor:pointer}.radio input[type="radio"],.radio-inline input[type="radio"],.checkbox input[type="checkbox"],.checkbox-inline input[type="checkbox"]{float:left;margin-left:-20px}.radio+.radio,.checkbox+.checkbox{margin-top:-5px}.radio-inline,.checkbox-inline{display:inline-block;padding-left:20px;margin-bottom:0;font-weight:normal;vertical-align:middle;cursor:pointer}.radio-inline+.radio-inline,.checkbox-inline+.checkbox-inline{margin-top:0;margin-left:10px}input[type="radio"][disabled],input[type="checkbox"][disabled],.radio[disabled],.radio-inline[disabled],.checkbox[disabled],.checkbox-inline[disabled],fieldset[disabled] input[type="radio"],fieldset[disabled] input[type="checkbox"],fieldset[disabled] .radio,fieldset[disabled] .radio-inline,fieldset[disabled] .checkbox,fieldset[disabled] .checkbox-inline{cursor:not-allowed}.input-sm{height:30px;padding:5px 10px;font-size:12px;line-height:1.5;border-radius:3px}select.input-sm{height:30px;line-height:30px}textarea.input-sm{height:auto}.input-lg{height:46px;padding:10px 16px;font-size:18px;line-height:1.33;border-radius:6px}select.input-lg{height:46px;line-height:46px}textarea.input-lg{height:auto}.has-warning .help-block,.has-warning .control-label,.has-warning .radio,.has-warning .checkbox,.has-warning .radio-inline,.has-warning .checkbox-inline{color:#8a6d3b}.has-warning .form-control{border-color:#8a6d3b;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);box-shadow:inset 0 1px 1px rgba(0,0,0,0.075)}.has-warning .form-control:focus{border-color:#66512c;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #c0a16b;box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #c0a16b}.has-warning .input-group-addon{color:#8a6d3b;background-color:#fcf8e3;border-color:#8a6d3b}.has-error .help-block,.has-error .control-label,.has-error .radio,.has-error .checkbox,.has-error .radio-inline,.has-error .checkbox-inline{color:#a94442}.has-error .form-control{border-color:#a94442;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);box-shadow:inset 0 1px 1px rgba(0,0,0,0.075)}.has-error .form-control:focus{border-color:#843534;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #ce8483;box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #ce8483}.has-error .input-group-addon{color:#a94442;background-color:#f2dede;border-color:#a94442}.has-success .help-block,.has-success .control-label,.has-success .radio,.has-success .checkbox,.has-success .radio-inline,.has-success .checkbox-inline{color:#3c763d}.has-success .form-control{border-color:#3c763d;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);box-shadow:inset 0 1px 1px rgba(0,0,0,0.075)}.has-success .form-control:focus{border-color:#2b542c;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #67b168;box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #67b168}.has-success .input-group-addon{color:#3c763d;background-color:#dff0d8;border-color:#3c763d}.form-control-static{margin-bottom:0}.help-block{display:block;margin-top:5px;margin-bottom:10px;color:#737373}@media(min-width:768px){.form-inline .form-group{display:inline-block;margin-bottom:0;vertical-align:middle}.form-inline .form-control{display:inline-block}.form-inline select.form-control{width:auto}.form-inline .radio,.form-inline .checkbox{display:inline-block;padding-left:0;margin-top:0;margin-bottom:0}.form-inline .radio input[type="radio"],.form-inline .checkbox input[type="checkbox"]{float:none;margin-left:0}}.form-horizontal .control-label,.form-horizontal .radio,.form-horizontal .checkbox,.form-horizontal .radio-inline,.form-horizontal .checkbox-inline{padding-top:7px;margin-top:0;margin-bottom:0}.form-horizontal .radio,.form-horizontal .checkbox{min-height:27px}.form-horizontal .form-group{margin-right:-15px;margin-left:-15px}.form-horizontal .form-group:before,.form-horizontal .form-group:after{display:table;content:" "}.form-horizontal .form-group:after{clear:both}.form-horizontal .form-group:before,.form-horizontal .form-group:after{display:table;content:" "}.form-horizontal .form-group:after{clear:both}.form-horizontal .form-control-static{padding-top:7px}@media(min-width:768px){.form-horizontal .control-label{text-align:right}}.btn{display:inline-block;padding:6px 12px;margin-bottom:0;font-size:14px;font-weight:normal;line-height:1.428571429;text-align:center;white-space:nowrap;vertical-align:middle;cursor:pointer;background-image:none;border:1px solid transparent;border-radius:4px;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;-o-user-select:none;user-select:none}.btn:focus{outline:thin dotted;outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}.btn:hover,.btn:focus{color:#333;text-decoration:none}.btn:active,.btn.active{background-image:none;outline:0;-webkit-box-shadow:inset 0 3px 5px rgba(0,0,0,0.125);box-shadow:inset 0 3px 5px rgba(0,0,0,0.125)}.btn.disabled,.btn[disabled],fieldset[disabled] .btn{pointer-events:none;cursor:not-allowed;opacity:.65;filter:alpha(opacity=65);-webkit-box-shadow:none;box-shadow:none}.btn-default{color:#333;background-color:#fff;border-color:#ccc}.btn-default:hover,.btn-default:focus,.btn-default:active,.btn-default.active,.open .dropdown-toggle.btn-default{color:#333;background-color:#ebebeb;border-color:#adadad}.btn-default:active,.btn-default.active,.open .dropdown-toggle.btn-default{background-image:none}.btn-default.disabled,.btn-default[disabled],fieldset[disabled] .btn-default,.btn-default.disabled:hover,.btn-default[disabled]:hover,fieldset[disabled] .btn-default:hover,.btn-default.disabled:focus,.btn-default[disabled]:focus,fieldset[disabled] .btn-default:focus,.btn-default.disabled:active,.btn-default[disabled]:active,fieldset[disabled] .btn-default:active,.btn-default.disabled.active,.btn-default[disabled].active,fieldset[disabled] .btn-default.active{background-color:#fff;border-color:#ccc}.btn-default .badge{color:#fff;background-color:#fff}.btn-primary{color:#fff;background-color:#428bca;border-color:#357ebd}.btn-primary:hover,.btn-primary:focus,.btn-primary:active,.btn-primary.active,.open .dropdown-toggle.btn-primary{color:#fff;background-color:#3276b1;border-color:#285e8e}.btn-primary:active,.btn-primary.active,.open .dropdown-toggle.btn-primary{background-image:none}.btn-primary.disabled,.btn-primary[disabled],fieldset[disabled] .btn-primary,.btn-primary.disabled:hover,.btn-primary[disabled]:hover,fieldset[disabled] .btn-primary:hover,.btn-primary.disabled:focus,.btn-primary[disabled]:focus,fieldset[disabled] .btn-primary:focus,.btn-primary.disabled:active,.btn-primary[disabled]:active,fieldset[disabled] .btn-primary:active,.btn-primary.disabled.active,.btn-primary[disabled].active,fieldset[disabled] .btn-primary.active{background-color:#428bca;border-color:#357ebd}.btn-primary .badge{color:#428bca;background-color:#fff}.btn-warning{color:#fff;background-color:#f0ad4e;border-color:#eea236}.btn-warning:hover,.btn-warning:focus,.btn-warning:active,.btn-warning.active,.open .dropdown-toggle.btn-warning{color:#fff;background-color:#ed9c28;border-color:#d58512}.btn-warning:active,.btn-warning.active,.open .dropdown-toggle.btn-warning{background-image:none}.btn-warning.disabled,.btn-warning[disabled],fieldset[disabled] .btn-warning,.btn-warning.disabled:hover,.btn-warning[disabled]:hover,fieldset[disabled] .btn-warning:hover,.btn-warning.disabled:focus,.btn-warning[disabled]:focus,fieldset[disabled] .btn-warning:focus,.btn-warning.disabled:active,.btn-warning[disabled]:active,fieldset[disabled] .btn-warning:active,.btn-warning.disabled.active,.btn-warning[disabled].active,fieldset[disabled] .btn-warning.active{background-color:#f0ad4e;border-color:#eea236}.btn-warning .badge{color:#f0ad4e;background-color:#fff}.btn-danger{color:#fff;background-color:#d9534f;border-color:#d43f3a}.btn-danger:hover,.btn-danger:focus,.btn-danger:active,.btn-danger.active,.open .dropdown-toggle.btn-danger{color:#fff;background-color:#d2322d;border-color:#ac2925}.btn-danger:active,.btn-danger.active,.open .dropdown-toggle.btn-danger{background-image:none}.btn-danger.disabled,.btn-danger[disabled],fieldset[disabled] .btn-danger,.btn-danger.disabled:hover,.btn-danger[disabled]:hover,fieldset[disabled] .btn-danger:hover,.btn-danger.disabled:focus,.btn-danger[disabled]:focus,fieldset[disabled] .btn-danger:focus,.btn-danger.disabled:active,.btn-danger[disabled]:active,fieldset[disabled] .btn-danger:active,.btn-danger.disabled.active,.btn-danger[disabled].active,fieldset[disabled] .btn-danger.active{background-color:#d9534f;border-color:#d43f3a}.btn-danger .badge{color:#d9534f;background-color:#fff}.btn-success{color:#fff;background-color:#5cb85c;border-color:#4cae4c}.btn-success:hover,.btn-success:focus,.btn-success:active,.btn-success.active,.open .dropdown-toggle.btn-success{color:#fff;background-color:#47a447;border-color:#398439}.btn-success:active,.btn-success.active,.open .dropdown-toggle.btn-success{background-image:none}.btn-success.disabled,.btn-success[disabled],fieldset[disabled] .btn-success,.btn-success.disabled:hover,.btn-success[disabled]:hover,fieldset[disabled] .btn-success:hover,.btn-success.disabled:focus,.btn-success[disabled]:focus,fieldset[disabled] .btn-success:focus,.btn-success.disabled:active,.btn-success[disabled]:active,fieldset[disabled] .btn-success:active,.btn-success.disabled.active,.btn-success[disabled].active,fieldset[disabled] .btn-success.active{background-color:#5cb85c;border-color:#4cae4c}.btn-success .badge{color:#5cb85c;background-color:#fff}.btn-info{color:#fff;background-color:#5bc0de;border-color:#46b8da}.btn-info:hover,.btn-info:focus,.btn-info:active,.btn-info.active,.open .dropdown-toggle.btn-info{color:#fff;background-color:#39b3d7;border-color:#269abc}.btn-info:active,.btn-info.active,.open .dropdown-toggle.btn-info{background-image:none}.btn-info.disabled,.btn-info[disabled],fieldset[disabled] .btn-info,.btn-info.disabled:hover,.btn-info[disabled]:hover,fieldset[disabled] .btn-info:hover,.btn-info.disabled:focus,.btn-info[disabled]:focus,fieldset[disabled] .btn-info:focus,.btn-info.disabled:active,.btn-info[disabled]:active,fieldset[disabled] .btn-info:active,.btn-info.disabled.active,.btn-info[disabled].active,fieldset[disabled] .btn-info.active{background-color:#5bc0de;border-color:#46b8da}.btn-info .badge{color:#5bc0de;background-color:#fff}.btn-link{font-weight:normal;color:#428bca;cursor:pointer;border-radius:0}.btn-link,.btn-link:active,.btn-link[disabled],fieldset[disabled] .btn-link{background-color:transparent;-webkit-box-shadow:none;box-shadow:none}.btn-link,.btn-link:hover,.btn-link:focus,.btn-link:active{border-color:transparent}.btn-link:hover,.btn-link:focus{color:#2a6496;text-decoration:underline;background-color:transparent}.btn-link[disabled]:hover,fieldset[disabled] .btn-link:hover,.btn-link[disabled]:focus,fieldset[disabled] .btn-link:focus{color:#999;text-decoration:none}.btn-lg{padding:10px 16px;font-size:18px;line-height:1.33;border-radius:6px}.btn-sm{padding:5px 10px;font-size:12px;line-height:1.5;border-radius:3px}.btn-xs{padding:1px 5px;font-size:12px;line-height:1.5;border-radius:3px}.btn-block{display:block;width:100%;padding-right:0;padding-left:0}.btn-block+.btn-block{margin-top:5px}input[type="submit"].btn-block,input[type="reset"].btn-block,input[type="button"].btn-block{width:100%}.fade{opacity:0;-webkit-transition:opacity .15s linear;transition:opacity .15s linear}.fade.in{opacity:1}.collapse{display:none}.collapse.in{display:block}.collapsing{position:relative;height:0;overflow:hidden;-webkit-transition:height .35s ease;transition:height .35s ease}@font-face{font-family:'Glyphicons Halflings';src:url('../fonts/glyphicons-halflings-regular.eot');src:url('../fonts/glyphicons-halflings-regular.eot?#iefix') format('embedded-opentype'),url('../fonts/glyphicons-halflings-regular.woff') format('woff'),url('../fonts/glyphicons-halflings-regular.ttf') format('truetype'),url('../fonts/glyphicons-halflings-regular.svg#glyphicons-halflingsregular') format('svg')}.glyphicon{position:relative;top:1px;display:inline-block;font-family:'Glyphicons Halflings';-webkit-font-smoothing:antialiased;font-style:normal;font-weight:normal;line-height:1;-moz-osx-font-smoothing:grayscale}.glyphicon:empty{width:1em}.glyphicon-asterisk:before{content:"\2a"}.glyphicon-plus:before{content:"\2b"}.glyphicon-euro:before{content:"\20ac"}.glyphicon-minus:before{content:"\2212"}.glyphicon-cloud:before{content:"\2601"}.glyphicon-envelope:before{content:"\2709"}.glyphicon-pencil:before{content:"\270f"}.glyphicon-glass:before{content:"\e001"}.glyphicon-music:before{content:"\e002"}.glyphicon-search:before{content:"\e003"}.glyphicon-heart:before{content:"\e005"}.glyphicon-star:before{content:"\e006"}.glyphicon-star-empty:before{content:"\e007"}.glyphicon-user:before{content:"\e008"}.glyphicon-film:before{content:"\e009"}.glyphicon-th-large:before{content:"\e010"}.glyphicon-th:before{content:"\e011"}.glyphicon-th-list:before{content:"\e012"}.glyphicon-ok:before{content:"\e013"}.glyphicon-remove:before{content:"\e014"}.glyphicon-zoom-in:before{content:"\e015"}.glyphicon-zoom-out:before{content:"\e016"}.glyphicon-off:before{content:"\e017"}.glyphicon-signal:before{content:"\e018"}.glyphicon-cog:before{content:"\e019"}.glyphicon-trash:before{content:"\e020"}.glyphicon-home:before{content:"\e021"}.glyphicon-file:before{content:"\e022"}.glyphicon-time:before{content:"\e023"}.glyphicon-road:before{content:"\e024"}.glyphicon-download-alt:before{content:"\e025"}.glyphicon-download:before{content:"\e026"}.glyphicon-upload:before{content:"\e027"}.glyphicon-inbox:before{content:"\e028"}.glyphicon-play-circle:before{content:"\e029"}.glyphicon-repeat:before{content:"\e030"}.glyphicon-refresh:before{content:"\e031"}.glyphicon-list-alt:before{content:"\e032"}.glyphicon-lock:before{content:"\e033"}.glyphicon-flag:before{content:"\e034"}.glyphicon-headphones:before{content:"\e035"}.glyphicon-volume-off:before{content:"\e036"}.glyphicon-volume-down:before{content:"\e037"}.glyphicon-volume-up:before{content:"\e038"}.glyphicon-qrcode:before{content:"\e039"}.glyphicon-barcode:before{content:"\e040"}.glyphicon-tag:before{content:"\e041"}.glyphicon-tags:before{content:"\e042"}.glyphicon-book:before{content:"\e043"}.glyphicon-bookmark:before{content:"\e044"}.glyphicon-print:before{content:"\e045"}.glyphicon-camera:before{content:"\e046"}.glyphicon-font:before{content:"\e047"}.glyphicon-bold:before{content:"\e048"}.glyphicon-italic:before{content:"\e049"}.glyphicon-text-height:before{content:"\e050"}.glyphicon-text-width:before{content:"\e051"}.glyphicon-align-left:before{content:"\e052"}.glyphicon-align-center:before{content:"\e053"}.glyphicon-align-right:before{content:"\e054"}.glyphicon-align-justify:before{content:"\e055"}.glyphicon-list:before{content:"\e056"}.glyphicon-indent-left:before{content:"\e057"}.glyphicon-indent-right:before{content:"\e058"}.glyphicon-facetime-video:before{content:"\e059"}.glyphicon-picture:before{content:"\e060"}.glyphicon-map-marker:before{content:"\e062"}.glyphicon-adjust:before{content:"\e063"}.glyphicon-tint:before{content:"\e064"}.glyphicon-edit:before{content:"\e065"}.glyphicon-share:before{content:"\e066"}.glyphicon-check:before{content:"\e067"}.glyphicon-move:before{content:"\e068"}.glyphicon-step-backward:before{content:"\e069"}.glyphicon-fast-backward:before{content:"\e070"}.glyphicon-backward:before{content:"\e071"}.glyphicon-play:before{content:"\e072"}.glyphicon-pause:before{content:"\e073"}.glyphicon-stop:before{content:"\e074"}.glyphicon-forward:before{content:"\e075"}.glyphicon-fast-forward:before{content:"\e076"}.glyphicon-step-forward:before{content:"\e077"}.glyphicon-eject:before{content:"\e078"}.glyphicon-chevron-left:before{content:"\e079"}.glyphicon-chevron-right:before{content:"\e080"}.glyphicon-plus-sign:before{content:"\e081"}.glyphicon-minus-sign:before{content:"\e082"}.glyphicon-remove-sign:before{content:"\e083"}.glyphicon-ok-sign:before{content:"\e084"}.glyphicon-question-sign:before{content:"\e085"}.glyphicon-info-sign:before{content:"\e086"}.glyphicon-screenshot:before{content:"\e087"}.glyphicon-remove-circle:before{content:"\e088"}.glyphicon-ok-circle:before{content:"\e089"}.glyphicon-ban-circle:before{content:"\e090"}.glyphicon-arrow-left:before{content:"\e091"}.glyphicon-arrow-right:before{content:"\e092"}.glyphicon-arrow-up:before{content:"\e093"}.glyphicon-arrow-down:before{content:"\e094"}.glyphicon-share-alt:before{content:"\e095"}.glyphicon-resize-full:before{content:"\e096"}.glyphicon-resize-small:before{content:"\e097"}.glyphicon-exclamation-sign:before{content:"\e101"}.glyphicon-gift:before{content:"\e102"}.glyphicon-leaf:before{content:"\e103"}.glyphicon-fire:before{content:"\e104"}.glyphicon-eye-open:before{content:"\e105"}.glyphicon-eye-close:before{content:"\e106"}.glyphicon-warning-sign:before{content:"\e107"}.glyphicon-plane:before{content:"\e108"}.glyphicon-calendar:before{content:"\e109"}.glyphicon-random:before{content:"\e110"}.glyphicon-comment:before{content:"\e111"}.glyphicon-magnet:before{content:"\e112"}.glyphicon-chevron-up:before{content:"\e113"}.glyphicon-chevron-down:before{content:"\e114"}.glyphicon-retweet:before{content:"\e115"}.glyphicon-shopping-cart:before{content:"\e116"}.glyphicon-folder-close:before{content:"\e117"}.glyphicon-folder-open:before{content:"\e118"}.glyphicon-resize-vertical:before{content:"\e119"}.glyphicon-resize-horizontal:before{content:"\e120"}.glyphicon-hdd:before{content:"\e121"}.glyphicon-bullhorn:before{content:"\e122"}.glyphicon-bell:before{content:"\e123"}.glyphicon-certificate:before{content:"\e124"}.glyphicon-thumbs-up:before{content:"\e125"}.glyphicon-thumbs-down:before{content:"\e126"}.glyphicon-hand-right:before{content:"\e127"}.glyphicon-hand-left:before{content:"\e128"}.glyphicon-hand-up:before{content:"\e129"}.glyphicon-hand-down:before{content:"\e130"}.glyphicon-circle-arrow-right:before{content:"\e131"}.glyphicon-circle-arrow-left:before{content:"\e132"}.glyphicon-circle-arrow-up:before{content:"\e133"}.glyphicon-circle-arrow-down:before{content:"\e134"}.glyphicon-globe:before{content:"\e135"}.glyphicon-wrench:before{content:"\e136"}.glyphicon-tasks:before{content:"\e137"}.glyphicon-filter:before{content:"\e138"}.glyphicon-briefcase:before{content:"\e139"}.glyphicon-fullscreen:before{content:"\e140"}.glyphicon-dashboard:before{content:"\e141"}.glyphicon-paperclip:before{content:"\e142"}.glyphicon-heart-empty:before{content:"\e143"}.glyphicon-link:before{content:"\e144"}.glyphicon-phone:before{content:"\e145"}.glyphicon-pushpin:before{content:"\e146"}.glyphicon-usd:before{content:"\e148"}.glyphicon-gbp:before{content:"\e149"}.glyphicon-sort:before{content:"\e150"}.glyphicon-sort-by-alphabet:before{content:"\e151"}.glyphicon-sort-by-alphabet-alt:before{content:"\e152"}.glyphicon-sort-by-order:before{content:"\e153"}.glyphicon-sort-by-order-alt:before{content:"\e154"}.glyphicon-sort-by-attributes:before{content:"\e155"}.glyphicon-sort-by-attributes-alt:before{content:"\e156"}.glyphicon-unchecked:before{content:"\e157"}.glyphicon-expand:before{content:"\e158"}.glyphicon-collapse-down:before{content:"\e159"}.glyphicon-collapse-up:before{content:"\e160"}.glyphicon-log-in:before{content:"\e161"}.glyphicon-flash:before{content:"\e162"}.glyphicon-log-out:before{content:"\e163"}.glyphicon-new-window:before{content:"\e164"}.glyphicon-record:before{content:"\e165"}.glyphicon-save:before{content:"\e166"}.glyphicon-open:before{content:"\e167"}.glyphicon-saved:before{content:"\e168"}.glyphicon-import:before{content:"\e169"}.glyphicon-export:before{content:"\e170"}.glyphicon-send:before{content:"\e171"}.glyphicon-floppy-disk:before{content:"\e172"}.glyphicon-floppy-saved:before{content:"\e173"}.glyphicon-floppy-remove:before{content:"\e174"}.glyphicon-floppy-save:before{content:"\e175"}.glyphicon-floppy-open:before{content:"\e176"}.glyphicon-credit-card:before{content:"\e177"}.glyphicon-transfer:before{content:"\e178"}.glyphicon-cutlery:before{content:"\e179"}.glyphicon-header:before{content:"\e180"}.glyphicon-compressed:before{content:"\e181"}.glyphicon-earphone:before{content:"\e182"}.glyphicon-phone-alt:before{content:"\e183"}.glyphicon-tower:before{content:"\e184"}.glyphicon-stats:before{content:"\e185"}.glyphicon-sd-video:before{content:"\e186"}.glyphicon-hd-video:before{content:"\e187"}.glyphicon-subtitles:before{content:"\e188"}.glyphicon-sound-stereo:before{content:"\e189"}.glyphicon-sound-dolby:before{content:"\e190"}.glyphicon-sound-5-1:before{content:"\e191"}.glyphicon-sound-6-1:before{content:"\e192"}.glyphicon-sound-7-1:before{content:"\e193"}.glyphicon-copyright-mark:before{content:"\e194"}.glyphicon-registration-mark:before{content:"\e195"}.glyphicon-cloud-download:before{content:"\e197"}.glyphicon-cloud-upload:before{content:"\e198"}.glyphicon-tree-conifer:before{content:"\e199"}.glyphicon-tree-deciduous:before{content:"\e200"}.caret{display:inline-block;width:0;height:0;margin-left:2px;vertical-align:middle;border-top:4px solid;border-right:4px solid transparent;border-left:4px solid transparent}.dropdown{position:relative}.dropdown-toggle:focus{outline:0}.dropdown-menu{position:absolute;top:100%;left:0;z-index:1000;display:none;float:left;min-width:160px;padding:5px 0;margin:2px 0 0;font-size:14px;list-style:none;background-color:#fff;border:1px solid #ccc;border:1px solid rgba(0,0,0,0.15);border-radius:4px;-webkit-box-shadow:0 6px 12px rgba(0,0,0,0.175);box-shadow:0 6px 12px rgba(0,0,0,0.175);background-clip:padding-box}.dropdown-menu.pull-right{right:0;left:auto}.dropdown-menu .divider{height:1px;margin:9px 0;overflow:hidden;background-color:#e5e5e5}.dropdown-menu>li>a{display:block;padding:3px 20px;clear:both;font-weight:normal;line-height:1.428571429;color:#333;white-space:nowrap}.dropdown-menu>li>a:hover,.dropdown-menu>li>a:focus{color:#262626;text-decoration:none;background-color:#f5f5f5}.dropdown-menu>.active>a,.dropdown-menu>.active>a:hover,.dropdown-menu>.active>a:focus{color:#fff;text-decoration:none;background-color:#428bca;outline:0}.dropdown-menu>.disabled>a,.dropdown-menu>.disabled>a:hover,.dropdown-menu>.disabled>a:focus{color:#999}.dropdown-menu>.disabled>a:hover,.dropdown-menu>.disabled>a:focus{text-decoration:none;cursor:not-allowed;background-color:transparent;background-image:none;filter:progid:DXImageTransform.Microsoft.gradient(enabled=false)}.open>.dropdown-menu{display:block}.open>a{outline:0}.dropdown-header{display:block;padding:3px 20px;font-size:12px;line-height:1.428571429;color:#999}.dropdown-backdrop{position:fixed;top:0;right:0;bottom:0;left:0;z-index:990}.pull-right>.dropdown-menu{right:0;left:auto}.dropup .caret,.navbar-fixed-bottom .dropdown .caret{border-top:0;border-bottom:4px solid;content:""}.dropup .dropdown-menu,.navbar-fixed-bottom .dropdown .dropdown-menu{top:auto;bottom:100%;margin-bottom:1px}@media(min-width:768px){.navbar-right .dropdown-menu{right:0;left:auto}}.btn-group,.btn-group-vertical{position:relative;display:inline-block;vertical-align:middle}.btn-group>.btn,.btn-group-vertical>.btn{position:relative;float:left}.btn-group>.btn:hover,.btn-group-vertical>.btn:hover,.btn-group>.btn:focus,.btn-group-vertical>.btn:focus,.btn-group>.btn:active,.btn-group-vertical>.btn:active,.btn-group>.btn.active,.btn-group-vertical>.btn.active{z-index:2}.btn-group>.btn:focus,.btn-group-vertical>.btn:focus{outline:0}.btn-group .btn+.btn,.btn-group .btn+.btn-group,.btn-group .btn-group+.btn,.btn-group .btn-group+.btn-group{margin-left:-1px}.btn-toolbar:before,.btn-toolbar:after{display:table;content:" "}.btn-toolbar:after{clear:both}.btn-toolbar:before,.btn-toolbar:after{display:table;content:" "}.btn-toolbar:after{clear:both}.btn-toolbar .btn-group{float:left}.btn-toolbar>.btn+.btn,.btn-toolbar>.btn-group+.btn,.btn-toolbar>.btn+.btn-group,.btn-toolbar>.btn-group+.btn-group{margin-left:5px}.btn-group>.btn:not(:first-child):not(:last-child):not(.dropdown-toggle){border-radius:0}.btn-group>.btn:first-child{margin-left:0}.btn-group>.btn:first-child:not(:last-child):not(.dropdown-toggle){border-top-right-radius:0;border-bottom-right-radius:0}.btn-group>.btn:last-child:not(:first-child),.btn-group>.dropdown-toggle:not(:first-child){border-bottom-left-radius:0;border-top-left-radius:0}.btn-group>.btn-group{float:left}.btn-group>.btn-group:not(:first-child):not(:last-child)>.btn{border-radius:0}.btn-group>.btn-group:first-child>.btn:last-child,.btn-group>.btn-group:first-child>.dropdown-toggle{border-top-right-radius:0;border-bottom-right-radius:0}.btn-group>.btn-group:last-child>.btn:first-child{border-bottom-left-radius:0;border-top-left-radius:0}.btn-group .dropdown-toggle:active,.btn-group.open .dropdown-toggle{outline:0}.btn-group-xs>.btn{padding:1px 5px;font-size:12px;line-height:1.5;border-radius:3px}.btn-group-sm>.btn{padding:5px 10px;font-size:12px;line-height:1.5;border-radius:3px}.btn-group-lg>.btn{padding:10px 16px;font-size:18px;line-height:1.33;border-radius:6px}.btn-group>.btn+.dropdown-toggle{padding-right:8px;padding-left:8px}.btn-group>.btn-lg+.dropdown-toggle{padding-right:12px;padding-left:12px}.btn-group.open .dropdown-toggle{-webkit-box-shadow:inset 0 3px 5px rgba(0,0,0,0.125);box-shadow:inset 0 3px 5px rgba(0,0,0,0.125)}.btn-group.open .dropdown-toggle.btn-link{-webkit-box-shadow:none;box-shadow:none}.btn .caret{margin-left:0}.btn-lg .caret{border-width:5px 5px 0;border-bottom-width:0}.dropup .btn-lg .caret{border-width:0 5px 5px}.btn-group-vertical>.btn,.btn-group-vertical>.btn-group,.btn-group-vertical>.btn-group>.btn{display:block;float:none;width:100%;max-width:100%}.btn-group-vertical>.btn-group:before,.btn-group-vertical>.btn-group:after{display:table;content:" "}.btn-group-vertical>.btn-group:after{clear:both}.btn-group-vertical>.btn-group:before,.btn-group-vertical>.btn-group:after{display:table;content:" "}.btn-group-vertical>.btn-group:after{clear:both}.btn-group-vertical>.btn-group>.btn{float:none}.btn-group-vertical>.btn+.btn,.btn-group-vertical>.btn+.btn-group,.btn-group-vertical>.btn-group+.btn,.btn-group-vertical>.btn-group+.btn-group{margin-top:-1px;margin-left:0}.btn-group-vertical>.btn:not(:first-child):not(:last-child){border-radius:0}.btn-group-vertical>.btn:first-child:not(:last-child){border-top-right-radius:4px;border-bottom-right-radius:0;border-bottom-left-radius:0}.btn-group-vertical>.btn:last-child:not(:first-child){border-top-right-radius:0;border-bottom-left-radius:4px;border-top-left-radius:0}.btn-group-vertical>.btn-group:not(:first-child):not(:last-child)>.btn{border-radius:0}.btn-group-vertical>.btn-group:first-child>.btn:last-child,.btn-group-vertical>.btn-group:first-child>.dropdown-toggle{border-bottom-right-radius:0;border-bottom-left-radius:0}.btn-group-vertical>.btn-group:last-child>.btn:first-child{border-top-right-radius:0;border-top-left-radius:0}.btn-group-justified{display:table;width:100%;border-collapse:separate;table-layout:fixed}.btn-group-justified>.btn,.btn-group-justified>.btn-group{display:table-cell;float:none;width:1%}.btn-group-justified>.btn-group .btn{width:100%}[data-toggle="buttons"]>.btn>input[type="radio"],[data-toggle="buttons"]>.btn>input[type="checkbox"]{display:none}.input-group{position:relative;display:table;border-collapse:separate}.input-group[class*="col-"]{float:none;padding-right:0;padding-left:0}.input-group .form-control{width:100%;margin-bottom:0}.input-group-lg>.form-control,.input-group-lg>.input-group-addon,.input-group-lg>.input-group-btn>.btn{height:46px;padding:10px 16px;font-size:18px;line-height:1.33;border-radius:6px}select.input-group-lg>.form-control,select.input-group-lg>.input-group-addon,select.input-group-lg>.input-group-btn>.btn{height:46px;line-height:46px}textarea.input-group-lg>.form-control,textarea.input-group-lg>.input-group-addon,textarea.input-group-lg>.input-group-btn>.btn{height:auto}.input-group-sm>.form-control,.input-group-sm>.input-group-addon,.input-group-sm>.input-group-btn>.btn{height:30px;padding:5px 10px;font-size:12px;line-height:1.5;border-radius:3px}select.input-group-sm>.form-control,select.input-group-sm>.input-group-addon,select.input-group-sm>.input-group-btn>.btn{height:30px;line-height:30px}textarea.input-group-sm>.form-control,textarea.input-group-sm>.input-group-addon,textarea.input-group-sm>.input-group-btn>.btn{height:auto}.input-group-addon,.input-group-btn,.input-group .form-control{display:table-cell}.input-group-addon:not(:first-child):not(:last-child),.input-group-btn:not(:first-child):not(:last-child),.input-group .form-control:not(:first-child):not(:last-child){border-radius:0}.input-group-addon,.input-group-btn{width:1%;white-space:nowrap;vertical-align:middle}.input-group-addon{padding:6px 12px;font-size:14px;font-weight:normal;line-height:1;color:#555;text-align:center;background-color:#eee;border:1px solid #ccc;border-radius:4px}.input-group-addon.input-sm{padding:5px 10px;font-size:12px;border-radius:3px}.input-group-addon.input-lg{padding:10px 16px;font-size:18px;border-radius:6px}.input-group-addon input[type="radio"],.input-group-addon input[type="checkbox"]{margin-top:0}.input-group .form-control:first-child,.input-group-addon:first-child,.input-group-btn:first-child>.btn,.input-group-btn:first-child>.dropdown-toggle,.input-group-btn:last-child>.btn:not(:last-child):not(.dropdown-toggle){border-top-right-radius:0;border-bottom-right-radius:0}.input-group-addon:first-child{border-right:0}.input-group .form-control:last-child,.input-group-addon:last-child,.input-group-btn:last-child>.btn,.input-group-btn:last-child>.dropdown-toggle,.input-group-btn:first-child>.btn:not(:first-child){border-bottom-left-radius:0;border-top-left-radius:0}.input-group-addon:last-child{border-left:0}.input-group-btn{position:relative;white-space:nowrap}.input-group-btn:first-child>.btn{margin-right:-1px}.input-group-btn:last-child>.btn{margin-left:-1px}.input-group-btn>.btn{position:relative}.input-group-btn>.btn+.btn{margin-left:-4px}.input-group-btn>.btn:hover,.input-group-btn>.btn:active{z-index:2}.nav{padding-left:0;margin-bottom:0;list-style:none}.nav:before,.nav:after{display:table;content:" "}.nav:after{clear:both}.nav:before,.nav:after{display:table;content:" "}.nav:after{clear:both}.nav>li{position:relative;display:block}.nav>li>a{position:relative;display:block;padding:10px 15px}.nav>li>a:hover,.nav>li>a:focus{text-decoration:none;background-color:#eee}.nav>li.disabled>a{color:#999}.nav>li.disabled>a:hover,.nav>li.disabled>a:focus{color:#999;text-decoration:none;cursor:not-allowed;background-color:transparent}.nav .open>a,.nav .open>a:hover,.nav .open>a:focus{background-color:#eee;border-color:#428bca}.nav .nav-divider{height:1px;margin:9px 0;overflow:hidden;background-color:#e5e5e5}.nav>li>a>img{max-width:none}.nav-tabs{border-bottom:1px solid #ddd}.nav-tabs>li{float:left;margin-bottom:-1px}.nav-tabs>li>a{margin-right:2px;line-height:1.428571429;border:1px solid transparent;border-radius:4px 4px 0 0}.nav-tabs>li>a:hover{border-color:#eee #eee #ddd}.nav-tabs>li.active>a,.nav-tabs>li.active>a:hover,.nav-tabs>li.active>a:focus{color:#555;cursor:default;background-color:#fff;border:1px solid #ddd;border-bottom-color:transparent}.nav-tabs.nav-justified{width:100%;border-bottom:0}.nav-tabs.nav-justified>li{float:none}.nav-tabs.nav-justified>li>a{margin-bottom:5px;text-align:center}.nav-tabs.nav-justified>.dropdown .dropdown-menu{top:auto;left:auto}@media(min-width:768px){.nav-tabs.nav-justified>li{display:table-cell;width:1%}.nav-tabs.nav-justified>li>a{margin-bottom:0}}.nav-tabs.nav-justified>li>a{margin-right:0;border-radius:4px}.nav-tabs.nav-justified>.active>a,.nav-tabs.nav-justified>.active>a:hover,.nav-tabs.nav-justified>.active>a:focus{border:1px solid #ddd}@media(min-width:768px){.nav-tabs.nav-justified>li>a{border-bottom:1px solid #ddd;border-radius:4px 4px 0 0}.nav-tabs.nav-justified>.active>a,.nav-tabs.nav-justified>.active>a:hover,.nav-tabs.nav-justified>.active>a:focus{border-bottom-color:#fff}}.nav-pills>li{float:left}.nav-pills>li>a{border-radius:4px}.nav-pills>li+li{margin-left:2px}.nav-pills>li.active>a,.nav-pills>li.active>a:hover,.nav-pills>li.active>a:focus{color:#fff;background-color:#428bca}.nav-stacked>li{float:none}.nav-stacked>li+li{margin-top:2px;margin-left:0}.nav-justified{width:100%}.nav-justified>li{float:none}.nav-justified>li>a{margin-bottom:5px;text-align:center}.nav-justified>.dropdown .dropdown-menu{top:auto;left:auto}@media(min-width:768px){.nav-justified>li{display:table-cell;width:1%}.nav-justified>li>a{margin-bottom:0}}.nav-tabs-justified{border-bottom:0}.nav-tabs-justified>li>a{margin-right:0;border-radius:4px}.nav-tabs-justified>.active>a,.nav-tabs-justified>.active>a:hover,.nav-tabs-justified>.active>a:focus{border:1px solid #ddd}@media(min-width:768px){.nav-tabs-justified>li>a{border-bottom:1px solid #ddd;border-radius:4px 4px 0 0}.nav-tabs-justified>.active>a,.nav-tabs-justified>.active>a:hover,.nav-tabs-justified>.active>a:focus{border-bottom-color:#fff}}.tab-content>.tab-pane{display:none}.tab-content>.active{display:block}.nav-tabs .dropdown-menu{margin-top:-1px;border-top-right-radius:0;border-top-left-radius:0}.navbar{position:relative;min-height:50px;margin-bottom:20px;border:1px solid transparent}.navbar:before,.navbar:after{display:table;content:" "}.navbar:after{clear:both}.navbar:before,.navbar:after{display:table;content:" "}.navbar:after{clear:both}@media(min-width:768px){.navbar{border-radius:4px}}.navbar-header:before,.navbar-header:after{display:table;content:" "}.navbar-header:after{clear:both}.navbar-header:before,.navbar-header:after{display:table;content:" "}.navbar-header:after{clear:both}@media(min-width:768px){.navbar-header{float:left}}.navbar-collapse{max-height:340px;padding-right:15px;padding-left:15px;overflow-x:visible;border-top:1px solid transparent;box-shadow:inset 0 1px 0 rgba(255,255,255,0.1);-webkit-overflow-scrolling:touch}.navbar-collapse:before,.navbar-collapse:after{display:table;content:" "}.navbar-collapse:after{clear:both}.navbar-collapse:before,.navbar-collapse:after{display:table;content:" "}.navbar-collapse:after{clear:both}.navbar-collapse.in{overflow-y:auto}@media(min-width:768px){.navbar-collapse{width:auto;border-top:0;box-shadow:none}.navbar-collapse.collapse{display:block!important;height:auto!important;padding-bottom:0;overflow:visible!important}.navbar-collapse.in{overflow-y:visible}.navbar-fixed-top .navbar-collapse,.navbar-static-top .navbar-collapse,.navbar-fixed-bottom .navbar-collapse{padding-right:0;padding-left:0}}.container>.navbar-header,.container>.navbar-collapse{margin-right:-15px;margin-left:-15px}@media(min-width:768px){.container>.navbar-header,.container>.navbar-collapse{margin-right:0;margin-left:0}}.navbar-static-top{z-index:1000;border-width:0 0 1px}@media(min-width:768px){.navbar-static-top{border-radius:0}}.navbar-fixed-top,.navbar-fixed-bottom{position:fixed;right:0;left:0;z-index:1030}@media(min-width:768px){.navbar-fixed-top,.navbar-fixed-bottom{border-radius:0}}.navbar-fixed-top{top:0;border-width:0 0 1px}.navbar-fixed-bottom{bottom:0;margin-bottom:0;border-width:1px 0 0}.navbar-brand{float:left;padding:15px 15px;font-size:18px;line-height:20px}.navbar-brand:hover,.navbar-brand:focus{text-decoration:none}@media(min-width:768px){.navbar>.container .navbar-brand{margin-left:-15px}}.navbar-toggle{position:relative;float:right;padding:9px 10px;margin-top:8px;margin-right:15px;margin-bottom:8px;background-color:transparent;background-image:none;border:1px solid transparent;border-radius:4px}.navbar-toggle .icon-bar{display:block;width:22px;height:2px;border-radius:1px}.navbar-toggle .icon-bar+.icon-bar{margin-top:4px}@media(min-width:768px){.navbar-toggle{display:none}}.navbar-nav{margin:7.5px -15px}.navbar-nav>li>a{padding-top:10px;padding-bottom:10px;line-height:20px}@media(max-width:767px){.navbar-nav .open .dropdown-menu{position:static;float:none;width:auto;margin-top:0;background-color:transparent;border:0;box-shadow:none}.navbar-nav .open .dropdown-menu>li>a,.navbar-nav .open .dropdown-menu .dropdown-header{padding:5px 15px 5px 25px}.navbar-nav .open .dropdown-menu>li>a{line-height:20px}.navbar-nav .open .dropdown-menu>li>a:hover,.navbar-nav .open .dropdown-menu>li>a:focus{background-image:none}}@media(min-width:768px){.navbar-nav{float:left;margin:0}.navbar-nav>li{float:left}.navbar-nav>li>a{padding-top:15px;padding-bottom:15px}.navbar-nav.navbar-right:last-child{margin-right:-15px}}@media(min-width:768px){.navbar-left{float:left!important}.navbar-right{float:right!important}}.navbar-form{padding:10px 15px;margin-top:8px;margin-right:-15px;margin-bottom:8px;margin-left:-15px;border-top:1px solid transparent;border-bottom:1px solid transparent;-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,0.1),0 1px 0 rgba(255,255,255,0.1);box-shadow:inset 0 1px 0 rgba(255,255,255,0.1),0 1px 0 rgba(255,255,255,0.1)}@media(min-width:768px){.navbar-form .form-group{display:inline-block;margin-bottom:0;vertical-align:middle}.navbar-form .form-control{display:inline-block}.navbar-form select.form-control{width:auto}.navbar-form .radio,.navbar-form .checkbox{display:inline-block;padding-left:0;margin-top:0;margin-bottom:0}.navbar-form .radio input[type="radio"],.navbar-form .checkbox input[type="checkbox"]{float:none;margin-left:0}}@media(max-width:767px){.navbar-form .form-group{margin-bottom:5px}}@media(min-width:768px){.navbar-form{width:auto;padding-top:0;padding-bottom:0;margin-right:0;margin-left:0;border:0;-webkit-box-shadow:none;box-shadow:none}.navbar-form.navbar-right:last-child{margin-right:-15px}}.navbar-nav>li>.dropdown-menu{margin-top:0;border-top-right-radius:0;border-top-left-radius:0}.navbar-fixed-bottom .navbar-nav>li>.dropdown-menu{border-bottom-right-radius:0;border-bottom-left-radius:0}.navbar-nav.pull-right>li>.dropdown-menu,.navbar-nav>li>.dropdown-menu.pull-right{right:0;left:auto}.navbar-btn{margin-top:8px;margin-bottom:8px}.navbar-btn.btn-sm{margin-top:10px;margin-bottom:10px}.navbar-btn.btn-xs{margin-top:14px;margin-bottom:14px}.navbar-text{margin-top:15px;margin-bottom:15px}@media(min-width:768px){.navbar-text{float:left;margin-right:15px;margin-left:15px}.navbar-text.navbar-right:last-child{margin-right:0}}.navbar-default{background-color:#f8f8f8;border-color:#e7e7e7}.navbar-default .navbar-brand{color:#777}.navbar-default .navbar-brand:hover,.navbar-default .navbar-brand:focus{color:#5e5e5e;background-color:transparent}.navbar-default .navbar-text{color:#777}.navbar-default .navbar-nav>li>a{color:#777}.navbar-default .navbar-nav>li>a:hover,.navbar-default .navbar-nav>li>a:focus{color:#333;background-color:transparent}.navbar-default .navbar-nav>.active>a,.navbar-default .navbar-nav>.active>a:hover,.navbar-default .navbar-nav>.active>a:focus{color:#555;background-color:#e7e7e7}.navbar-default .navbar-nav>.disabled>a,.navbar-default .navbar-nav>.disabled>a:hover,.navbar-default .navbar-nav>.disabled>a:focus{color:#ccc;background-color:transparent}.navbar-default .navbar-toggle{border-color:#ddd}.navbar-default .navbar-toggle:hover,.navbar-default .navbar-toggle:focus{background-color:#ddd}.navbar-default .navbar-toggle .icon-bar{background-color:#ccc}.navbar-default .navbar-collapse,.navbar-default .navbar-form{border-color:#e7e7e7}.navbar-default .navbar-nav>.open>a,.navbar-default .navbar-nav>.open>a:hover,.navbar-default .navbar-nav>.open>a:focus{color:#555;background-color:#e7e7e7}@media(max-width:767px){.navbar-default .navbar-nav .open .dropdown-menu>li>a{color:#777}.navbar-default .navbar-nav .open .dropdown-menu>li>a:hover,.navbar-default .navbar-nav .open .dropdown-menu>li>a:focus{color:#333;background-color:transparent}.navbar-default .navbar-nav .open .dropdown-menu>.active>a,.navbar-default .navbar-nav .open .dropdown-menu>.active>a:hover,.navbar-default .navbar-nav .open .dropdown-menu>.active>a:focus{color:#555;background-color:#e7e7e7}.navbar-default .navbar-nav .open .dropdown-menu>.disabled>a,.navbar-default .navbar-nav .open .dropdown-menu>.disabled>a:hover,.navbar-default .navbar-nav .open .dropdown-menu>.disabled>a:focus{color:#ccc;background-color:transparent}}.navbar-default .navbar-link{color:#777}.navbar-default .navbar-link:hover{color:#333}.navbar-inverse{background-color:#222;border-color:#080808}.navbar-inverse .navbar-brand{color:#999}.navbar-inverse .navbar-brand:hover,.navbar-inverse .navbar-brand:focus{color:#fff;background-color:transparent}.navbar-inverse .navbar-text{color:#999}.navbar-inverse .navbar-nav>li>a{color:#999}.navbar-inverse .navbar-nav>li>a:hover,.navbar-inverse .navbar-nav>li>a:focus{color:#fff;background-color:transparent}.navbar-inverse .navbar-nav>.active>a,.navbar-inverse .navbar-nav>.active>a:hover,.navbar-inverse .navbar-nav>.active>a:focus{color:#fff;background-color:#080808}.navbar-inverse .navbar-nav>.disabled>a,.navbar-inverse .navbar-nav>.disabled>a:hover,.navbar-inverse .navbar-nav>.disabled>a:focus{color:#444;background-color:transparent}.navbar-inverse .navbar-toggle{border-color:#333}.navbar-inverse .navbar-toggle:hover,.navbar-inverse .navbar-toggle:focus{background-color:#333}.navbar-inverse .navbar-toggle .icon-bar{background-color:#fff}.navbar-inverse .navbar-collapse,.navbar-inverse .navbar-form{border-color:#101010}.navbar-inverse .navbar-nav>.open>a,.navbar-inverse .navbar-nav>.open>a:hover,.navbar-inverse .navbar-nav>.open>a:focus{color:#fff;background-color:#080808}@media(max-width:767px){.navbar-inverse .navbar-nav .open .dropdown-menu>.dropdown-header{border-color:#080808}.navbar-inverse .navbar-nav .open .dropdown-menu .divider{background-color:#080808}.navbar-inverse .navbar-nav .open .dropdown-menu>li>a{color:#999}.navbar-inverse .navbar-nav .open .dropdown-menu>li>a:hover,.navbar-inverse .navbar-nav .open .dropdown-menu>li>a:focus{color:#fff;background-color:transparent}.navbar-inverse .navbar-nav .open .dropdown-menu>.active>a,.navbar-inverse .navbar-nav .open .dropdown-menu>.active>a:hover,.navbar-inverse .navbar-nav .open .dropdown-menu>.active>a:focus{color:#fff;background-color:#080808}.navbar-inverse .navbar-nav .open .dropdown-menu>.disabled>a,.navbar-inverse .navbar-nav .open .dropdown-menu>.disabled>a:hover,.navbar-inverse .navbar-nav .open .dropdown-menu>.disabled>a:focus{color:#444;background-color:transparent}}.navbar-inverse .navbar-link{color:#999}.navbar-inverse .navbar-link:hover{color:#fff}.breadcrumb{padding:8px 15px;margin-bottom:20px;list-style:none;background-color:#f5f5f5;border-radius:4px}.breadcrumb>li{display:inline-block}.breadcrumb>li+li:before{padding:0 5px;color:#ccc;content:"/\00a0"}.breadcrumb>.active{color:#999}.pagination{display:inline-block;padding-left:0;margin:20px 0;border-radius:4px}.pagination>li{display:inline}.pagination>li>a,.pagination>li>span{position:relative;float:left;padding:6px 12px;margin-left:-1px;line-height:1.428571429;text-decoration:none;background-color:#fff;border:1px solid #ddd}.pagination>li:first-child>a,.pagination>li:first-child>span{margin-left:0;border-bottom-left-radius:4px;border-top-left-radius:4px}.pagination>li:last-child>a,.pagination>li:last-child>span{border-top-right-radius:4px;border-bottom-right-radius:4px}.pagination>li>a:hover,.pagination>li>span:hover,.pagination>li>a:focus,.pagination>li>span:focus{background-color:#eee}.pagination>.active>a,.pagination>.active>span,.pagination>.active>a:hover,.pagination>.active>span:hover,.pagination>.active>a:focus,.pagination>.active>span:focus{z-index:2;color:#fff;cursor:default;background-color:#428bca;border-color:#428bca}.pagination>.disabled>span,.pagination>.disabled>span:hover,.pagination>.disabled>span:focus,.pagination>.disabled>a,.pagination>.disabled>a:hover,.pagination>.disabled>a:focus{color:#999;cursor:not-allowed;background-color:#fff;border-color:#ddd}.pagination-lg>li>a,.pagination-lg>li>span{padding:10px 16px;font-size:18px}.pagination-lg>li:first-child>a,.pagination-lg>li:first-child>span{border-bottom-left-radius:6px;border-top-left-radius:6px}.pagination-lg>li:last-child>a,.pagination-lg>li:last-child>span{border-top-right-radius:6px;border-bottom-right-radius:6px}.pagination-sm>li>a,.pagination-sm>li>span{padding:5px 10px;font-size:12px}.pagination-sm>li:first-child>a,.pagination-sm>li:first-child>span{border-bottom-left-radius:3px;border-top-left-radius:3px}.pagination-sm>li:last-child>a,.pagination-sm>li:last-child>span{border-top-right-radius:3px;border-bottom-right-radius:3px}.pager{padding-left:0;margin:20px 0;text-align:center;list-style:none}.pager:before,.pager:after{display:table;content:" "}.pager:after{clear:both}.pager:before,.pager:after{display:table;content:" "}.pager:after{clear:both}.pager li{display:inline}.pager li>a,.pager li>span{display:inline-block;padding:5px 14px;background-color:#fff;border:1px solid #ddd;border-radius:15px}.pager li>a:hover,.pager li>a:focus{text-decoration:none;background-color:#eee}.pager .next>a,.pager .next>span{float:right}.pager .previous>a,.pager .previous>span{float:left}.pager .disabled>a,.pager .disabled>a:hover,.pager .disabled>a:focus,.pager .disabled>span{color:#999;cursor:not-allowed;background-color:#fff}.label{display:inline;padding:.2em .6em .3em;font-size:75%;font-weight:bold;line-height:1;color:#fff;text-align:center;white-space:nowrap;vertical-align:baseline;border-radius:.25em}.label[href]:hover,.label[href]:focus{color:#fff;text-decoration:none;cursor:pointer}.label:empty{display:none}.btn .label{position:relative;top:-1px}.label-default{background-color:#999}.label-default[href]:hover,.label-default[href]:focus{background-color:#808080}.label-primary{background-color:#428bca}.label-primary[href]:hover,.label-primary[href]:focus{background-color:#3071a9}.label-success{background-color:#5cb85c}.label-success[href]:hover,.label-success[href]:focus{background-color:#449d44}.label-info{background-color:#5bc0de}.label-info[href]:hover,.label-info[href]:focus{background-color:#31b0d5}.label-warning{background-color:#f0ad4e}.label-warning[href]:hover,.label-warning[href]:focus{background-color:#ec971f}.label-danger{background-color:#d9534f}.label-danger[href]:hover,.label-danger[href]:focus{background-color:#c9302c}.badge{display:inline-block;min-width:10px;padding:3px 7px;font-size:12px;font-weight:bold;line-height:1;color:#fff;text-align:center;white-space:nowrap;vertical-align:baseline;background-color:#999;border-radius:10px}.badge:empty{display:none}.btn .badge{position:relative;top:-1px}a.badge:hover,a.badge:focus{color:#fff;text-decoration:none;cursor:pointer}a.list-group-item.active>.badge,.nav-pills>.active>a>.badge{color:#428bca;background-color:#fff}.nav-pills>li>a>.badge{margin-left:3px}.jumbotron{padding:30px;margin-bottom:30px;font-size:21px;font-weight:200;line-height:2.1428571435;color:inherit;background-color:#eee}.jumbotron h1,.jumbotron .h1{line-height:1;color:inherit}.jumbotron p{line-height:1.4}.container .jumbotron{border-radius:6px}.jumbotron .container{max-width:100%}@media screen and (min-width:768px){.jumbotron{padding-top:48px;padding-bottom:48px}.container .jumbotron{padding-right:60px;padding-left:60px}.jumbotron h1,.jumbotron .h1{font-size:63px}}.thumbnail{display:block;padding:4px;margin-bottom:20px;line-height:1.428571429;background-color:#fff;border:1px solid #ddd;border-radius:4px;-webkit-transition:all .2s ease-in-out;transition:all .2s ease-in-out}.thumbnail>img,.thumbnail a>img{display:block;height:auto;max-width:100%;margin-right:auto;margin-left:auto}a.thumbnail:hover,a.thumbnail:focus,a.thumbnail.active{border-color:#428bca}.thumbnail .caption{padding:9px;color:#333}.alert{padding:15px;margin-bottom:20px;border:1px solid transparent;border-radius:4px}.alert h4{margin-top:0;color:inherit}.alert .alert-link{font-weight:bold}.alert>p,.alert>ul{margin-bottom:0}.alert>p+p{margin-top:5px}.alert-dismissable{padding-right:35px}.alert-dismissable .close{position:relative;top:-2px;right:-21px;color:inherit}.alert-success{color:#3c763d;background-color:#dff0d8;border-color:#d6e9c6}.alert-success hr{border-top-color:#c9e2b3}.alert-success .alert-link{color:#2b542c}.alert-info{color:#31708f;background-color:#d9edf7;border-color:#bce8f1}.alert-info hr{border-top-color:#a6e1ec}.alert-info .alert-link{color:#245269}.alert-warning{color:#8a6d3b;background-color:#fcf8e3;border-color:#faebcc}.alert-warning hr{border-top-color:#f7e1b5}.alert-warning .alert-link{color:#66512c}.alert-danger{color:#a94442;background-color:#f2dede;border-color:#ebccd1}.alert-danger hr{border-top-color:#e4b9c0}.alert-danger .alert-link{color:#843534}@-webkit-keyframes progress-bar-stripes{from{background-position:40px 0}to{background-position:0 0}}@keyframes progress-bar-stripes{from{background-position:40px 0}to{background-position:0 0}}.progress{height:20px;margin-bottom:20px;overflow:hidden;background-color:#f5f5f5;border-radius:4px;-webkit-box-shadow:inset 0 1px 2px rgba(0,0,0,0.1);box-shadow:inset 0 1px 2px rgba(0,0,0,0.1)}.progress-bar{float:left;width:0;height:100%;font-size:12px;line-height:20px;color:#fff;text-align:center;background-color:#428bca;-webkit-box-shadow:inset 0 -1px 0 rgba(0,0,0,0.15);box-shadow:inset 0 -1px 0 rgba(0,0,0,0.15);-webkit-transition:width .6s ease;transition:width .6s ease}.progress-striped .progress-bar{background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-size:40px 40px}.progress.active .progress-bar{-webkit-animation:progress-bar-stripes 2s linear infinite;animation:progress-bar-stripes 2s linear infinite}.progress-bar-success{background-color:#5cb85c}.progress-striped .progress-bar-success{background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent)}.progress-bar-info{background-color:#5bc0de}.progress-striped .progress-bar-info{background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent)}.progress-bar-warning{background-color:#f0ad4e}.progress-striped .progress-bar-warning{background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent)}.progress-bar-danger{background-color:#d9534f}.progress-striped .progress-bar-danger{background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent)}.media,.media-body{overflow:hidden;zoom:1}.media,.media .media{margin-top:15px}.media:first-child{margin-top:0}.media-object{display:block}.media-heading{margin:0 0 5px}.media>.pull-left{margin-right:10px}.media>.pull-right{margin-left:10px}.media-list{padding-left:0;list-style:none}.list-group{padding-left:0;margin-bottom:20px}.list-group-item{position:relative;display:block;padding:10px 15px;margin-bottom:-1px;background-color:#fff;border:1px solid #ddd}.list-group-item:first-child{border-top-right-radius:4px;border-top-left-radius:4px}.list-group-item:last-child{margin-bottom:0;border-bottom-right-radius:4px;border-bottom-left-radius:4px}.list-group-item>.badge{float:right}.list-group-item>.badge+.badge{margin-right:5px}a.list-group-item{color:#555}a.list-group-item .list-group-item-heading{color:#333}a.list-group-item:hover,a.list-group-item:focus{text-decoration:none;background-color:#f5f5f5}a.list-group-item.active,a.list-group-item.active:hover,a.list-group-item.active:focus{z-index:2;color:#fff;background-color:#428bca;border-color:#428bca}a.list-group-item.active .list-group-item-heading,a.list-group-item.active:hover .list-group-item-heading,a.list-group-item.active:focus .list-group-item-heading{color:inherit}a.list-group-item.active .list-group-item-text,a.list-group-item.active:hover .list-group-item-text,a.list-group-item.active:focus .list-group-item-text{color:#e1edf7}.list-group-item-heading{margin-top:0;margin-bottom:5px}.list-group-item-text{margin-bottom:0;line-height:1.3}.panel{margin-bottom:20px;background-color:#fff;border:1px solid transparent;border-radius:4px;-webkit-box-shadow:0 1px 1px rgba(0,0,0,0.05);box-shadow:0 1px 1px rgba(0,0,0,0.05)}.panel-body{padding:15px}.panel-body:before,.panel-body:after{display:table;content:" "}.panel-body:after{clear:both}.panel-body:before,.panel-body:after{display:table;content:" "}.panel-body:after{clear:both}.panel>.list-group{margin-bottom:0}.panel>.list-group .list-group-item{border-width:1px 0}.panel>.list-group .list-group-item:first-child{border-top-right-radius:0;border-top-left-radius:0}.panel>.list-group .list-group-item:last-child{border-bottom:0}.panel-heading+.list-group .list-group-item:first-child{border-top-width:0}.panel>.table,.panel>.table-responsive>.table{margin-bottom:0}.panel>.panel-body+.table,.panel>.panel-body+.table-responsive{border-top:1px solid #ddd}.panel>.table>tbody:first-child th,.panel>.table>tbody:first-child td{border-top:0}.panel>.table-bordered,.panel>.table-responsive>.table-bordered{border:0}.panel>.table-bordered>thead>tr>th:first-child,.panel>.table-responsive>.table-bordered>thead>tr>th:first-child,.panel>.table-bordered>tbody>tr>th:first-child,.panel>.table-responsive>.table-bordered>tbody>tr>th:first-child,.panel>.table-bordered>tfoot>tr>th:first-child,.panel>.table-responsive>.table-bordered>tfoot>tr>th:first-child,.panel>.table-bordered>thead>tr>td:first-child,.panel>.table-responsive>.table-bordered>thead>tr>td:first-child,.panel>.table-bordered>tbody>tr>td:first-child,.panel>.table-responsive>.table-bordered>tbody>tr>td:first-child,.panel>.table-bordered>tfoot>tr>td:first-child,.panel>.table-responsive>.table-bordered>tfoot>tr>td:first-child{border-left:0}.panel>.table-bordered>thead>tr>th:last-child,.panel>.table-responsive>.table-bordered>thead>tr>th:last-child,.panel>.table-bordered>tbody>tr>th:last-child,.panel>.table-responsive>.table-bordered>tbody>tr>th:last-child,.panel>.table-bordered>tfoot>tr>th:last-child,.panel>.table-responsive>.table-bordered>tfoot>tr>th:last-child,.panel>.table-bordered>thead>tr>td:last-child,.panel>.table-responsive>.table-bordered>thead>tr>td:last-child,.panel>.table-bordered>tbody>tr>td:last-child,.panel>.table-responsive>.table-bordered>tbody>tr>td:last-child,.panel>.table-bordered>tfoot>tr>td:last-child,.panel>.table-responsive>.table-bordered>tfoot>tr>td:last-child{border-right:0}.panel>.table-bordered>thead>tr:last-child>th,.panel>.table-responsive>.table-bordered>thead>tr:last-child>th,.panel>.table-bordered>tbody>tr:last-child>th,.panel>.table-responsive>.table-bordered>tbody>tr:last-child>th,.panel>.table-bordered>tfoot>tr:last-child>th,.panel>.table-responsive>.table-bordered>tfoot>tr:last-child>th,.panel>.table-bordered>thead>tr:last-child>td,.panel>.table-responsive>.table-bordered>thead>tr:last-child>td,.panel>.table-bordered>tbody>tr:last-child>td,.panel>.table-responsive>.table-bordered>tbody>tr:last-child>td,.panel>.table-bordered>tfoot>tr:last-child>td,.panel>.table-responsive>.table-bordered>tfoot>tr:last-child>td{border-bottom:0}.panel>.table-responsive{margin-bottom:0;border:0}.panel-heading{padding:10px 15px;border-bottom:1px solid transparent;border-top-right-radius:3px;border-top-left-radius:3px}.panel-heading>.dropdown .dropdown-toggle{color:inherit}.panel-title{margin-top:0;margin-bottom:0;font-size:16px;color:inherit}.panel-title>a{color:inherit}.panel-footer{padding:10px 15px;background-color:#f5f5f5;border-top:1px solid #ddd;border-bottom-right-radius:3px;border-bottom-left-radius:3px}.panel-group .panel{margin-bottom:0;overflow:hidden;border-radius:4px}.panel-group .panel+.panel{margin-top:5px}.panel-group .panel-heading{border-bottom:0}.panel-group .panel-heading+.panel-collapse .panel-body{border-top:1px solid #ddd}.panel-group .panel-footer{border-top:0}.panel-group .panel-footer+.panel-collapse .panel-body{border-bottom:1px solid #ddd}.panel-default{border-color:#ddd}.panel-default>.panel-heading{color:#333;background-color:#f5f5f5;border-color:#ddd}.panel-default>.panel-heading+.panel-collapse .panel-body{border-top-color:#ddd}.panel-default>.panel-footer+.panel-collapse .panel-body{border-bottom-color:#ddd}.panel-primary{border-color:#428bca}.panel-primary>.panel-heading{color:#fff;background-color:#428bca;border-color:#428bca}.panel-primary>.panel-heading+.panel-collapse .panel-body{border-top-color:#428bca}.panel-primary>.panel-footer+.panel-collapse .panel-body{border-bottom-color:#428bca}.panel-success{border-color:#d6e9c6}.panel-success>.panel-heading{color:#3c763d;background-color:#dff0d8;border-color:#d6e9c6}.panel-success>.panel-heading+.panel-collapse .panel-body{border-top-color:#d6e9c6}.panel-success>.panel-footer+.panel-collapse .panel-body{border-bottom-color:#d6e9c6}.panel-warning{border-color:#faebcc}.panel-warning>.panel-heading{color:#8a6d3b;background-color:#fcf8e3;border-color:#faebcc}.panel-warning>.panel-heading+.panel-collapse .panel-body{border-top-color:#faebcc}.panel-warning>.panel-footer+.panel-collapse .panel-body{border-bottom-color:#faebcc}.panel-danger{border-color:#ebccd1}.panel-danger>.panel-heading{color:#a94442;background-color:#f2dede;border-color:#ebccd1}.panel-danger>.panel-heading+.panel-collapse .panel-body{border-top-color:#ebccd1}.panel-danger>.panel-footer+.panel-collapse .panel-body{border-bottom-color:#ebccd1}.panel-info{border-color:#bce8f1}.panel-info>.panel-heading{color:#31708f;background-color:#d9edf7;border-color:#bce8f1}.panel-info>.panel-heading+.panel-collapse .panel-body{border-top-color:#bce8f1}.panel-info>.panel-footer+.panel-collapse .panel-body{border-bottom-color:#bce8f1}.well{min-height:20px;padding:19px;margin-bottom:20px;background-color:#f5f5f5;border:1px solid #e3e3e3;border-radius:4px;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.05);box-shadow:inset 0 1px 1px rgba(0,0,0,0.05)}.well blockquote{border-color:#ddd;border-color:rgba(0,0,0,0.15)}.well-lg{padding:24px;border-radius:6px}.well-sm{padding:9px;border-radius:3px}.close{float:right;font-size:21px;font-weight:bold;line-height:1;color:#000;text-shadow:0 1px 0 #fff;opacity:.2;filter:alpha(opacity=20)}.close:hover,.close:focus{color:#000;text-decoration:none;cursor:pointer;opacity:.5;filter:alpha(opacity=50)}button.close{padding:0;cursor:pointer;background:transparent;border:0;-webkit-appearance:none}.modal-open{overflow:hidden}.modal{position:fixed;top:0;right:0;bottom:0;left:0;z-index:1040;display:none;overflow:auto;overflow-y:scroll}.modal.fade .modal-dialog{-webkit-transform:translate(0,-25%);-ms-transform:translate(0,-25%);transform:translate(0,-25%);-webkit-transition:-webkit-transform .3s ease-out;-moz-transition:-moz-transform .3s ease-out;-o-transition:-o-transform .3s ease-out;transition:transform .3s ease-out}.modal.in .modal-dialog{-webkit-transform:translate(0,0);-ms-transform:translate(0,0);transform:translate(0,0)}.modal-dialog{position:relative;z-index:1050;width:auto;margin:10px}.modal-content{position:relative;background-color:#fff;border:1px solid #999;border:1px solid rgba(0,0,0,0.2);border-radius:6px;outline:0;-webkit-box-shadow:0 3px 9px rgba(0,0,0,0.5);box-shadow:0 3px 9px rgba(0,0,0,0.5);background-clip:padding-box}.modal-backdrop{position:fixed;top:0;right:0;bottom:0;left:0;z-index:1030;background-color:#000}.modal-backdrop.fade{opacity:0;filter:alpha(opacity=0)}.modal-backdrop.in{opacity:.5;filter:alpha(opacity=50)}.modal-header{min-height:16.428571429px;padding:15px;border-bottom:1px solid #e5e5e5}.modal-header .close{margin-top:-2px}.modal-title{margin:0;line-height:1.428571429}.modal-body{position:relative;padding:20px}.modal-footer{padding:19px 20px 20px;margin-top:15px;text-align:right;border-top:1px solid #e5e5e5}.modal-footer:before,.modal-footer:after{display:table;content:" "}.modal-footer:after{clear:both}.modal-footer:before,.modal-footer:after{display:table;content:" "}.modal-footer:after{clear:both}.modal-footer .btn+.btn{margin-bottom:0;margin-left:5px}.modal-footer .btn-group .btn+.btn{margin-left:-1px}.modal-footer .btn-block+.btn-block{margin-left:0}@media screen and (min-width:768px){.modal-dialog{width:600px;margin:30px auto}.modal-content{-webkit-box-shadow:0 5px 15px rgba(0,0,0,0.5);box-shadow:0 5px 15px rgba(0,0,0,0.5)}}.tooltip{position:absolute;z-index:1030;display:block;font-size:12px;line-height:1.4;opacity:0;filter:alpha(opacity=0);visibility:visible}.tooltip.in{opacity:.9;filter:alpha(opacity=90)}.tooltip.top{padding:5px 0;margin-top:-3px}.tooltip.right{padding:0 5px;margin-left:3px}.tooltip.bottom{padding:5px 0;margin-top:3px}.tooltip.left{padding:0 5px;margin-left:-3px}.tooltip-inner{max-width:200px;padding:3px 8px;color:#fff;text-align:center;text-decoration:none;background-color:#000;border-radius:4px}.tooltip-arrow{position:absolute;width:0;height:0;border-color:transparent;border-style:solid}.tooltip.top .tooltip-arrow{bottom:0;left:50%;margin-left:-5px;border-top-color:#000;border-width:5px 5px 0}.tooltip.top-left .tooltip-arrow{bottom:0;left:5px;border-top-color:#000;border-width:5px 5px 0}.tooltip.top-right .tooltip-arrow{right:5px;bottom:0;border-top-color:#000;border-width:5px 5px 0}.tooltip.right .tooltip-arrow{top:50%;left:0;margin-top:-5px;border-right-color:#000;border-width:5px 5px 5px 0}.tooltip.left .tooltip-arrow{top:50%;right:0;margin-top:-5px;border-left-color:#000;border-width:5px 0 5px 5px}.tooltip.bottom .tooltip-arrow{top:0;left:50%;margin-left:-5px;border-bottom-color:#000;border-width:0 5px 5px}.tooltip.bottom-left .tooltip-arrow{top:0;left:5px;border-bottom-color:#000;border-width:0 5px 5px}.tooltip.bottom-right .tooltip-arrow{top:0;right:5px;border-bottom-color:#000;border-width:0 5px 5px}.popover{position:absolute;top:0;left:0;z-index:1010;display:none;max-width:276px;padding:1px;text-align:left;white-space:normal;background-color:#fff;border:1px solid #ccc;border:1px solid rgba(0,0,0,0.2);border-radius:6px;-webkit-box-shadow:0 5px 10px rgba(0,0,0,0.2);box-shadow:0 5px 10px rgba(0,0,0,0.2);background-clip:padding-box}.popover.top{margin-top:-10px}.popover.right{margin-left:10px}.popover.bottom{margin-top:10px}.popover.left{margin-left:-10px}.popover-title{padding:8px 14px;margin:0;font-size:14px;font-weight:normal;line-height:18px;background-color:#f7f7f7;border-bottom:1px solid #ebebeb;border-radius:5px 5px 0 0}.popover-content{padding:9px 14px}.popover .arrow,.popover .arrow:after{position:absolute;display:block;width:0;height:0;border-color:transparent;border-style:solid}.popover .arrow{border-width:11px}.popover .arrow:after{border-width:10px;content:""}.popover.top .arrow{bottom:-11px;left:50%;margin-left:-11px;border-top-color:#999;border-top-color:rgba(0,0,0,0.25);border-bottom-width:0}.popover.top .arrow:after{bottom:1px;margin-left:-10px;border-top-color:#fff;border-bottom-width:0;content:" "}.popover.right .arrow{top:50%;left:-11px;margin-top:-11px;border-right-color:#999;border-right-color:rgba(0,0,0,0.25);border-left-width:0}.popover.right .arrow:after{bottom:-10px;left:1px;border-right-color:#fff;border-left-width:0;content:" "}.popover.bottom .arrow{top:-11px;left:50%;margin-left:-11px;border-bottom-color:#999;border-bottom-color:rgba(0,0,0,0.25);border-top-width:0}.popover.bottom .arrow:after{top:1px;margin-left:-10px;border-bottom-color:#fff;border-top-width:0;content:" "}.popover.left .arrow{top:50%;right:-11px;margin-top:-11px;border-left-color:#999;border-left-color:rgba(0,0,0,0.25);border-right-width:0}.popover.left .arrow:after{right:1px;bottom:-10px;border-left-color:#fff;border-right-width:0;content:" "}.carousel{position:relative}.carousel-inner{position:relative;width:100%;overflow:hidden}.carousel-inner>.item{position:relative;display:none;-webkit-transition:.6s ease-in-out left;transition:.6s ease-in-out left}.carousel-inner>.item>img,.carousel-inner>.item>a>img{display:block;height:auto;max-width:100%;line-height:1}.carousel-inner>.active,.carousel-inner>.next,.carousel-inner>.prev{display:block}.carousel-inner>.active{left:0}.carousel-inner>.next,.carousel-inner>.prev{position:absolute;top:0;width:100%}.carousel-inner>.next{left:100%}.carousel-inner>.prev{left:-100%}.carousel-inner>.next.left,.carousel-inner>.prev.right{left:0}.carousel-inner>.active.left{left:-100%}.carousel-inner>.active.right{left:100%}.carousel-control{position:absolute;top:0;bottom:0;left:0;width:15%;font-size:20px;color:#fff;text-align:center;text-shadow:0 1px 2px rgba(0,0,0,0.6);opacity:.5;filter:alpha(opacity=50)}.carousel-control.left{background-image:-webkit-linear-gradient(left,color-stop(rgba(0,0,0,0.5) 0),color-stop(rgba(0,0,0,0.0001) 100%));background-image:linear-gradient(to right,rgba(0,0,0,0.5) 0,rgba(0,0,0,0.0001) 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#80000000',endColorstr='#00000000',GradientType=1)}.carousel-control.right{right:0;left:auto;background-image:-webkit-linear-gradient(left,color-stop(rgba(0,0,0,0.0001) 0),color-stop(rgba(0,0,0,0.5) 100%));background-image:linear-gradient(to right,rgba(0,0,0,0.0001) 0,rgba(0,0,0,0.5) 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#00000000',endColorstr='#80000000',GradientType=1)}.carousel-control:hover,.carousel-control:focus{color:#fff;text-decoration:none;outline:0;opacity:.9;filter:alpha(opacity=90)}.carousel-control .icon-prev,.carousel-control .icon-next,.carousel-control .glyphicon-chevron-left,.carousel-control .glyphicon-chevron-right{position:absolute;top:50%;z-index:5;display:inline-block}.carousel-control .icon-prev,.carousel-control .glyphicon-chevron-left{left:50%}.carousel-control .icon-next,.carousel-control .glyphicon-chevron-right{right:50%}.carousel-control .icon-prev,.carousel-control .icon-next{width:20px;height:20px;margin-top:-10px;margin-left:-10px;font-family:serif}.carousel-control .icon-prev:before{content:'\2039'}.carousel-control .icon-next:before{content:'\203a'}.carousel-indicators{position:absolute;bottom:10px;left:50%;z-index:15;width:60%;padding-left:0;margin-left:-30%;text-align:center;list-style:none}.carousel-indicators li{display:inline-block;width:10px;height:10px;margin:1px;text-indent:-999px;cursor:pointer;background-color:#000 \9;background-color:rgba(0,0,0,0);border:1px solid #fff;border-radius:10px}.carousel-indicators .active{width:12px;height:12px;margin:0;background-color:#fff}.carousel-caption{position:absolute;right:15%;bottom:20px;left:15%;z-index:10;padding-top:20px;padding-bottom:20px;color:#fff;text-align:center;text-shadow:0 1px 2px rgba(0,0,0,0.6)}.carousel-caption .btn{text-shadow:none}@media screen and (min-width:768px){.carousel-control .glyphicons-chevron-left,.carousel-control .glyphicons-chevron-right,.carousel-control .icon-prev,.carousel-control .icon-next{width:30px;height:30px;margin-top:-15px;margin-left:-15px;font-size:30px}.carousel-caption{right:20%;left:20%;padding-bottom:30px}.carousel-indicators{bottom:20px}}.clearfix:before,.clearfix:after{display:table;content:" "}.clearfix:after{clear:both}.center-block{display:block;margin-right:auto;margin-left:auto}.pull-right{float:right!important}.pull-left{float:left!important}.hide{display:none!important}.show{display:block!important}.invisible{visibility:hidden}.text-hide{font:0/0 a;color:transparent;text-shadow:none;background-color:transparent;border:0}.hidden{display:none!important;visibility:hidden!important}.affix{position:fixed}@-ms-viewport{width:device-width}.visible-xs,tr.visible-xs,th.visible-xs,td.visible-xs{display:none!important}@media(max-width:767px){.visible-xs{display:block!important}table.visible-xs{display:table}tr.visible-xs{display:table-row!important}th.visible-xs,td.visible-xs{display:table-cell!important}}@media(min-width:768px) and (max-width:991px){.visible-xs.visible-sm{display:block!important}table.visible-xs.visible-sm{display:table}tr.visible-xs.visible-sm{display:table-row!important}th.visible-xs.visible-sm,td.visible-xs.visible-sm{display:table-cell!important}}@media(min-width:992px) and (max-width:1199px){.visible-xs.visible-md{display:block!important}table.visible-xs.visible-md{display:table}tr.visible-xs.visible-md{display:table-row!important}th.visible-xs.visible-md,td.visible-xs.visible-md{display:table-cell!important}}@media(min-width:1200px){.visible-xs.visible-lg{display:block!important}table.visible-xs.visible-lg{display:table}tr.visible-xs.visible-lg{display:table-row!important}th.visible-xs.visible-lg,td.visible-xs.visible-lg{display:table-cell!important}}.visible-sm,tr.visible-sm,th.visible-sm,td.visible-sm{display:none!important}@media(max-width:767px){.visible-sm.visible-xs{display:block!important}table.visible-sm.visible-xs{display:table}tr.visible-sm.visible-xs{display:table-row!important}th.visible-sm.visible-xs,td.visible-sm.visible-xs{display:table-cell!important}}@media(min-width:768px) and (max-width:991px){.visible-sm{display:block!important}table.visible-sm{display:table}tr.visible-sm{display:table-row!important}th.visible-sm,td.visible-sm{display:table-cell!important}}@media(min-width:992px) and (max-width:1199px){.visible-sm.visible-md{display:block!important}table.visible-sm.visible-md{display:table}tr.visible-sm.visible-md{display:table-row!important}th.visible-sm.visible-md,td.visible-sm.visible-md{display:table-cell!important}}@media(min-width:1200px){.visible-sm.visible-lg{display:block!important}table.visible-sm.visible-lg{display:table}tr.visible-sm.visible-lg{display:table-row!important}th.visible-sm.visible-lg,td.visible-sm.visible-lg{display:table-cell!important}}.visible-md,tr.visible-md,th.visible-md,td.visible-md{display:none!important}@media(max-width:767px){.visible-md.visible-xs{display:block!important}table.visible-md.visible-xs{display:table}tr.visible-md.visible-xs{display:table-row!important}th.visible-md.visible-xs,td.visible-md.visible-xs{display:table-cell!important}}@media(min-width:768px) and (max-width:991px){.visible-md.visible-sm{display:block!important}table.visible-md.visible-sm{display:table}tr.visible-md.visible-sm{display:table-row!important}th.visible-md.visible-sm,td.visible-md.visible-sm{display:table-cell!important}}@media(min-width:992px) and (max-width:1199px){.visible-md{display:block!important}table.visible-md{display:table}tr.visible-md{display:table-row!important}th.visible-md,td.visible-md{display:table-cell!important}}@media(min-width:1200px){.visible-md.visible-lg{display:block!important}table.visible-md.visible-lg{display:table}tr.visible-md.visible-lg{display:table-row!important}th.visible-md.visible-lg,td.visible-md.visible-lg{display:table-cell!important}}.visible-lg,tr.visible-lg,th.visible-lg,td.visible-lg{display:none!important}@media(max-width:767px){.visible-lg.visible-xs{display:block!important}table.visible-lg.visible-xs{display:table}tr.visible-lg.visible-xs{display:table-row!important}th.visible-lg.visible-xs,td.visible-lg.visible-xs{display:table-cell!important}}@media(min-width:768px) and (max-width:991px){.visible-lg.visible-sm{display:block!important}table.visible-lg.visible-sm{display:table}tr.visible-lg.visible-sm{display:table-row!important}th.visible-lg.visible-sm,td.visible-lg.visible-sm{display:table-cell!important}}@media(min-width:992px) and (max-width:1199px){.visible-lg.visible-md{display:block!important}table.visible-lg.visible-md{display:table}tr.visible-lg.visible-md{display:table-row!important}th.visible-lg.visible-md,td.visible-lg.visible-md{display:table-cell!important}}@media(min-width:1200px){.visible-lg{display:block!important}table.visible-lg{display:table}tr.visible-lg{display:table-row!important}th.visible-lg,td.visible-lg{display:table-cell!important}}.hidden-xs{display:block!important}table.hidden-xs{display:table}tr.hidden-xs{display:table-row!important}th.hidden-xs,td.hidden-xs{display:table-cell!important}@media(max-width:767px){.hidden-xs,tr.hidden-xs,th.hidden-xs,td.hidden-xs{display:none!important}}@media(min-width:768px) and (max-width:991px){.hidden-xs.hidden-sm,tr.hidden-xs.hidden-sm,th.hidden-xs.hidden-sm,td.hidden-xs.hidden-sm{display:none!important}}@media(min-width:992px) and (max-width:1199px){.hidden-xs.hidden-md,tr.hidden-xs.hidden-md,th.hidden-xs.hidden-md,td.hidden-xs.hidden-md{display:none!important}}@media(min-width:1200px){.hidden-xs.hidden-lg,tr.hidden-xs.hidden-lg,th.hidden-xs.hidden-lg,td.hidden-xs.hidden-lg{display:none!important}}.hidden-sm{display:block!important}table.hidden-sm{display:table}tr.hidden-sm{display:table-row!important}th.hidden-sm,td.hidden-sm{display:table-cell!important}@media(max-width:767px){.hidden-sm.hidden-xs,tr.hidden-sm.hidden-xs,th.hidden-sm.hidden-xs,td.hidden-sm.hidden-xs{display:none!important}}@media(min-width:768px) and (max-width:991px){.hidden-sm,tr.hidden-sm,th.hidden-sm,td.hidden-sm{display:none!important}}@media(min-width:992px) and (max-width:1199px){.hidden-sm.hidden-md,tr.hidden-sm.hidden-md,th.hidden-sm.hidden-md,td.hidden-sm.hidden-md{display:none!important}}@media(min-width:1200px){.hidden-sm.hidden-lg,tr.hidden-sm.hidden-lg,th.hidden-sm.hidden-lg,td.hidden-sm.hidden-lg{display:none!important}}.hidden-md{display:block!important}table.hidden-md{display:table}tr.hidden-md{display:table-row!important}th.hidden-md,td.hidden-md{display:table-cell!important}@media(max-width:767px){.hidden-md.hidden-xs,tr.hidden-md.hidden-xs,th.hidden-md.hidden-xs,td.hidden-md.hidden-xs{display:none!important}}@media(min-width:768px) and (max-width:991px){.hidden-md.hidden-sm,tr.hidden-md.hidden-sm,th.hidden-md.hidden-sm,td.hidden-md.hidden-sm{display:none!important}}@media(min-width:992px) and (max-width:1199px){.hidden-md,tr.hidden-md,th.hidden-md,td.hidden-md{display:none!important}}@media(min-width:1200px){.hidden-md.hidden-lg,tr.hidden-md.hidden-lg,th.hidden-md.hidden-lg,td.hidden-md.hidden-lg{display:none!important}}.hidden-lg{display:block!important}table.hidden-lg{display:table}tr.hidden-lg{display:table-row!important}th.hidden-lg,td.hidden-lg{display:table-cell!important}@media(max-width:767px){.hidden-lg.hidden-xs,tr.hidden-lg.hidden-xs,th.hidden-lg.hidden-xs,td.hidden-lg.hidden-xs{display:none!important}}@media(min-width:768px) and (max-width:991px){.hidden-lg.hidden-sm,tr.hidden-lg.hidden-sm,th.hidden-lg.hidden-sm,td.hidden-lg.hidden-sm{display:none!important}}@media(min-width:992px) and (max-width:1199px){.hidden-lg.hidden-md,tr.hidden-lg.hidden-md,th.hidden-lg.hidden-md,td.hidden-lg.hidden-md{display:none!important}}@media(min-width:1200px){.hidden-lg,tr.hidden-lg,th.hidden-lg,td.hidden-lg{display:none!important}}.visible-print,tr.visible-print,th.visible-print,td.visible-print{display:none!important}@media print{.visible-print{display:block!important}table.visible-print{display:table}tr.visible-print{display:table-row!important}th.visible-print,td.visible-print{display:table-cell!important}.hidden-print,tr.hidden-print,th.hidden-print,td.hidden-print{display:none!important}}
\ No newline at end of file
diff --git a/contrib/gnunet-arch-full.svg b/contrib/gnunet-arch-full.svg
new file mode 100644
index 0000000000000000000000000000000000000000..766f2b855454443966b2e92ffa6b24d6852c4fdc
--- /dev/null
+++ b/contrib/gnunet-arch-full.svg
@@ -0,0 +1,648 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
+ "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<!-- Generated by graphviz version 2.38.0 (20140413.2041)
+ -->
+<!-- Title: dependencies Pages: 1 -->
+<svg width="1277pt" height="836pt"
+ viewBox="0.00 0.00 1276.81 836.00" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
+<g id="graph0" class="graph" transform="scale(1 1) rotate(0) translate(4 832)">
+<title>dependencies</title>
+<polygon fill="white" stroke="none" points="-4,4 -4,-832 1272.81,-832 1272.81,4 -4,4"/>
+<!-- voting -->
+<g id="node1" class="node"><title>voting</title>
+<polygon fill="none" stroke="black" points="120.944,-743.562 80,-756 39.0559,-743.562 39.0942,-723.438 120.906,-723.438 120.944,-743.562"/>
+<text text-anchor="middle" x="80" y="-734.3" font-family="Times,serif" font-size="14.00">voting</text>
+</g>
+<!-- consensus -->
+<g id="node2" class="node"><title>consensus</title>
+<ellipse fill="none" stroke="black" cx="112" cy="-594" rx="46.2923" ry="18"/>
+<text text-anchor="middle" x="112" y="-590.3" font-family="Times,serif" font-size="14.00">consensus</text>
+</g>
+<!-- voting&#45;&gt;consensus -->
+<g id="edge1" class="edge"><title>voting&#45;&gt;consensus</title>
+<path fill="none" stroke="black" d="M121.028,-728.482C145.315,-721.103 174.155,-707.724 189,-684 197.487,-670.436 196.445,-662.162 189,-648 180.933,-632.654 166.19,-620.887 151.748,-612.383"/>
+<polygon fill="black" stroke="black" points="153.308,-609.247 142.857,-607.508 149.942,-615.385 153.308,-609.247"/>
+</g>
+<!-- identity -->
+<g id="node3" class="node"><title>identity</title>
+<ellipse fill="none" stroke="black" cx="282" cy="-450" rx="37.8943" ry="18"/>
+<text text-anchor="middle" x="282" y="-446.3" font-family="Times,serif" font-size="14.00">identity</text>
+</g>
+<!-- voting&#45;&gt;identity -->
+<g id="edge2" class="edge"><title>voting&#45;&gt;identity</title>
+<path fill="none" stroke="black" d="M58.5145,-723.377C45.8789,-714.02 31.0387,-700.353 24,-684 5.02284,-639.911 -2.50901,-616.016 24,-576 46.6577,-541.798 71.8444,-557.396 109,-540 158.351,-516.894 214.207,-487.564 248.77,-469.032"/>
+<polygon fill="black" stroke="black" points="250.781,-471.924 257.931,-464.105 247.466,-465.759 250.781,-471.924"/>
+</g>
+<!-- cadet -->
+<g id="node4" class="node"><title>cadet</title>
+<ellipse fill="none" stroke="black" cx="538" cy="-450" rx="29.4969" ry="18"/>
+<text text-anchor="middle" x="538" y="-446.3" font-family="Times,serif" font-size="14.00">cadet</text>
+</g>
+<!-- voting&#45;&gt;cadet -->
+<g id="edge3" class="edge"><title>voting&#45;&gt;cadet</title>
+<path fill="none" stroke="black" d="M72.0051,-723.243C55.682,-693.149 22.8306,-620.604 57,-576 70.8829,-557.877 390.653,-484.265 500.977,-459.316"/>
+<polygon fill="black" stroke="black" points="501.999,-462.673 510.983,-457.057 500.458,-455.845 501.999,-462.673"/>
+</g>
+<!-- secretsharing -->
+<g id="node5" class="node"><title>secretsharing</title>
+<ellipse fill="none" stroke="black" cx="123" cy="-666" rx="57.3905" ry="18"/>
+<text text-anchor="middle" x="123" y="-662.3" font-family="Times,serif" font-size="14.00">secretsharing</text>
+</g>
+<!-- voting&#45;&gt;secretsharing -->
+<g id="edge4" class="edge"><title>voting&#45;&gt;secretsharing</title>
+<path fill="none" stroke="black" d="M88.4954,-723.17C93.8716,-714.418 100.986,-702.837 107.357,-692.466"/>
+<polygon fill="black" stroke="black" points="110.45,-694.117 112.702,-683.764 104.486,-690.453 110.45,-694.117"/>
+</g>
+<!-- consensus&#45;&gt;cadet -->
+<g id="edge72" class="edge"><title>consensus&#45;&gt;cadet</title>
+<path fill="none" stroke="black" d="M146.507,-581.905C153.275,-579.85 160.34,-577.79 167,-576 236.135,-557.417 256.193,-562.96 324,-540 360.547,-527.625 367.474,-519.056 403,-504 437.068,-489.562 476.509,-474.236 503.927,-463.798"/>
+<polygon fill="black" stroke="black" points="505.344,-467.004 513.453,-460.185 502.862,-460.459 505.344,-467.004"/>
+</g>
+<!-- set -->
+<g id="node24" class="node"><title>set</title>
+<ellipse fill="none" stroke="black" cx="517" cy="-522" rx="27" ry="18"/>
+<text text-anchor="middle" x="517" y="-518.3" font-family="Times,serif" font-size="14.00">set</text>
+</g>
+<!-- consensus&#45;&gt;set -->
+<g id="edge71" class="edge"><title>consensus&#45;&gt;set</title>
+<path fill="none" stroke="black" d="M145.818,-581.678C152.772,-579.596 160.083,-577.583 167,-576 182.24,-572.511 394.44,-541.075 480.815,-528.33"/>
+<polygon fill="black" stroke="black" points="481.561,-531.758 490.943,-526.837 480.539,-524.833 481.561,-531.758"/>
+</g>
+<!-- dht -->
+<g id="node7" class="node"><title>dht</title>
+<ellipse fill="none" stroke="black" cx="756" cy="-378" rx="27" ry="18"/>
+<text text-anchor="middle" x="756" y="-374.3" font-family="Times,serif" font-size="14.00">dht</text>
+</g>
+<!-- cadet&#45;&gt;dht -->
+<g id="edge51" class="edge"><title>cadet&#45;&gt;dht</title>
+<path fill="none" stroke="black" d="M563.434,-440.833C602.822,-428.186 678.592,-403.856 722.428,-389.78"/>
+<polygon fill="black" stroke="black" points="723.607,-393.078 732.058,-386.688 721.467,-386.413 723.607,-393.078"/>
+</g>
+<!-- core -->
+<g id="node8" class="node"><title>core</title>
+<ellipse fill="none" stroke="black" cx="555" cy="-234" rx="27" ry="18"/>
+<text text-anchor="middle" x="555" y="-230.3" font-family="Times,serif" font-size="14.00">core</text>
+</g>
+<!-- cadet&#45;&gt;core -->
+<g id="edge50" class="edge"><title>cadet&#45;&gt;core</title>
+<path fill="none" stroke="black" d="M539.362,-431.849C542.303,-394.832 549.266,-307.181 552.824,-262.386"/>
+<polygon fill="black" stroke="black" points="556.328,-262.478 553.631,-252.232 549.35,-261.924 556.328,-262.478"/>
+</g>
+<!-- block -->
+<g id="node11" class="node"><title>block</title>
+<polygon fill="none" stroke="black" points="429,-324 385.598,-306 429,-288 472.402,-306 429,-324"/>
+<text text-anchor="middle" x="429" y="-302.3" font-family="Times,serif" font-size="14.00">block</text>
+</g>
+<!-- cadet&#45;&gt;block -->
+<g id="edge52" class="edge"><title>cadet&#45;&gt;block</title>
+<path fill="none" stroke="blue" stroke-dasharray="1,5" d="M522.106,-434.467C511.33,-424.227 497.085,-409.913 486,-396 469.058,-374.736 452.633,-348.272 441.802,-329.75"/>
+<polygon fill="blue" stroke="blue" points="444.702,-327.773 436.674,-320.859 438.638,-331.27 444.702,-327.773"/>
+</g>
+<!-- secretsharing&#45;&gt;consensus -->
+<g id="edge5" class="edge"><title>secretsharing&#45;&gt;consensus</title>
+<path fill="none" stroke="black" d="M120.281,-647.697C119.069,-639.983 117.612,-630.712 116.261,-622.112"/>
+<polygon fill="black" stroke="black" points="119.698,-621.44 114.688,-612.104 112.783,-622.526 119.698,-621.44"/>
+</g>
+<!-- fs -->
+<g id="node6" class="node"><title>fs</title>
+<polygon fill="none" stroke="black" points="100,-527.562 73,-540 46,-527.562 46.0252,-507.438 99.9748,-507.438 100,-527.562"/>
+<text text-anchor="middle" x="73" y="-518.3" font-family="Times,serif" font-size="14.00">fs</text>
+</g>
+<!-- fs&#45;&gt;identity -->
+<g id="edge12" class="edge"><title>fs&#45;&gt;identity</title>
+<path fill="none" stroke="black" d="M100.21,-509.307C104.786,-507.46 109.507,-505.625 114,-504 164.764,-485.643 178.566,-484.387 230,-468 233.971,-466.735 238.108,-465.404 242.237,-464.067"/>
+<polygon fill="black" stroke="black" points="243.351,-467.386 251.778,-460.965 241.186,-460.729 243.351,-467.386"/>
+</g>
+<!-- fs&#45;&gt;cadet -->
+<g id="edge9" class="edge"><title>fs&#45;&gt;cadet</title>
+<path fill="none" stroke="black" d="M100.01,-516.934C178.772,-505.077 408.387,-470.512 499.803,-456.75"/>
+<polygon fill="black" stroke="black" points="500.372,-460.204 509.74,-455.254 499.33,-453.282 500.372,-460.204"/>
+</g>
+<!-- fs&#45;&gt;dht -->
+<g id="edge6" class="edge"><title>fs&#45;&gt;dht</title>
+<path fill="none" stroke="black" d="M100.081,-509.411C132.571,-495.433 183.726,-473.164 192,-468 213.144,-454.802 212.035,-441.688 235,-432 322.67,-395.017 615.27,-383.079 719.081,-379.955"/>
+<polygon fill="black" stroke="black" points="719.199,-383.453 729.093,-379.664 718.996,-376.456 719.199,-383.453"/>
+</g>
+<!-- fs&#45;&gt;core -->
+<g id="edge7" class="edge"><title>fs&#45;&gt;core</title>
+<path fill="none" stroke="black" d="M65.0877,-507.277C55.5997,-488.827 42.6595,-455.618 57,-432 93.0072,-372.699 269.007,-312.27 334,-288 397.135,-264.424 474.404,-248.714 518.841,-240.869"/>
+<polygon fill="black" stroke="black" points="519.614,-244.287 528.871,-239.134 518.42,-237.39 519.614,-244.287"/>
+</g>
+<!-- datastore -->
+<g id="node9" class="node"><title>datastore</title>
+<ellipse fill="none" stroke="black" cx="108" cy="-450" rx="42.4939" ry="18"/>
+<text text-anchor="middle" x="108" y="-446.3" font-family="Times,serif" font-size="14.00">datastore</text>
+</g>
+<!-- fs&#45;&gt;datastore -->
+<g id="edge8" class="edge"><title>fs&#45;&gt;datastore</title>
+<path fill="none" stroke="black" d="M79.9149,-507.17C84.2467,-498.507 89.9645,-487.071 95.1098,-476.78"/>
+<polygon fill="black" stroke="black" points="98.2763,-478.274 99.618,-467.764 92.0153,-475.143 98.2763,-478.274"/>
+</g>
+<!-- ats -->
+<g id="node10" class="node"><title>ats</title>
+<ellipse fill="none" stroke="black" cx="385" cy="-90" rx="27" ry="18"/>
+<text text-anchor="middle" x="385" y="-86.3" font-family="Times,serif" font-size="14.00">ats</text>
+</g>
+<!-- fs&#45;&gt;ats -->
+<g id="edge10" class="edge"><title>fs&#45;&gt;ats</title>
+<path fill="none" stroke="black" d="M60.2844,-507.296C39.3694,-483.267 0,-431.113 0,-379 0,-379 0,-379 0,-233 0,-159.097 252.872,-111.714 348.742,-96.4063"/>
+<polygon fill="black" stroke="black" points="349.504,-99.8296 358.84,-94.8203 348.418,-92.9144 349.504,-99.8296"/>
+</g>
+<!-- fs&#45;&gt;block -->
+<g id="edge11" class="edge"><title>fs&#45;&gt;block</title>
+<path fill="none" stroke="blue" stroke-dasharray="1,5" d="M99.0792,-507.426C116.81,-497.613 140.343,-483.417 159,-468 175.732,-454.174 174.815,-445.258 192,-432 259.224,-380.139 351.062,-338.689 398.245,-319.166"/>
+<polygon fill="blue" stroke="blue" points="399.679,-322.361 407.611,-315.337 397.03,-315.881 399.679,-322.361"/>
+</g>
+<!-- dht&#45;&gt;core -->
+<g id="edge42" class="edge"><title>dht&#45;&gt;core</title>
+<path fill="none" stroke="black" d="M780.722,-370.233C802.496,-362.816 832.877,-348.569 847,-324 854.974,-310.128 857.48,-300.09 847,-288 810.092,-245.421 650.341,-266.908 596,-252 592.628,-251.075 589.164,-249.944 585.745,-248.709"/>
+<polygon fill="black" stroke="black" points="586.936,-245.416 576.348,-245.037 584.388,-251.936 586.936,-245.416"/>
+</g>
+<!-- dht&#45;&gt;block -->
+<g id="edge44" class="edge"><title>dht&#45;&gt;block</title>
+<path fill="none" stroke="black" d="M730.132,-372.774C681.84,-364.697 574.817,-345.908 486,-324 478.104,-322.052 469.673,-319.694 461.782,-317.363"/>
+<polygon fill="black" stroke="black" points="462.742,-313.997 452.157,-314.456 460.718,-320.698 462.742,-313.997"/>
+</g>
+<!-- nse -->
+<g id="node27" class="node"><title>nse</title>
+<ellipse fill="none" stroke="black" cx="811" cy="-306" rx="27" ry="18"/>
+<text text-anchor="middle" x="811" y="-302.3" font-family="Times,serif" font-size="14.00">nse</text>
+</g>
+<!-- dht&#45;&gt;nse -->
+<g id="edge43" class="edge"><title>dht&#45;&gt;nse</title>
+<path fill="none" stroke="black" d="M767.934,-361.811C775.214,-352.546 784.663,-340.52 792.854,-330.094"/>
+<polygon fill="black" stroke="black" points="795.663,-332.185 799.089,-322.159 790.159,-327.86 795.663,-332.185"/>
+</g>
+<!-- datacache -->
+<g id="node28" class="node"><title>datacache</title>
+<polygon fill="none" stroke="black" points="702,-324 637.818,-306 702,-288 766.182,-306 702,-324"/>
+<text text-anchor="middle" x="702" y="-302.3" font-family="Times,serif" font-size="14.00">datacache</text>
+</g>
+<!-- dht&#45;&gt;datacache -->
+<g id="edge45" class="edge"><title>dht&#45;&gt;datacache</title>
+<path fill="none" stroke="black" d="M744.016,-361.465C736.66,-351.93 727.125,-339.57 718.998,-329.034"/>
+<polygon fill="black" stroke="black" points="721.73,-326.846 712.851,-321.066 716.187,-331.121 721.73,-326.846"/>
+</g>
+<!-- peerinfo -->
+<g id="node29" class="node"><title>peerinfo</title>
+<ellipse fill="none" stroke="black" cx="518" cy="-90" rx="40.0939" ry="18"/>
+<text text-anchor="middle" x="518" y="-86.3" font-family="Times,serif" font-size="14.00">peerinfo</text>
+</g>
+<!-- dht&#45;&gt;peerinfo -->
+<g id="edge46" class="edge"><title>dht&#45;&gt;peerinfo</title>
+<path fill="none" stroke="black" d="M728.828,-376.457C687.438,-374.282 608.033,-364.658 557,-324 495.436,-274.952 504.26,-168.494 512.535,-118.27"/>
+<polygon fill="black" stroke="black" points="516.027,-118.624 514.32,-108.168 509.133,-117.406 516.027,-118.624"/>
+</g>
+<!-- hello -->
+<g id="node30" class="node"><title>hello</title>
+<polygon fill="none" stroke="black" points="854,-36 813.614,-18 854,-3.55271e-15 894.386,-18 854,-36"/>
+<text text-anchor="middle" x="854" y="-14.3" font-family="Times,serif" font-size="14.00">hello</text>
+</g>
+<!-- dht&#45;&gt;hello -->
+<g id="edge47" class="edge"><title>dht&#45;&gt;hello</title>
+<path fill="none" stroke="black" d="M782.364,-373.864C833.24,-367.278 942.225,-350.399 968,-324 996.322,-294.992 988,-275.542 988,-235 988,-235 988,-235 988,-161 988,-99.7534 921.245,-54.2239 881.968,-32.736"/>
+<polygon fill="black" stroke="black" points="883.108,-29.3792 872.632,-27.796 879.834,-35.5665 883.108,-29.3792"/>
+</g>
+<!-- transport -->
+<g id="node33" class="node"><title>transport</title>
+<ellipse fill="none" stroke="black" cx="680" cy="-162" rx="42.4939" ry="18"/>
+<text text-anchor="middle" x="680" y="-158.3" font-family="Times,serif" font-size="14.00">transport</text>
+</g>
+<!-- core&#45;&gt;transport -->
+<g id="edge58" class="edge"><title>core&#45;&gt;transport</title>
+<path fill="none" stroke="black" d="M575.083,-221.753C594.251,-211.02 623.495,-194.643 646.244,-181.903"/>
+<polygon fill="black" stroke="black" points="648.219,-184.809 655.234,-176.869 644.799,-178.701 648.219,-184.809"/>
+</g>
+<!-- exit -->
+<g id="node12" class="node"><title>exit</title>
+<polygon fill="none" stroke="black" points="952,-540 898,-540 898,-504 952,-504 952,-540"/>
+<text text-anchor="middle" x="925" y="-518.3" font-family="Times,serif" font-size="14.00">exit</text>
+</g>
+<!-- exit&#45;&gt;cadet -->
+<g id="edge13" class="edge"><title>exit&#45;&gt;cadet</title>
+<path fill="none" stroke="black" d="M897.67,-514.323C883.742,-511.021 866.513,-507.093 851,-504 752.337,-484.331 635.236,-465.765 576.155,-456.729"/>
+<polygon fill="black" stroke="black" points="576.571,-453.252 566.158,-455.206 575.517,-460.172 576.571,-453.252"/>
+</g>
+<!-- tun -->
+<g id="node13" class="node"><title>tun</title>
+<polygon fill="none" stroke="black" points="929,-468 897.995,-450 929,-432 960.005,-450 929,-468"/>
+<text text-anchor="middle" x="929" y="-446.3" font-family="Times,serif" font-size="14.00">tun</text>
+</g>
+<!-- exit&#45;&gt;tun -->
+<g id="edge14" class="edge"><title>exit&#45;&gt;tun</title>
+<path fill="none" stroke="black" d="M925.989,-503.697C926.436,-495.868 926.975,-486.435 927.473,-477.728"/>
+<polygon fill="black" stroke="black" points="930.974,-477.806 928.05,-467.622 923.985,-477.406 930.974,-477.806"/>
+</g>
+<!-- dnsstub -->
+<g id="node14" class="node"><title>dnsstub</title>
+<polygon fill="none" stroke="black" points="1032,-468 978.877,-450 1032,-432 1085.12,-450 1032,-468"/>
+<text text-anchor="middle" x="1032" y="-446.3" font-family="Times,serif" font-size="14.00">dnsstub</text>
+</g>
+<!-- exit&#45;&gt;dnsstub -->
+<g id="edge15" class="edge"><title>exit&#45;&gt;dnsstub</title>
+<path fill="none" stroke="black" d="M951.175,-503.876C967.88,-492.948 989.443,-478.841 1006.1,-467.947"/>
+<polygon fill="black" stroke="black" points="1008.33,-470.67 1014.78,-462.266 1004.49,-464.812 1008.33,-470.67"/>
+</g>
+<!-- vpn -->
+<g id="node15" class="node"><title>vpn</title>
+<ellipse fill="none" stroke="black" cx="815" cy="-522" rx="27" ry="18"/>
+<text text-anchor="middle" x="815" y="-518.3" font-family="Times,serif" font-size="14.00">vpn</text>
+</g>
+<!-- vpn&#45;&gt;cadet -->
+<g id="edge16" class="edge"><title>vpn&#45;&gt;cadet</title>
+<path fill="none" stroke="black" d="M793.129,-511.116C787.017,-508.578 780.317,-506.003 774,-504 705.524,-482.293 623.185,-465.931 576.085,-457.463"/>
+<polygon fill="black" stroke="black" points="576.482,-453.979 566.025,-455.678 575.26,-460.871 576.482,-453.979"/>
+</g>
+<!-- vpn&#45;&gt;tun -->
+<g id="edge18" class="edge"><title>vpn&#45;&gt;tun</title>
+<path fill="none" stroke="black" d="M834.339,-509.125C854.149,-496.961 884.945,-478.051 905.995,-465.126"/>
+<polygon fill="black" stroke="black" points="907.942,-468.038 914.632,-459.822 904.279,-462.072 907.942,-468.038"/>
+</g>
+<!-- regex -->
+<g id="node16" class="node"><title>regex</title>
+<ellipse fill="none" stroke="black" cx="756" cy="-450" rx="30.5947" ry="18"/>
+<text text-anchor="middle" x="756" y="-446.3" font-family="Times,serif" font-size="14.00">regex</text>
+</g>
+<!-- vpn&#45;&gt;regex -->
+<g id="edge17" class="edge"><title>vpn&#45;&gt;regex</title>
+<path fill="none" stroke="black" d="M802.198,-505.811C794.496,-496.673 784.53,-484.849 775.827,-474.524"/>
+<polygon fill="black" stroke="black" points="778.307,-472.035 769.186,-466.644 772.954,-476.546 778.307,-472.035"/>
+</g>
+<!-- regex&#45;&gt;dht -->
+<g id="edge57" class="edge"><title>regex&#45;&gt;dht</title>
+<path fill="none" stroke="black" d="M756,-431.697C756,-423.983 756,-414.712 756,-406.112"/>
+<polygon fill="black" stroke="black" points="759.5,-406.104 756,-396.104 752.5,-406.104 759.5,-406.104"/>
+</g>
+<!-- regex&#45;&gt;block -->
+<g id="edge49" class="edge"><title>regex&#45;&gt;block</title>
+<path fill="none" stroke="blue" stroke-dasharray="1,5" d="M732.22,-438.673C673.767,-413.29 523.157,-347.888 458.838,-319.957"/>
+<polygon fill="blue" stroke="blue" points="459.85,-316.581 449.283,-315.808 457.061,-323.002 459.85,-316.581"/>
+</g>
+<!-- pt -->
+<g id="node17" class="node"><title>pt</title>
+<polygon fill="none" stroke="black" points="986,-599.562 959,-612 932,-599.562 932.025,-579.438 985.975,-579.438 986,-599.562"/>
+<text text-anchor="middle" x="959" y="-590.3" font-family="Times,serif" font-size="14.00">pt</text>
+</g>
+<!-- pt&#45;&gt;cadet -->
+<g id="edge19" class="edge"><title>pt&#45;&gt;cadet</title>
+<path fill="none" stroke="black" d="M931.717,-579.439C928.807,-578.197 925.864,-577.023 923,-576 860.875,-553.809 836.841,-571.725 779,-540 758.602,-528.812 761.339,-515.294 741,-504 688.34,-474.76 619.008,-461.18 576.516,-455.23"/>
+<polygon fill="black" stroke="black" points="576.951,-451.758 566.577,-453.91 576.029,-458.697 576.951,-451.758"/>
+</g>
+<!-- pt&#45;&gt;vpn -->
+<g id="edge20" class="edge"><title>pt&#45;&gt;vpn</title>
+<path fill="none" stroke="black" d="M931.915,-579.834C907.352,-567.894 871.179,-550.309 845.585,-537.868"/>
+<polygon fill="black" stroke="black" points="846.864,-534.598 836.34,-533.373 843.803,-540.893 846.864,-534.598"/>
+</g>
+<!-- dns -->
+<g id="node18" class="node"><title>dns</title>
+<ellipse fill="none" stroke="black" cx="997" cy="-522" rx="27" ry="18"/>
+<text text-anchor="middle" x="997" y="-518.3" font-family="Times,serif" font-size="14.00">dns</text>
+</g>
+<!-- pt&#45;&gt;dns -->
+<g id="edge21" class="edge"><title>pt&#45;&gt;dns</title>
+<path fill="none" stroke="black" d="M966.508,-579.17C971.277,-570.385 977.594,-558.748 983.241,-548.346"/>
+<polygon fill="black" stroke="black" points="986.48,-549.716 988.175,-539.257 980.328,-546.376 986.48,-549.716"/>
+</g>
+<!-- dnsparser -->
+<g id="node19" class="node"><title>dnsparser</title>
+<polygon fill="none" stroke="black" points="1143,-540 1080.49,-522 1143,-504 1205.51,-522 1143,-540"/>
+<text text-anchor="middle" x="1143" y="-518.3" font-family="Times,serif" font-size="14.00">dnsparser</text>
+</g>
+<!-- pt&#45;&gt;dnsparser -->
+<g id="edge22" class="edge"><title>pt&#45;&gt;dnsparser</title>
+<path fill="none" stroke="black" d="M986.15,-582.671C1018.5,-570.365 1072.61,-549.781 1108.05,-536.296"/>
+<polygon fill="black" stroke="black" points="1109.42,-539.521 1117.52,-532.694 1106.93,-532.979 1109.42,-539.521"/>
+</g>
+<!-- dns&#45;&gt;tun -->
+<g id="edge23" class="edge"><title>dns&#45;&gt;tun</title>
+<path fill="none" stroke="black" d="M982.91,-506.496C972.543,-495.824 958.362,-481.226 947.147,-469.681"/>
+<polygon fill="black" stroke="black" points="949.418,-466.995 939.94,-462.261 944.397,-471.873 949.418,-466.995"/>
+</g>
+<!-- dns&#45;&gt;dnsstub -->
+<g id="edge24" class="edge"><title>dns&#45;&gt;dnsstub</title>
+<path fill="none" stroke="black" d="M1005.12,-504.765C1009.59,-495.828 1015.21,-484.573 1020.16,-474.673"/>
+<polygon fill="black" stroke="black" points="1023.3,-476.227 1024.64,-465.717 1017.04,-473.096 1023.3,-476.227"/>
+</g>
+<!-- gnsrecord -->
+<g id="node25" class="node"><title>gnsrecord</title>
+<ellipse fill="none" stroke="black" cx="1192" cy="-450" rx="45.4919" ry="18"/>
+<text text-anchor="middle" x="1192" y="-446.3" font-family="Times,serif" font-size="14.00">gnsrecord</text>
+</g>
+<!-- dnsparser&#45;&gt;gnsrecord -->
+<g id="edge39" class="edge"><title>dnsparser&#45;&gt;gnsrecord</title>
+<path fill="none" stroke="blue" stroke-dasharray="1,5" d="M1152.92,-506.834C1159.12,-497.971 1167.29,-486.304 1174.55,-475.928"/>
+<polygon fill="blue" stroke="blue" points="1177.51,-477.805 1180.38,-467.606 1171.77,-473.791 1177.51,-477.805"/>
+</g>
+<!-- zonemaster -->
+<g id="node20" class="node"><title>zonemaster</title>
+<polygon fill="none" stroke="black" points="914.433,-599.562 851,-612 787.567,-599.562 787.626,-579.438 914.374,-579.438 914.433,-599.562"/>
+<text text-anchor="middle" x="851" y="-590.3" font-family="Times,serif" font-size="14.00">zonemaster</text>
+</g>
+<!-- zonemaster&#45;&gt;dht -->
+<g id="edge26" class="edge"><title>zonemaster&#45;&gt;dht</title>
+<path fill="none" stroke="black" d="M853.642,-579.298C856.499,-561.438 859.583,-529.479 851,-504 836.849,-461.994 802.343,-422.916 779.052,-399.996"/>
+<polygon fill="black" stroke="black" points="781.264,-397.267 771.628,-392.861 776.413,-402.314 781.264,-397.267"/>
+</g>
+<!-- namestore -->
+<g id="node21" class="node"><title>namestore</title>
+<ellipse fill="none" stroke="black" cx="685" cy="-522" rx="47.3916" ry="18"/>
+<text text-anchor="middle" x="685" y="-518.3" font-family="Times,serif" font-size="14.00">namestore</text>
+</g>
+<!-- zonemaster&#45;&gt;namestore -->
+<g id="edge25" class="edge"><title>zonemaster&#45;&gt;namestore</title>
+<path fill="none" stroke="black" d="M818.599,-579.337C791.812,-568.041 753.653,-551.95 724.971,-539.855"/>
+<polygon fill="black" stroke="black" points="726.212,-536.58 715.637,-535.919 723.492,-543.03 726.212,-536.58"/>
+</g>
+<!-- namestore&#45;&gt;identity -->
+<g id="edge37" class="edge"><title>namestore&#45;&gt;identity</title>
+<path fill="none" stroke="black" d="M642.634,-513.641C566.046,-500.338 405.247,-472.408 326.867,-458.793"/>
+<polygon fill="black" stroke="black" points="327.275,-455.312 316.823,-457.049 326.077,-462.208 327.275,-455.312"/>
+</g>
+<!-- namestore&#45;&gt;gnsrecord -->
+<g id="edge38" class="edge"><title>namestore&#45;&gt;gnsrecord</title>
+<path fill="none" stroke="black" d="M726.085,-512.971C742.503,-509.919 761.609,-506.564 779,-504 918.405,-483.451 954.522,-488.05 1094,-468 1109.42,-465.784 1126.13,-463.019 1141.32,-460.368"/>
+<polygon fill="black" stroke="black" points="1142.32,-463.746 1151.56,-458.558 1141.1,-456.853 1142.32,-463.746"/>
+</g>
+<!-- gns -->
+<g id="node22" class="node"><title>gns</title>
+<ellipse fill="none" stroke="black" cx="850" cy="-666" rx="27" ry="18"/>
+<text text-anchor="middle" x="850" y="-662.3" font-family="Times,serif" font-size="14.00">gns</text>
+</g>
+<!-- gns&#45;&gt;identity -->
+<g id="edge34" class="edge"><title>gns&#45;&gt;identity</title>
+<path fill="none" stroke="black" d="M823.048,-663.899C740.091,-660.169 489.801,-646.281 417,-612 395.952,-602.089 396.543,-591.28 379,-576 359.686,-559.178 350.742,-559.383 334,-540 317.464,-520.856 303.335,-495.717 293.996,-477.041"/>
+<polygon fill="black" stroke="black" points="297.085,-475.39 289.562,-467.93 290.791,-478.453 297.085,-475.39"/>
+</g>
+<!-- gns&#45;&gt;dht -->
+<g id="edge28" class="edge"><title>gns&#45;&gt;dht</title>
+<path fill="none" stroke="black" d="M870.511,-653.985C875.467,-651.699 880.829,-649.525 886,-648 1002.11,-613.746 1046.93,-664.524 1156,-612 1236.59,-573.194 1305.75,-498.559 1246,-432 1215.85,-398.416 902.601,-384.19 793.343,-380.225"/>
+<polygon fill="black" stroke="black" points="793.243,-376.719 783.125,-379.863 792.995,-383.715 793.243,-376.719"/>
+</g>
+<!-- gns&#45;&gt;block -->
+<g id="edge29" class="edge"><title>gns&#45;&gt;block</title>
+<path fill="none" stroke="blue" stroke-dasharray="1,5" d="M822.824,-664.872C770.707,-663.582 654.321,-655.598 569,-612 548.284,-601.414 548.925,-590.83 531,-576 509.902,-558.544 496.079,-562.857 481,-540 438.212,-475.142 430.206,-380.324 428.985,-334.208"/>
+<polygon fill="blue" stroke="blue" points="432.483,-334.033 428.808,-324.096 425.484,-334.156 432.483,-334.033"/>
+</g>
+<!-- gns&#45;&gt;dnsstub -->
+<g id="edge33" class="edge"><title>gns&#45;&gt;dnsstub</title>
+<path fill="none" stroke="black" d="M871.065,-654.325C875.905,-652.077 881.078,-649.834 886,-648 941.778,-627.217 973.486,-654.658 1015,-612 1049.82,-576.222 1044.5,-512.583 1037.99,-476.971"/>
+<polygon fill="black" stroke="black" points="1041.36,-476 1035.97,-466.88 1034.5,-477.373 1041.36,-476"/>
+</g>
+<!-- gns&#45;&gt;vpn -->
+<g id="edge31" class="edge"><title>gns&#45;&gt;vpn</title>
+<path fill="none" stroke="black" d="M827.858,-655.35C811.041,-646.688 789.135,-632.213 779,-612 768.086,-590.233 781.353,-564.325 794.756,-546.091"/>
+<polygon fill="black" stroke="black" points="797.832,-547.84 801.242,-537.808 792.321,-543.524 797.832,-547.84"/>
+</g>
+<!-- gns&#45;&gt;dns -->
+<g id="edge27" class="edge"><title>gns&#45;&gt;dns</title>
+<path fill="none" stroke="black" d="M871.13,-654.496C875.967,-652.239 881.122,-649.949 886,-648 933.377,-629.072 964.65,-653.009 995,-612 1008.03,-594.39 1007.25,-568.995 1003.95,-549.835"/>
+<polygon fill="black" stroke="black" points="1007.35,-549.022 1001.93,-539.921 1000.49,-550.418 1007.35,-549.022"/>
+</g>
+<!-- gns&#45;&gt;dnsparser -->
+<g id="edge32" class="edge"><title>gns&#45;&gt;dnsparser</title>
+<path fill="none" stroke="black" d="M870.586,-654.227C875.54,-651.931 880.881,-649.692 886,-648 963.461,-622.391 995.505,-653.066 1066,-612 1093.37,-596.054 1115.84,-566.774 1129.29,-546.163"/>
+<polygon fill="black" stroke="black" points="1132.29,-547.978 1134.66,-537.654 1126.37,-544.243 1132.29,-547.978"/>
+</g>
+<!-- revocation -->
+<g id="node23" class="node"><title>revocation</title>
+<ellipse fill="none" stroke="black" cx="474" cy="-594" rx="48.1917" ry="18"/>
+<text text-anchor="middle" x="474" y="-590.3" font-family="Times,serif" font-size="14.00">revocation</text>
+</g>
+<!-- gns&#45;&gt;revocation -->
+<g id="edge30" class="edge"><title>gns&#45;&gt;revocation</title>
+<path fill="none" stroke="black" d="M823.776,-661.482C769.658,-654.024 641.808,-635.374 536,-612 531.019,-610.9 525.841,-609.65 520.694,-608.34"/>
+<polygon fill="black" stroke="black" points="521.456,-604.922 510.895,-605.77 519.68,-611.693 521.456,-604.922"/>
+</g>
+<!-- gns&#45;&gt;gnsrecord -->
+<g id="edge41" class="edge"><title>gns&#45;&gt;gnsrecord</title>
+<path fill="none" stroke="black" d="M870.549,-654.113C875.504,-651.822 880.856,-649.613 886,-648 978.027,-619.137 1009.84,-646.249 1100,-612 1156.37,-590.587 1185.79,-592.754 1215,-540 1225.98,-520.174 1217.7,-494.957 1208.15,-476.431"/>
+<polygon fill="black" stroke="black" points="1211.2,-474.717 1203.29,-467.672 1205.08,-478.114 1211.2,-474.717"/>
+</g>
+<!-- revocation&#45;&gt;core -->
+<g id="edge35" class="edge"><title>revocation&#45;&gt;core</title>
+<path fill="none" stroke="black" d="M447.586,-578.755C410.639,-556.683 348,-510.49 348,-451 348,-451 348,-451 348,-377 348,-335.398 347.208,-317.038 377,-288 415.046,-250.916 477.859,-239.613 517.794,-236.267"/>
+<polygon fill="black" stroke="black" points="518.191,-239.747 527.918,-235.547 517.695,-232.765 518.191,-239.747"/>
+</g>
+<!-- revocation&#45;&gt;set -->
+<g id="edge36" class="edge"><title>revocation&#45;&gt;set</title>
+<path fill="none" stroke="black" d="M484.409,-576.055C489.683,-567.469 496.183,-556.888 501.987,-547.439"/>
+<polygon fill="black" stroke="black" points="505.024,-549.182 507.276,-538.829 499.06,-545.518 505.024,-549.182"/>
+</g>
+<!-- set&#45;&gt;cadet -->
+<g id="edge75" class="edge"><title>set&#45;&gt;cadet</title>
+<path fill="none" stroke="black" d="M522.084,-504.055C524.482,-496.059 527.401,-486.331 530.08,-477.4"/>
+<polygon fill="black" stroke="black" points="533.442,-478.373 532.963,-467.789 526.737,-476.362 533.442,-478.373"/>
+</g>
+<!-- conversation -->
+<g id="node26" class="node"><title>conversation</title>
+<polygon fill="none" stroke="black" points="1017.18,-743.562 948,-756 878.82,-743.562 878.884,-723.438 1017.12,-723.438 1017.18,-743.562"/>
+<text text-anchor="middle" x="948" y="-734.3" font-family="Times,serif" font-size="14.00">conversation</text>
+</g>
+<!-- conversation&#45;&gt;cadet -->
+<g id="edge53" class="edge"><title>conversation&#45;&gt;cadet</title>
+<path fill="none" stroke="black" d="M900.537,-723.335C873.864,-714.435 840.677,-701.257 814,-684 756.206,-646.615 759.329,-615.558 703,-576 673.069,-554.981 658.318,-561.866 629,-540 611.601,-527.024 611.36,-519.336 596,-504 585.077,-493.094 572.479,-481.475 561.82,-471.903"/>
+<polygon fill="black" stroke="black" points="563.901,-469.069 554.107,-465.028 559.243,-474.295 563.901,-469.069"/>
+</g>
+<!-- conversation&#45;&gt;gns -->
+<g id="edge54" class="edge"><title>conversation&#45;&gt;gns</title>
+<path fill="none" stroke="black" d="M928.638,-723.17C913.533,-712.381 892.408,-697.291 875.857,-685.469"/>
+<polygon fill="black" stroke="black" points="877.846,-682.589 867.674,-679.625 873.777,-688.285 877.846,-682.589"/>
+</g>
+<!-- conversation&#45;&gt;gnsrecord -->
+<g id="edge40" class="edge"><title>conversation&#45;&gt;gnsrecord</title>
+<path fill="none" stroke="blue" stroke-dasharray="1,5" d="M1017.21,-728.51C1076.25,-719.968 1155.24,-705.041 1179,-684 1241.33,-628.786 1256.97,-583.117 1231,-504 1227.58,-493.58 1221.24,-483.522 1214.65,-475.019"/>
+<polygon fill="blue" stroke="blue" points="1217.15,-472.551 1208.08,-467.08 1211.76,-477.015 1217.15,-472.551"/>
+</g>
+<!-- speaker -->
+<g id="node31" class="node"><title>speaker</title>
+<polygon fill="none" stroke="black" points="948,-684 894.877,-666 948,-648 1001.12,-666 948,-684"/>
+<text text-anchor="middle" x="948" y="-662.3" font-family="Times,serif" font-size="14.00">speaker</text>
+</g>
+<!-- conversation&#45;&gt;speaker -->
+<g id="edge55" class="edge"><title>conversation&#45;&gt;speaker</title>
+<path fill="none" stroke="black" d="M948,-723.17C948,-714.919 948,-704.153 948,-694.256"/>
+<polygon fill="black" stroke="black" points="951.5,-694.019 948,-684.019 944.5,-694.019 951.5,-694.019"/>
+</g>
+<!-- microphone -->
+<g id="node32" class="node"><title>microphone</title>
+<polygon fill="none" stroke="black" points="1095,-684 1019.76,-666 1095,-648 1170.24,-666 1095,-684"/>
+<text text-anchor="middle" x="1095" y="-662.3" font-family="Times,serif" font-size="14.00">microphone</text>
+</g>
+<!-- conversation&#45;&gt;microphone -->
+<g id="edge56" class="edge"><title>conversation&#45;&gt;microphone</title>
+<path fill="none" stroke="black" d="M976.692,-723.337C1001.14,-711.695 1036.29,-694.958 1061.92,-682.753"/>
+<polygon fill="black" stroke="black" points="1063.71,-685.777 1071.23,-678.318 1060.7,-679.457 1063.71,-685.777"/>
+</g>
+<!-- nse&#45;&gt;core -->
+<g id="edge48" class="edge"><title>nse&#45;&gt;core</title>
+<path fill="none" stroke="black" d="M790.412,-294.231C785.459,-291.935 780.118,-289.695 775,-288 697.966,-262.487 673.625,-275.652 596,-252 592.83,-251.034 589.569,-249.913 586.336,-248.716"/>
+<polygon fill="black" stroke="black" points="587.428,-245.385 576.841,-244.978 584.864,-251.899 587.428,-245.385"/>
+</g>
+<!-- peerinfo&#45;&gt;hello -->
+<g id="edge76" class="edge"><title>peerinfo&#45;&gt;hello</title>
+<path fill="none" stroke="black" d="M548.194,-77.9517C554.676,-75.8006 561.524,-73.6914 568,-72 654.752,-49.3407 758.747,-32.6176 814.333,-24.4966"/>
+<polygon fill="black" stroke="black" points="815.063,-27.9277 824.46,-23.0344 814.062,-20.9995 815.063,-27.9277"/>
+</g>
+<!-- transport&#45;&gt;ats -->
+<g id="edge66" class="edge"><title>transport&#45;&gt;ats</title>
+<path fill="none" stroke="black" d="M644.122,-152.487C587.168,-138.972 476.742,-112.769 420.21,-99.3548"/>
+<polygon fill="black" stroke="black" points="420.844,-95.9082 410.306,-97.0048 419.228,-102.719 420.844,-95.9082"/>
+</g>
+<!-- transport&#45;&gt;peerinfo -->
+<g id="edge68" class="edge"><title>transport&#45;&gt;peerinfo</title>
+<path fill="none" stroke="black" d="M651.411,-148.647C624.725,-137.116 584.738,-119.837 555.501,-107.204"/>
+<polygon fill="black" stroke="black" points="556.601,-103.867 546.033,-103.113 553.824,-110.292 556.601,-103.867"/>
+</g>
+<!-- transport&#45;&gt;hello -->
+<g id="edge67" class="edge"><title>transport&#45;&gt;hello</title>
+<path fill="none" stroke="black" d="M721.405,-157.922C756.719,-153.037 806.213,-140.439 835,-108 850.042,-91.0495 854.193,-65.1533 854.935,-45.6573"/>
+<polygon fill="black" stroke="black" points="858.435,-45.6195 855.044,-35.5822 851.436,-45.5437 858.435,-45.6195"/>
+</g>
+<!-- nat -->
+<g id="node36" class="node"><title>nat</title>
+<polygon fill="none" stroke="black" points="796,-108 765.835,-90 796,-72 826.165,-90 796,-108"/>
+<text text-anchor="middle" x="796" y="-86.3" font-family="Times,serif" font-size="14.00">nat</text>
+</g>
+<!-- transport&#45;&gt;nat -->
+<g id="edge69" class="edge"><title>transport&#45;&gt;nat</title>
+<path fill="none" stroke="black" d="M703.474,-146.834C723.706,-134.626 752.749,-117.1 772.878,-104.953"/>
+<polygon fill="black" stroke="black" points="774.946,-107.793 781.7,-99.6294 771.33,-101.799 774.946,-107.793"/>
+</g>
+<!-- fragmentation -->
+<g id="node37" class="node"><title>fragmentation</title>
+<polygon fill="none" stroke="black" points="662,-108 576.537,-90 662,-72 747.463,-90 662,-108"/>
+<text text-anchor="middle" x="662" y="-86.3" font-family="Times,serif" font-size="14.00">fragmentation</text>
+</g>
+<!-- transport&#45;&gt;fragmentation -->
+<g id="edge70" class="edge"><title>transport&#45;&gt;fragmentation</title>
+<path fill="none" stroke="black" d="M675.643,-144.055C673.556,-135.941 671.011,-126.044 668.687,-117.006"/>
+<polygon fill="black" stroke="black" points="672.073,-116.12 666.193,-107.307 665.294,-117.864 672.073,-116.12"/>
+</g>
+<!-- topology -->
+<g id="node34" class="node"><title>topology</title>
+<polygon fill="none" stroke="black" points="959.5,-324 894.5,-324 894.5,-288 959.5,-288 959.5,-324"/>
+<text text-anchor="middle" x="927" y="-302.3" font-family="Times,serif" font-size="14.00">topology</text>
+</g>
+<!-- topology&#45;&gt;core -->
+<g id="edge61" class="edge"><title>topology&#45;&gt;core</title>
+<path fill="none" stroke="black" d="M894.413,-292.17C889.63,-290.593 884.724,-289.139 880,-288 756.312,-258.18 718.97,-284.656 596,-252 592.621,-251.103 589.151,-249.989 585.73,-248.765"/>
+<polygon fill="black" stroke="black" points="586.918,-245.471 576.329,-245.106 584.379,-251.995 586.918,-245.471"/>
+</g>
+<!-- topology&#45;&gt;peerinfo -->
+<g id="edge59" class="edge"><title>topology&#45;&gt;peerinfo</title>
+<path fill="none" stroke="black" d="M894.233,-295.354C862.315,-285.612 812.655,-269.532 771,-252 705.781,-224.55 688.475,-218.336 629,-180 597.704,-159.827 564.778,-132.553 542.992,-113.534"/>
+<polygon fill="black" stroke="black" points="545.032,-110.666 535.215,-106.682 540.404,-115.919 545.032,-110.666"/>
+</g>
+<!-- topology&#45;&gt;hello -->
+<g id="edge62" class="edge"><title>topology&#45;&gt;hello</title>
+<path fill="none" stroke="black" d="M922.652,-287.966C910.314,-239.626 875.032,-101.398 860.438,-44.2243"/>
+<polygon fill="black" stroke="black" points="863.829,-43.3557 857.964,-34.532 857.046,-45.087 863.829,-43.3557"/>
+</g>
+<!-- topology&#45;&gt;transport -->
+<g id="edge60" class="edge"><title>topology&#45;&gt;transport</title>
+<path fill="none" stroke="black" d="M897.206,-287.871C850.798,-261.191 761.564,-209.891 713.17,-182.069"/>
+<polygon fill="black" stroke="black" points="714.758,-178.945 704.344,-176.995 711.269,-185.014 714.758,-178.945"/>
+</g>
+<!-- hostlist -->
+<g id="node35" class="node"><title>hostlist</title>
+<polygon fill="none" stroke="black" points="214,-324 158,-324 158,-288 214,-288 214,-324"/>
+<text text-anchor="middle" x="186" y="-302.3" font-family="Times,serif" font-size="14.00">hostlist</text>
+</g>
+<!-- hostlist&#45;&gt;core -->
+<g id="edge63" class="edge"><title>hostlist&#45;&gt;core</title>
+<path fill="none" stroke="black" d="M214.167,-292.599C218.733,-290.88 223.455,-289.271 228,-288 330.933,-259.219 456.746,-244.294 517.975,-238.275"/>
+<polygon fill="black" stroke="black" points="518.666,-241.725 528.286,-237.286 517.998,-234.757 518.666,-241.725"/>
+</g>
+<!-- hostlist&#45;&gt;peerinfo -->
+<g id="edge64" class="edge"><title>hostlist&#45;&gt;peerinfo</title>
+<path fill="none" stroke="black" d="M212.608,-287.849C273.449,-248.632 422.455,-152.586 487.166,-110.875"/>
+<polygon fill="black" stroke="black" points="489.21,-113.721 495.719,-105.362 485.418,-107.838 489.21,-113.721"/>
+</g>
+<!-- hostlist&#45;&gt;hello -->
+<g id="edge65" class="edge"><title>hostlist&#45;&gt;hello</title>
+<path fill="none" stroke="black" d="M192.198,-287.715C209.228,-243.039 261.382,-123.627 349,-72 425.521,-26.9118 694.449,-19.9666 805.486,-19.053"/>
+<polygon fill="black" stroke="black" points="805.751,-22.5513 815.727,-18.9823 805.703,-15.5515 805.751,-22.5513"/>
+</g>
+<!-- scalarproduct -->
+<g id="node38" class="node"><title>scalarproduct</title>
+<ellipse fill="none" stroke="black" cx="636" cy="-594" rx="57.6901" ry="18"/>
+<text text-anchor="middle" x="636" y="-590.3" font-family="Times,serif" font-size="14.00">scalarproduct</text>
+</g>
+<!-- scalarproduct&#45;&gt;cadet -->
+<g id="edge74" class="edge"><title>scalarproduct&#45;&gt;cadet</title>
+<path fill="none" stroke="black" d="M622.726,-576.035C614.79,-565.742 604.61,-552.266 596,-540 581.021,-518.662 564.9,-493.752 553.465,-475.721"/>
+<polygon fill="black" stroke="black" points="556.241,-473.562 547.943,-466.975 550.322,-477.299 556.241,-473.562"/>
+</g>
+<!-- scalarproduct&#45;&gt;set -->
+<g id="edge73" class="edge"><title>scalarproduct&#45;&gt;set</title>
+<path fill="none" stroke="black" d="M610.179,-577.811C591.059,-566.564 565.021,-551.248 545.33,-539.665"/>
+<polygon fill="black" stroke="black" points="546.899,-536.527 536.505,-534.473 543.349,-542.56 546.899,-536.527"/>
+</g>
+<!-- secushare -->
+<g id="node39" class="node"><title>secushare</title>
+<polygon fill="none" stroke="black" points="633.366,-815.562 578,-828 522.634,-815.562 522.686,-795.438 633.314,-795.438 633.366,-815.562"/>
+<text text-anchor="middle" x="578" y="-806.3" font-family="Times,serif" font-size="14.00">secushare</text>
+</g>
+<!-- social -->
+<g id="node42" class="node"><title>social</title>
+<ellipse fill="none" stroke="black" cx="578" cy="-738" rx="31.3957" ry="18"/>
+<text text-anchor="middle" x="578" y="-734.3" font-family="Times,serif" font-size="14.00">social</text>
+</g>
+<!-- secushare&#45;&gt;social -->
+<g id="edge80" class="edge"><title>secushare&#45;&gt;social</title>
+<path fill="none" stroke="black" d="M578,-795.17C578,-786.919 578,-776.153 578,-766.256"/>
+<polygon fill="black" stroke="black" points="581.5,-766.019 578,-756.019 574.5,-766.019 581.5,-766.019"/>
+</g>
+<!-- multicast -->
+<g id="node40" class="node"><title>multicast</title>
+<ellipse fill="none" stroke="black" cx="326" cy="-594" rx="43.5923" ry="18"/>
+<text text-anchor="middle" x="326" y="-590.3" font-family="Times,serif" font-size="14.00">multicast</text>
+</g>
+<!-- multicast&#45;&gt;cadet -->
+<g id="edge82" class="edge"><title>multicast&#45;&gt;cadet</title>
+<path fill="none" stroke="black" d="M347.889,-578.338C386.803,-552.273 467.927,-497.935 510.526,-469.402"/>
+<polygon fill="black" stroke="black" points="512.642,-472.198 519.003,-463.725 508.747,-466.382 512.642,-472.198"/>
+</g>
+<!-- psyc -->
+<g id="node41" class="node"><title>psyc</title>
+<ellipse fill="none" stroke="black" cx="326" cy="-666" rx="27" ry="18"/>
+<text text-anchor="middle" x="326" y="-662.3" font-family="Times,serif" font-size="14.00">psyc</text>
+</g>
+<!-- psyc&#45;&gt;multicast -->
+<g id="edge81" class="edge"><title>psyc&#45;&gt;multicast</title>
+<path fill="none" stroke="black" d="M326,-647.697C326,-639.983 326,-630.712 326,-622.112"/>
+<polygon fill="black" stroke="black" points="329.5,-622.104 326,-612.104 322.5,-622.104 329.5,-622.104"/>
+</g>
+<!-- psycstore -->
+<g id="node43" class="node"><title>psycstore</title>
+<ellipse fill="none" stroke="black" cx="220" cy="-594" rx="44.393" ry="18"/>
+<text text-anchor="middle" x="220" y="-590.3" font-family="Times,serif" font-size="14.00">psycstore</text>
+</g>
+<!-- psyc&#45;&gt;psycstore -->
+<g id="edge79" class="edge"><title>psyc&#45;&gt;psycstore</title>
+<path fill="none" stroke="black" d="M307.536,-652.807C291.938,-642.506 269.271,-627.537 250.911,-615.413"/>
+<polygon fill="black" stroke="black" points="252.567,-612.312 242.294,-609.722 248.71,-618.154 252.567,-612.312"/>
+</g>
+<!-- social&#45;&gt;gns -->
+<g id="edge78" class="edge"><title>social&#45;&gt;gns</title>
+<path fill="none" stroke="black" d="M605.831,-729.838C655.82,-716.973 760.68,-689.987 815.282,-675.935"/>
+<polygon fill="black" stroke="black" points="816.373,-679.268 825.185,-673.386 814.628,-672.489 816.373,-679.268"/>
+</g>
+<!-- social&#45;&gt;psyc -->
+<g id="edge77" class="edge"><title>social&#45;&gt;psyc</title>
+<path fill="none" stroke="black" d="M550.552,-729.376C504.247,-716.513 410.731,-690.537 360.222,-676.506"/>
+<polygon fill="black" stroke="black" points="360.996,-673.089 350.424,-673.784 359.122,-679.833 360.996,-673.089"/>
+</g>
+<!-- rps -->
+<g id="node44" class="node"><title>rps</title>
+<ellipse fill="none" stroke="black" cx="593" cy="-306" rx="27" ry="18"/>
+<text text-anchor="middle" x="593" y="-302.3" font-family="Times,serif" font-size="14.00">rps</text>
+</g>
+<!-- rps&#45;&gt;core -->
+<g id="edge83" class="edge"><title>rps&#45;&gt;core</title>
+<path fill="none" stroke="black" d="M584.187,-288.765C579.582,-280.283 573.845,-269.714 568.679,-260.197"/>
+<polygon fill="black" stroke="black" points="571.613,-258.266 563.766,-251.147 565.461,-261.606 571.613,-258.266"/>
+</g>
+</g>
+</svg>
diff --git a/contrib/gnunet_infrastructure/handbook_pull.sh b/contrib/gnunet_infrastructure/handbook_pull.sh
new file mode 100755
index 0000000000000000000000000000000000000000..16c7430ae32df154ff728d70c2bac2ac099c6153
--- /dev/null
+++ b/contrib/gnunet_infrastructure/handbook_pull.sh
@@ -0,0 +1,18 @@
+#!/bin/sh
+#
+# This essentially could be solved by:
+# git config pull.rebase true
+# git config rebase.autoStash true
+# but chances are that this is easy to
+# forget.
+# so execute this file on the server
+# instead of setting a git config.
+
+echo "Running git pull with autoStash and rebase"
+echo "If anything breaks in the future, delete"
+echo "and repeat - it was once considered to"
+echo "be responsible for non-trivial conflicts!"
+echo "We apply this because we need to build the"
+echo "handbook and tutorial without manual interventions."
+
+git pull --rebase --autostash
diff --git a/contrib/guix.README b/contrib/guix.README
new file mode 100644
index 0000000000000000000000000000000000000000..d73b0f4aabf07c5e5714fa6d2fcb8bcecb1ebc94
--- /dev/null
+++ b/contrib/guix.README
@@ -0,0 +1,29 @@
+guix.scm contains Guix package definitions that can be used to
+override the ones found in Guix's GNU distribution.
+
+Guix packagers are encouraged to adopt and adjust these definitions.
+
+GNUnet developers can use this for easily setting up a development or
+test environment using Guix.
+
+When using the package definition for building a package this will
+pick up the current development code. The version of the resulting
+package is the output of 'git describe --tags'.
+
+To make guix build the development package defined here, use the
+following command:
+
+  guix build -f <gnunet.git>/contrib/guix
+
+To spawn a (development) environment with GNUnet's dependencies
+installed, run:
+
+  guix environment --load-path=<gnunet.git>/contrib/guix.scm
+
+To spawn a (test) environment with GNUnet available in this
+environment, run:
+
+  guix environment --load-path=<gnunet.git>/contrib/guix.scm --ad-hoc guix
+
+It is recommented to also pass the '--pure' option to guix, to make
+sure the environment is not polluted with existing packages.
diff --git a/contrib/guix.scm b/contrib/guix.scm
new file mode 100644
index 0000000000000000000000000000000000000000..4376d1ef59a84e88a714a3e1b3c10993718dfd42
--- /dev/null
+++ b/contrib/guix.scm
@@ -0,0 +1,51 @@
+;;; guix.scm -- Guix package definition
+
+(use-modules
+  (guix git-download)
+  (guix download)
+  (guix packages)
+  (guix utils)
+  (guix gexp)
+  (gnu packages)
+  (gnu packages autotools)
+  (gnu packages gettext)
+  (gnu packages gnunet)
+  (gnu packages image)
+  (gnu packages texinfo)
+  (srfi srfi-1)
+  (ice-9 popen)
+  (ice-9 rdelim))
+
+(define %source-dir (dirname (dirname (current-filename))))
+
+(define %git-commit
+  (read-string (open-pipe "git show HEAD | head -1 | cut -d ' ' -f 2" OPEN_READ)))
+
+(define-public gnunet-git
+  (package
+    (inherit gnunet)
+    (name "gnunet")
+    (version (git-version (package-version gnunet) "HEAD" %git-commit))
+    (source (local-file %source-dir #:recursive? #t))
+    (inputs
+     `(("libjpeg" ,libjpeg)
+       ,@(package-inputs gnunet)))
+    (native-inputs
+     `(("autoconf" ,autoconf)
+       ("automake" ,automake)
+       ("gettext" ,gnu-gettext)
+       ("libtool" ,libtool)
+       ("texinfo" ,texinfo)
+       ("which" ,(@ (gnu packages base) which))
+       ,@(package-native-inputs gnunet)))
+    (arguments
+     (substitute-keyword-arguments (package-arguments gnunet)
+       ((#:phases phases)
+        `(modify-phases ,phases
+           (add-after 'unpack 'make-po-directory-writable
+             (lambda _
+               (for-each make-file-writable
+                         (find-files "po" "."))
+               #t))))))))
+
+gnunet-git
diff --git a/contrib/indent_pre-commit b/contrib/indent_pre-commit
new file mode 100755
index 0000000000000000000000000000000000000000..c67fcaf0c65393ccdb385e786147fe28a240a1ed
--- /dev/null
+++ b/contrib/indent_pre-commit
@@ -0,0 +1,22 @@
+#!/bin/sh
+# Run this script to indent the GNUnet code.  When run without arguments,
+# it indents the ENTIRE src/ tree.  Run with 'src/XXX' to indent the
+# src/XXX directory.
+#
+# This script is in the public domain.
+if test $# = 0
+then
+ PATHS=src/
+else
+ PATHS="$@"
+fi
+find $PATHS -name "*.c" -exec indent {} \;
+find $PATHS -name "*.h" -exec indent {} \;
+find $PATHS -name "*.c" -exec indent {} \;
+find $PATHS -name "*.h" -exec indent {} \;
+find $PATHS -name "*.c" -exec contrib/scripts/removetrailingwhitespace.py {} \;
+find $PATHS -name "*.h" -exec contrib/scripts/removetrailingwhitespace.py {} \;
+if test -n "`dos2unix -V | head -n1 | awk '{print $1 $2}'`"; then
+  find $PATHS -name "*.c" -exec dos2unix {} \;
+  find $PATHS -name "*.h" -exec dos2unix {} \;
+fi
diff --git a/contrib/nse/experiments/infiniband.conf b/contrib/nse/experiments/infiniband.conf
new file mode 100644
index 0000000000000000000000000000000000000000..907c1a35e85bfdc869d3038e117b7925eef66158
--- /dev/null
+++ b/contrib/nse/experiments/infiniband.conf
@@ -0,0 +1,125 @@
+[PATHS]
+SERVICEHOME = $GNUNET_TMP/nse-profiler/
+
+[testbed]
+START_ON_DEMAND = NO
+PORT = 12113
+ACCEPT_FROM = 127.0.0.1;192.168.0.0/16;
+HOSTNAME = localhost
+MAX_PARALLEL_TOPOLOGY_CONFIG_OPERATIONS = 5
+OVERLAY_TOPOLOGY = RANDOM
+OVERLAY_RANDOM_LINKS = 1000
+OPERATION_TIMEOUT = 45 s
+
+[nse]
+PORT = 12114
+UNIXPATH = $GNUNET_TMP/test-nse-service-nse.unix
+BINARY = gnunet-service-nse
+#BINARY = /home/mrwiggles/documents/research/gnunet/gnunet-ng/src/nse/.libs/gnunet-service-nse
+#PREFIX = valgrind --leak-check=full --log-file=valgrind_nse.%p
+START_ON_DEMAND = NO
+# Overriding network settings for faster testing (do NOT use
+# these values in production just because they are here)
+WORKDELAY = 60 s
+INTERVAL = 10 s
+WORKBITS = 0
+PROOFFILE = $SERVICEHOME/nse.proof
+
+[arm]
+UNIXPATH = $GNUNET_TMP/test-nse-service-arm.unix
+
+[statistics]
+START_ON_DEMAND = YES
+PORT = 12115
+
+[fs]
+START_ON_DEMAND = NO
+
+[datastore]
+START_ON_DEMAND = NO
+
+[dht]
+START_ON_DEMAND = NO
+
+[nat]
+DISABLEV6 = YES
+BINDTO = 127.0.0.1
+ENABLE_UPNP = NO
+BEHIND_NAT = NO
+ALLOW_NAT = NO
+INTERNAL_ADDRESS = 127.0.0.1
+EXTERNAL_ADDRESS = 127.0.0.1
+
+[transport]
+plugins = udp
+
+[transport-udp]
+PORT = 12116
+
+[core]
+START_ON_DEMAND = YES
+
+[peerinfo]
+START_ON_DEMAND = YES
+
+[dns]
+START_ON_DEMAND = NO
+
+[topology]
+START_ON_DEMAND = NO
+
+[dv]
+START_ON_DEMAND = NO
+
+[resolver]
+START_ON_DEMAND = YES
+
+[cadet]
+START_ON_DEMAND = NO
+
+[chat]
+START_ON_DEMAND = NO
+
+[gns]
+START_ON_DEMAND = NO
+
+[vpn]
+START_ON_DEMAND = NO
+
+[nse-profiler]
+OUTPUT_FILE = nse_output_2000_peers.dat
+TOPOLOGY_OUTPUT_FILE = nse_topo_2000_peers
+DATA_OUTPUT_FILE = nse_stats_2000_peers
+ROUND0 = 1000
+#ROUND1 = 2000
+ROUND2 = 2000
+ROUND3 = 2000
+ROUND4 = 2000
+ROUND5 = 2000
+ROUND6 = 2000
+ROUND7 = 2000
+ROUND8 = 2000
+ROUND9 = 2000
+ROUND10 = 2000
+ROUND11 = 1000
+ROUND12 = 1000
+ROUND13 = 1000
+ROUND14 = 1000
+ROUND15 = 1000
+ROUND16 = 1000
+ROUND17 = 1000
+ROUND18 = 1000
+ROUND19 = 1000
+ROUND20 = 1000
+ROUND21 = 2000
+ROUND22 = 2000
+ROUND23 = 2000
+ROUND24 = 2000
+ROUND25 = 2000
+ROUND26 = 2000
+ROUND27 = 2000
+ROUND28 = 2000
+ROUND29 = 2000
+ROUND30 = 2000
+WAIT_TIME = 1920 s
+CONNECTION_LIMIT = 10
diff --git a/contrib/packages/alpine/gnunet/gnunet-gns-proxy.initd b/contrib/packages/alpine/gnunet/gnunet-gns-proxy.initd
new file mode 100644
index 0000000000000000000000000000000000000000..3c5a22ee23850216b7189cfcf163616ab98da6a4
--- /dev/null
+++ b/contrib/packages/alpine/gnunet/gnunet-gns-proxy.initd
@@ -0,0 +1,107 @@
+#!/sbin/openrc-run
+# Contributor: xrs <xrs@mail36.net>
+# Maintainer: xrs <xrs@mail36.net>
+
+name="gnunet-gns-proxy"
+description="GNUnet GNS proxy for name resolution in Firefox/Chromium"
+command_background="yes"
+pidfile="/run/${SVCNAME}.pid"
+users=`awk -F ':' '$3>=1000 && $3<2000 {print $1}' /etc/passwd`
+
+depend() {
+	need gnunet-user-services
+}
+
+start() {
+        # Enable GNS proxy for existant users.
+        for user in $users; do
+		# Create/Renew GNS certificate authority (CA) per user.
+		su $user -c "gnunet-gns-proxy-setup-ca"
+
+		# Customize gnunet.conf
+                port=$((8000+$(id -u $user)))
+                gnunet-config -c /home/$user/.config/gnunet.conf \
+                        --rewrite \
+                        --section=gns-proxy \
+                        --option=IMMEDIATE_START \
+                        --value=YES
+                gnunet-config -c /home/$user/.config/gnunet.conf \
+                        --rewrite \
+                        --section=gns-proxy \
+                        --option=OPTIONS \
+                        --value="-p $port"
+
+		# Start gns-proxy
+		if test -z "`ps|grep $user|grep gnunet-gns-proxy`" > /dev/null 2>&1
+		then
+			su $user -c "gnunet-arm \
+				-c /home/$user/.config/gnunet.conf -i gns-proxy"
+		fi
+
+		# Firefox
+		if [ ! -d  /home/$user/.mozilla/firefox/*.default ];then
+			timeout 3s firefox --headless # dirty: create profile if not existent
+		fi
+		for ffprofile in /home/$user/.mozilla/firefox/*.*/; do
+			js=$ffprofile/user.js
+			if [ -f $js ]; then
+				sed -i '/Preferences for using the GNU Name System/d' $js
+				sed -i '/network.proxy.socks/d' $js
+				sed -i '/network.proxy.socks_port/d' $js
+				sed -i '/network.proxy.socks_remote_dns/d' $js
+				sed -i '/network.proxy.type/d' $js
+			fi
+			echo "// Preferences for using the GNU Name System" >> $js
+			echo "user_pref(\"network.proxy.socks\", \"localhost\");" >> $js
+			echo "user_pref(\"network.proxy.socks_port\", $port);" >> $js
+			echo "user_pref(\"network.proxy.socks_remote_dns\", true);" >> $js
+			echo "user_pref(\"network.proxy.type\", 1);" >> $js
+		done
+
+		# Chromium
+		profile=/home/$user/.profile
+		if [ -f $profile ]; then
+			sed -i '/CHROMIUM_USER_FLAGS/d' $profile
+		fi
+		echo "export CHROMIUM_USER_FLAGS=--proxy-server=socks5://localhost:$port" \
+			>> $profile
+	done
+}
+
+stop() {
+	for user in $users; do
+		# Stop gns-proxy
+		if test "`ps|grep $user|grep gnunet-gns-proxy`" > /dev/null 2>&1
+		then
+			su $user -c "gnunet-arm \
+				-c /home/$user/.config/gnunet.conf -k gns-proxy"
+		fi
+
+		# Disable gns-proxy in config
+                gnunet-config -c /home/$user/.config/gnunet.conf \
+                        --rewrite \
+                        --section=gns-proxy \
+                        --option=IMMEDIATE_START \
+                        --value=NO
+
+		# Reset proxy preferences
+		for ffprofile in /home/$user/.mozilla/firefox/*.*/; do
+			for file in user.js prefs.js; do
+				js=$ffprofile/$file
+				if [ -f $js ]; then
+					sed -i '/Preferences for using the GNU Name System/d' $js
+					sed -i '/network.proxy.socks/d' $js
+					sed -i '/network.proxy.socks_port/d' $js
+					sed -i '/network.proxy.socks_remote_dns/d' $js
+					sed -i '/network.proxy.type/d' $js
+				fi
+			done
+		done
+
+		# Chromium
+		profile=/home/$user/.profile
+		if [ -f $profile ]; then
+			sed -i '/CHROMIUM_USER_FLAGS/d' $profile
+		fi
+	done
+}
diff --git a/contrib/patches/lrn-indent.diff b/contrib/patches/lrn-indent.diff
new file mode 100644
index 0000000000000000000000000000000000000000..8ba3b77cccc79006ad5ec1de0b5c5ae46681a4a8
--- /dev/null
+++ b/contrib/patches/lrn-indent.diff
@@ -0,0 +1,83 @@
+diff -u indent-2.2.11/src/args.c indent-2.2.11.my/src/args.c
+--- indent-2.2.11/src/args.c	2008-07-23 23:27:17 +0400
++++ indent-2.2.11.my/src/args.c	2011-08-16 14:07:30 +0400
+@@ -151,6 +151,7 @@
+ static int exp_cpp  = 0;
+ static int exp_cs   = 0;
+ static int exp_d    = 0;
++static int exp_ddd  = 0;
+ static int exp_bfda = 0;
+ static int exp_bfde = 0;
+ static int exp_di   = 0;
+@@ -317,6 +318,8 @@
+     {"fca",     PRO_BOOL,                            true,       ON, &settings.format_comments,                  &exp_fca},
+     {"fc1",     PRO_BOOL,                            true,       ON, &settings.format_col1_comments,             &exp_fc1},
+     {"eei",     PRO_BOOL,                           false,       ON, &settings.extra_expression_indent,          &exp_eei},
++    {"ddd",     PRO_BOOL,                            true,       ON, &settings.diff_decls_and_defs,              &exp_ddd},
++    {"nddd",    PRO_BOOL,                            true,      OFF, &settings.diff_decls_and_defs,              &exp_ddd},
+     {"dj",      PRO_BOOL,                           false,       ON, &settings.ljust_decl,                       &exp_dj},
+     {"di",      PRO_INT,                               16, ONOFF_NA, &settings.decl_indent,                      &exp_di},
+     {"d",       PRO_INT,                                0, ONOFF_NA, &settings.unindent_displace,                &exp_d},
+@@ -436,6 +439,8 @@
+     {"fca",     PRO_BOOL,                           false,       ON, &settings.format_comments,                  &exp_fca},
+     {"fc1",     PRO_BOOL,                           false,       ON, &settings.format_col1_comments,             &exp_fc1},
+     {"eei",     PRO_BOOL,                           false,       ON, &settings.extra_expression_indent,          &exp_eei},
++    {"ddd",     PRO_BOOL,                            true,       ON, &settings.diff_decls_and_defs,              &exp_ddd},
++    {"nddd",    PRO_BOOL,                            true,      OFF, &settings.diff_decls_and_defs,              &exp_ddd},
+     {"dj",      PRO_BOOL,                           false,       ON, &settings.ljust_decl,                       &exp_dj},
+     {"di",      PRO_INT,                                2, ONOFF_NA, &settings.decl_indent,                      &exp_di},
+     {"d",       PRO_INT,                                0, ONOFF_NA, &settings.unindent_displace,                &exp_d},
+diff -u indent-2.2.11/src/handletoken.c indent-2.2.11.my/src/handletoken.c
+--- indent-2.2.11/src/handletoken.c	2009-02-15 14:20:42 +0300
++++ indent-2.2.11.my/src/handletoken.c	2011-08-16 14:18:28 +0400
+@@ -1642,6 +1642,11 @@
+     {
+       /* what ? */
+     }
++    if (parser_state_tos->in_parameter_declaration_prototype)
++    {
++      parser_state_tos->in_parameter_declaration_prototype = 0;
++      parser_state_tos->in_parameter_declaration = 0;
++    }
+ }
+ 
+ /**
+diff -u indent-2.2.11/src/indent.h indent-2.2.11.my/src/indent.h
+--- indent-2.2.11/src/indent.h	2009-10-11 23:15:34 +0400
++++ indent-2.2.11.my/src/indent.h	2011-08-16 14:19:37 +0400
+@@ -318,6 +318,11 @@
+     int brace_indent; /*!< number of spaces to indent braces from the suround if, while, etc. in -bl
+                        * (bype_2 == 0) code */
+     int expect_output_file;  /*!< Means "-o" was specified. */
++    int diff_decls_and_defs; /*!< Makes indent think that function prototypes are terminated by ';',
++                              * without this option indent will not be able to tell a difference between
++                              * int foo (); and int foo () {}
++                              * This is the default.
++                              */
+ } user_options_ty;
+ 
+ extern user_options_ty settings;
+@@ -430,6 +435,7 @@
+                                    * slightly different */
+     int in_stmt;                  /*!<  set to 1 while in a stmt */
+     int in_parameter_declaration;
++    int in_parameter_declaration_prototype;
+     int ind_level;                /*!<  the current indentation level in spaces */
+     int ind_stmt;                 /*!<  set to 1 if next line should have an extra
+                                    * indentation level because we are in the
+diff -u indent-2.2.11/src/lexi.c indent-2.2.11.my/src/lexi.c
+--- indent-2.2.11/src/lexi.c	2009-11-11 22:36:32 +0300
++++ indent-2.2.11.my/src/lexi.c	2011-08-16 14:14:28 +0400
+@@ -616,8 +616,11 @@
+                * I've added '=' to this list to keep from breaking
+                * a non-valid C macro from libc.  -jla */
+                     
+-               if (*tp != ';' && *tp != ',' && *tp != '(' && *tp != '=')
++               if ((*tp != ';' || !settings.diff_decls_and_defs) &&
++                   *tp != ',' && *tp != '(' && *tp != '=')
+                {
++                  if (*tp == ';')
++                    parser_state_tos->in_parameter_declaration_prototype = 1;
+                   parser_state_tos->in_parameter_declaration = 1;
+                }
+             }
diff --git a/contrib/patches/texi2html5-indent.diff b/contrib/patches/texi2html5-indent.diff
new file mode 100644
index 0000000000000000000000000000000000000000..2abbcb766672637dfc07b7ac85a226fb0466cf58
--- /dev/null
+++ b/contrib/patches/texi2html5-indent.diff
@@ -0,0 +1,42 @@
+diff -ru indent-gnunet/doc/Makefile.am indent-texi2html5/doc/Makefile.am
+--- indent-gnunet/doc/Makefile.am	2008-04-14 20:31:19.000000000 +0200
++++ indent-texi2html5/doc/Makefile.am	2011-08-22 20:24:26.979782439 +0200
+@@ -34,14 +34,14 @@
+ html-split: @PACKAGE@_toc.html
+ 
+ @PACKAGE@.html: version.texi $(@PACKAGE@_TEXINFOS)
+-	$(TEXI2HTML) -expandinfo -number -monolithic `if test -f @PACKAGE@.texinfo; then echo @PACKAGE@.texinfo; else echo $(srcdir)/@PACKAGE@.texinfo; fi`
++	$(TEXI2HTML) -expandinfo -monolithic `if test -f @PACKAGE@.texinfo; then echo @PACKAGE@.texinfo; else echo $(srcdir)/@PACKAGE@.texinfo; fi`
+ 
+ @PACKAGE@_toc.html: version.texi $(@PACKAGE@_TEXINFOS)
+ 	case "$(TEXI2HTML)" in \
+ 	  *"/missing texi2html") \
+-	     $(TEXI2HTML) -expand info -number -nomenu -split section `if test -f @PACKAGE@.texinfo; then echo @PACKAGE@.texinfo; else echo $(srcdir)/@PACKAGE@.texinfo; fi` || exit 0 ;; \
++	     $(TEXI2HTML) -expand info -nomenu -split section `if test -f @PACKAGE@.texinfo; then echo @PACKAGE@.texinfo; else echo $(srcdir)/@PACKAGE@.texinfo; fi` || exit 0 ;; \
+ 	  *) $(RM) @PACKAGE@_*.html ; \
+-	     $(TEXI2HTML) -expand info -number -nomenu -split section `if test -f @PACKAGE@.texinfo; then echo @PACKAGE@.texinfo; else echo $(srcdir)/@PACKAGE@.texinfo; fi` ;; \
++	     $(TEXI2HTML) -expand info -nomenu -split section `if test -f @PACKAGE@.texinfo; then echo @PACKAGE@.texinfo; else echo $(srcdir)/@PACKAGE@.texinfo; fi` ;; \
+ 	esac
+ 
+ install-html-monolithic: @PACKAGE@.html
+diff -ru indent-gnunet/doc/Makefile.in indent-texi2html5/doc/Makefile.in
+--- indent-gnunet/doc/Makefile.in	2010-01-31 17:25:21.000000000 +0100
++++ indent-texi2html5/doc/Makefile.in	2011-08-22 20:24:41.376449156 +0200
+@@ -663,14 +663,14 @@
+ html-split: @PACKAGE@_toc.html
+ 
+ @PACKAGE@.html: version.texi $(@PACKAGE@_TEXINFOS)
+-	$(TEXI2HTML) -expandinfo -number -monolithic `if test -f @PACKAGE@.texinfo; then echo @PACKAGE@.texinfo; else echo $(srcdir)/@PACKAGE@.texinfo; fi`
++	$(TEXI2HTML) -expandinfo -monolithic `if test -f @PACKAGE@.texinfo; then echo @PACKAGE@.texinfo; else echo $(srcdir)/@PACKAGE@.texinfo; fi`
+ 
+ @PACKAGE@_toc.html: version.texi $(@PACKAGE@_TEXINFOS)
+ 	case "$(TEXI2HTML)" in \
+ 	  *"/missing texi2html") \
+-	     $(TEXI2HTML) -expand info -number -nomenu -split section `if test -f @PACKAGE@.texinfo; then echo @PACKAGE@.texinfo; else echo $(srcdir)/@PACKAGE@.texinfo; fi` || exit 0 ;; \
++	     $(TEXI2HTML) -expand info -nomenu -split section `if test -f @PACKAGE@.texinfo; then echo @PACKAGE@.texinfo; else echo $(srcdir)/@PACKAGE@.texinfo; fi` || exit 0 ;; \
+ 	  *) $(RM) @PACKAGE@_*.html ; \
+-	     $(TEXI2HTML) -expand info -number -nomenu -split section `if test -f @PACKAGE@.texinfo; then echo @PACKAGE@.texinfo; else echo $(srcdir)/@PACKAGE@.texinfo; fi` ;; \
++	     $(TEXI2HTML) -expand info -nomenu -split section `if test -f @PACKAGE@.texinfo; then echo @PACKAGE@.texinfo; else echo $(srcdir)/@PACKAGE@.texinfo; fi` ;; \
+ 	esac
+ 
+ install-html-monolithic: @PACKAGE@.html
diff --git a/contrib/patches/transport_ats_years.diff b/contrib/patches/transport_ats_years.diff
new file mode 100644
index 0000000000000000000000000000000000000000..f48c9555d9c02fa1fb803953dcca51f3206ca41d
--- /dev/null
+++ b/contrib/patches/transport_ats_years.diff
@@ -0,0 +1,132 @@
+Index: src/ats/ats_api_scheduling.c
+===================================================================
+--- src/ats/ats_api_scheduling.c	(revision 29617)
++++ src/ats/ats_api_scheduling.c	(working copy)
+@@ -28,7 +28,7 @@
+ #include "ats.h"
+ 
+ 
+-#define INTERFACE_PROCESSING_INTERVALL GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 1)
++#define INTERFACE_PROCESSING_INTERVALL GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_YEARS, 1)
+ 
+ #define NOT_FOUND 0
+ 
+Index: src/ats/gnunet-service-ats-solver_proportional.c
+===================================================================
+--- src/ats/gnunet-service-ats-solver_proportional.c	(revision 29617)
++++ src/ats/gnunet-service-ats-solver_proportional.c	(working copy)
+@@ -205,12 +205,12 @@
+  *
+  */
+ 
+-#define PREF_AGING_INTERVAL GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 10)
++#define PREF_AGING_INTERVAL GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_YEARS, 10)
+ #define PREF_AGING_FACTOR 0.95
+ 
+ #define DEFAULT_REL_PREFERENCE 1.0
+ #define DEFAULT_ABS_PREFERENCE 0.0
+-#define MIN_UPDATE_INTERVAL GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 10)
++#define MIN_UPDATE_INTERVAL GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_YEARS, 10)
+ 
+ /**
+  * A handle for the proportional solver
+Index: src/ats/gnunet-service-ats_normalization.h
+===================================================================
+--- src/ats/gnunet-service-ats_normalization.h	(revision 29617)
++++ src/ats/gnunet-service-ats_normalization.h	(working copy)
+@@ -27,7 +27,7 @@
+ #include "platform.h"
+ #include "gnunet_ats_service.h"
+ 
+-#define PREF_AGING_INTERVAL GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 10)
++#define PREF_AGING_INTERVAL GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_YEARS, 10)
+ #define PREF_AGING_FACTOR 0.95
+ #define PREF_EPSILON 0.1
+ 
+Index: src/include/gnunet_constants.h
+===================================================================
+--- src/include/gnunet_constants.h	(revision 29617)
++++ src/include/gnunet_constants.h	(working copy)
+@@ -49,7 +49,7 @@
+  * After how long do we consider a connection to a peer dead
+  * if we don't receive messages from the peer?
+  */
+-#define GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 5)
++#define GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_YEARS, 5)
+ 
+ /**
+  * How long do we delay reading more from a peer after a quota violation?
+@@ -61,7 +61,7 @@
+  * even if we assume that the service commonly does not
+  * respond instantly (DNS, Database, etc.).
+  */
+-#define GNUNET_CONSTANTS_SERVICE_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 10)
++#define GNUNET_CONSTANTS_SERVICE_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_YEARS, 10)
+ 
+ /**
+  * How long do we delay messages to get larger packet sizes (CORKing)?
+Index: src/transport/gnunet-service-transport_neighbours.c
+===================================================================
+--- src/transport/gnunet-service-transport_neighbours.c	(revision 29617)
++++ src/transport/gnunet-service-transport_neighbours.c	(working copy)
+@@ -65,7 +65,7 @@
+  * send 3 keepalives in each interval, so 3 messages would need to be
+  * lost in a row for a disconnect).
+  */
+-#define KEEPALIVE_FREQUENCY GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 100)
++#define KEEPALIVE_FREQUENCY GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_YEARS, 100)
+ 
+ /**
+  * How long are we willing to wait for a response from ATS before timing out?
+Index: src/transport/gnunet-service-transport_validation.c
+===================================================================
+--- src/transport/gnunet-service-transport_validation.c	(revision 29617)
++++ src/transport/gnunet-service-transport_validation.c	(working copy)
+@@ -42,7 +42,7 @@
+  * OTOH, we don't want to spend too much time generating PONG signatures,
+  * so they must have some lifetime to reduce our CPU usage.
+  */
+-#define PONG_SIGNATURE_LIFETIME GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_HOURS, 1)
++#define PONG_SIGNATURE_LIFETIME GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_HOURS, 12)
+ 
+ /**
+  * After how long do we expire an address in a HELLO that we just
+@@ -57,7 +57,7 @@
+  * we cannot validate (because after this time we can destroy the
+  * validation record).
+  */
+-#define UNVALIDATED_PING_KEEPALIVE GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 5)
++#define UNVALIDATED_PING_KEEPALIVE GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_HOURS, 4)
+ 
+ /**
+  * How often do we PING an address that we have successfully validated
+@@ -64,17 +64,17 @@
+  * in the past but are not actively using?  Should be (significantly)
+  * smaller than HELLO_ADDRESS_EXPIRATION.
+  */
+-#define VALIDATED_PING_FREQUENCY GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 15)
++#define VALIDATED_PING_FREQUENCY GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_HOURS, 6)
+ 
+ /**
+  * How often do we PING an address that we are currently using?
+  */
+-#define CONNECTED_PING_FREQUENCY GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 2)
++#define CONNECTED_PING_FREQUENCY GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_YEARS, 2)
+ 
+ /**
+  * How much delay is acceptable for sending the PING or PONG?
+  */
+-#define ACCEPTABLE_PING_DELAY GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 1)
++#define ACCEPTABLE_PING_DELAY GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 1)
+ 
+ /**
+  * Size of the validation map hashmap.
+@@ -807,7 +807,7 @@
+ 	 */
+ 
+ 	validation_next = GNUNET_TIME_absolute_get();
+-	validation_delay.rel_value_us = (GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT.rel_value_us) / (max_fds / 2);
++	validation_delay.rel_value_us = GNUNET_TIME_UNIT_MILLISECONDS.rel_value_us;
+ 	validations_fast_start_threshold = (max_fds / 2);
+ 	validations_running = 0;
+ 	GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Validation uses a fast start threshold of %u connections and a delay between of %s\n ",
diff --git a/contrib/privacy-sensitive-symbols.mspec b/contrib/privacy-sensitive-symbols.mspec
new file mode 100644
index 0000000000000000000000000000000000000000..0002c9211db2c1684e4d11b5b9f24af06ed94caa
--- /dev/null
+++ b/contrib/privacy-sensitive-symbols.mspec
@@ -0,0 +1,66 @@
+# private key in 'struct GNUNET_CRYPTO_EccPrivateKey' (FIXME: rename from 'd' to something longer...)
+::^d$
+
+# private key in 'struct GNUNET_CRYPTO_AesSessionKey'
+::^key$
+
+# private key in 'struct GNUNET_CRYPTO_AesSessionKey'
+::^key$
+
+# buf in adjust in crypto_ecc.c
+crypto_ecc\.c:^adjust$:^buf$
+
+# buf in mpi_print in crypto_ecc.c
+crypto_ecc\.c:^mpi_print$:^buf$
+
+# data in mpi_scan in crypto_ecc.c
+crypto_ecc\.c:^mpi_scan$:^data$
+
+# xbuf in GNUNET_CRYPTO_ecc_ecdh in crypto_ecc.c
+crypto_ecc\.c:^GNUNET_CRYPTO_ecc_edch$:^xbuf$
+
+# key_material in GNUNET_CRYPTO_ecc_ecdh in crypto_ecc.c
+crypto_ecc\.c:^GNUNET_CRYPTO_ecc_edch$:^key_material$
+
+# label in key derivation in crypto_ecc.c
+crypto_ecc\.c:^derive_h$:^label$
+crypto_ecc\.c:^GNUNET_CRYPTO_ecc_key_derive$:^label$
+crypto_ecc\.c:^GNUNET_CRYPTO_ecc_public_key_derive$:^label$
+
+# random numbers in crypto_random.c
+crypto_ecc\.c:^GNUNET_CRYPTO_random_u32$:^ret$
+crypto_ecc\.c:^GNUNET_CRYPTO_random_u64$:^ret$
+crypto_ecc\.c:^GNUNET_CRYPTO_random_permute$:^x$
+
+# keys in gnunet-service-core_kx.c
+gnunet-service-core_kx\.c:GSC_KX_handle_ephemeral_key:^key_material$
+gnunet-service-core_kx\.c::^encrypt_key$
+gnunet-service-core_kx\.c::^decrypt_key$
+gnunet-service-core_kx\.c:derive_aes_key:^key_material$
+gnunet-service-core_kx\.c:derive_aes_key:^skey$
+gnunet-service-core_kx\.c:derive_auth_key:^akey$
+gnunet-service-core_kx\.c:derive_auth_key:^skey$
+
+# keywords in file-sharing
+fs_.*::keyword
+gnunet-service-fs.*::keyword
+gnunet-search\.c.*::keyword
+gnunet-search\.c.*:^run$:^args$
+
+
+# download URI for downloading
+gnunet-service-fs.*::chk
+gnunet-search\.c.*::chk
+fs_uri\.c:uri_chk_parse:^h1$
+fs_uri\.c:uri_chk_parse:^h2$
+fs_uri\.c:GNUNET_FS_uri_parse:^uri$
+gnunet-download\.c.*:^run$:^args$
+
+# filename for downloading
+gnunet-download\.c::^filename$
+
+# filename for publishing
+gnunet-publish\.c:run:^uri_string$
+gnunet-publish\.c:run:^args$
+gnunet-publish\.c:identity_continuation:^args0$
+
diff --git a/contrib/scripts/.gitignore b/contrib/scripts/.gitignore
new file mode 100644
index 0000000000000000000000000000000000000000..3b34b9b69d90b96b5c7fc2a4c0bd74698d9babc8
--- /dev/null
+++ b/contrib/scripts/.gitignore
@@ -0,0 +1,3 @@
+gnunet-chk.py
+removetrailingwhitespace.py
+check-texinfo.awk
diff --git a/contrib/scripts/afferify b/contrib/scripts/afferify
new file mode 100755
index 0000000000000000000000000000000000000000..2fa607e1a6f9d66adbb081704e4ac0eb978e86b9
--- /dev/null
+++ b/contrib/scripts/afferify
@@ -0,0 +1,110 @@
+#!/usr/bin/perl
+# Catch all in-source GPL2/3 license declarations and convert
+# them to AGPL.
+#
+# You expected this to be using diff & patch? Well, the source
+# files have all sorts of different commenting and indentation
+# styles, not speaking of typos and failed uses of search and
+# replace, that an attempt in using the patch(1) tool would fail
+# miserably. This script instead is based on my rgrep from 1998.
+# Keeping it here as it may be useful to other projects under-
+# going the same pains. It is forbidden to use this script to
+# convert AGPL code back to less strict licensing. Haha, just
+# kidding.
+#
+#	-symlynX
+
+use File::Find;
+$|=1;
+# Recurse into current or given directories
+find(\&wanted, $#ARGV >= 0 ? @ARGV : '.');
+print STDERR "\n";
+exit;
+
+
+sub wanted {
+	my $name = $File::Find::name;
+	($dev,$ino,$mode,$nlink,$uid,$gid,$rdev,$size,$atime,$mtime,$ctime)
+		= lstat;
+	return $File::Find::prune = 1 if /^(CVS|\.git|\.svn)$/;
+	# Nicer if you 'make distclean' first
+	return if /\.(o|pdf)$/i;
+	return if -d _ or -l _;
+	return if /afferify/;	# Don't apply this to itself ;)
+				# No.. i didn't do it.. just being careful ;) ;)
+#	return unless -T _;	# We don't have binaries in the repo, do we?
+
+	# We need the default variable '$_' for more important duties.
+	my $f = $_;
+
+	if (sysopen(I, $f, O_RDONLY)) {
+		$_ = &slurp(*I);
+		close I;
+		# Debugging: What's inside the file we just read?
+#		print STDERR '> ', $_;
+
+if (0) {
+# This code did the initial conversion. We ifdef it out.
+
+		# Good idea to have the text start with "GNUnet" rather than "This program"
+		if ( s#GNUnet is free software; you can redistribute it and/or modify it under the#GNUnet is free software: you can redistribute it and/or modify it# ) {
+		    # Whoever had the idea of reformatting the GPL license text...
+		    print STDERR "\nTrying wide style on $name\t";
+
+		    # Most important thing to know in order to be able
+		    # to read perl code: if regexps appear without any
+		    # context, it means they are applied to the default
+		    # variable being '$_'.
+		    return unless s#terms of the GNU General Public License as published by the Free Software#under the terms of the GNU Affero General Public License as published#;
+		    return unless s#^(\W*\s+)Foundation; either version \d, or \(at your option\) any later version\.#\1by the Free Software Foundation, either version 3 of the License,\n\1or (at your option) any later version.#m;
+		    return unless s#GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY#GNUnet is distributed in the hope that it will be useful, but#;
+		    return unless s#WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR#WITHOUT ANY WARRANTY; without even the implied warranty of#;
+		    return unless s#^(\W*\s+)A PARTICULAR PURPOSE.  See the GNU General Public License for more details.#\1MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n\1Affero General Public License for more details.#m;
+		    return unless s#^\W*\n\W*\s+You should have received a copy of the GNU General Public License along with\n\W*\s+GNUnet. see the file COPYING\.  If not, .* see\s*\W*\s+<http://www.gnu.org/licenses/>\n##m;
+		} else {
+		    # If this string is not in the file, leave it alone.
+		    return unless s#GNUnet is free software; you can redistribute it and/or modify#GNUnet is free software: you can redistribute it and/or modify it#;
+		    print STDERR "\nTrying regular style on $name\t";
+
+		    # Patterns are designed to also match some typos and substitutions.
+		    return unless s#it under the terms of the GNU General Public Lice\w+ as published#under the terms of the GNU Affero General Public License as published#;
+		    return unless s#by the Free Software Foundation; either version \d, or \(at your#by the Free Software Foundation, either version 3 of the License,#;
+		    return unless s#option\) any later version\.#or (at your option) any later version.#;
+		    return unless s#General Public Lice\w+ for more details\.#Affero General Public License for more details.#;
+		    return unless s#^\W*\n\W*\s+You should have received a copy of the GNU General Public Lice\w+\n\W*\s+along with GNUnet. see the file COPYING\.  If not, write to the\n\W*\s+Free Software Foundation, Inc\., (51 Franklin Street, Fifth Floor|59 Tem ?ple Place - Suite 330),\n\W*\s+Boston, MA 0211\d-130\d, USA\.\n##m;
+		}
+		print STDERR "OK";
+
+} else {
+# This is the code in actual & current use:
+
+		return unless m#GNUnet is free software: you can redistribute it and/or modify it#;
+		print STDERR "\nTrying $name\t";
+		# There was a mistake in the replacement text!
+		return unless s#under the terms of the GNU General Public License as published#under the terms of the GNU Affero General Public License as published#;
+		# Don't apply this one twice!
+#		return unless s#(\n\W*)(\s+)(Affero General Public License for more details\.)#\1\2\3\1\1\2You should have received a copy of the GNU Affero General Public License\1\2along with this program.  If not, see <http://www.gnu.org/licenses/>.#;
+		print STDERR "FIXED";
+}
+
+		# We directly overwrite the original file in the
+		# assumption that we're in a healthy revertible git.
+		open(O, '>', $f) or die "Cannot overwrite $f";
+		# Imagine, I could have left out $_ here... ;)
+		print O $_;
+		close O;
+	} else {
+		die "Cannot access $name";
+	}
+}
+
+# Reads a file from a stream into a variable all at once:
+sub slurp {
+	# Perl sure gets clunky here
+	local(*IN) = @_;
+	local($save) = $/;
+	undef $/;
+	local($data) = <IN>;
+	$/ = $save;
+	return $data;
+}
diff --git a/contrib/scripts/build-install-gnunet-debian10.sh b/contrib/scripts/build-install-gnunet-debian10.sh
new file mode 100755
index 0000000000000000000000000000000000000000..8ac7ce8bb74a1f83dbda2223649370116db9daff
--- /dev/null
+++ b/contrib/scripts/build-install-gnunet-debian10.sh
@@ -0,0 +1,40 @@
+#!/bin/sh
+set -exo
+set -u pipefail
+
+if [ "$USER" = "root" ]; then
+  export SUDO_CMD=""
+else
+  SUDO_CMD="sudo"
+fi
+
+$SUDO_CMD apt update
+
+$SUDO_CMD apt install -y git libtool autoconf \
+autopoint libmicrohttpd-dev build-essential libgcrypt-dev \
+libidn11-dev zlib1g-dev libunistring-dev libglpk-dev miniupnpc \
+libextractor-dev libjansson-dev libcurl4-gnutls-dev gnutls-bin \
+libsqlite3-dev openssl libnss3-tools libopus-dev libpulse-dev libogg-dev
+
+mkdir ~/gnunet_installation || true
+
+cd ~/gnunet_installation
+
+git clone --depth 1 https://gnunet.org/git/gnunet.git || true
+
+cd ~/gnunet_installation/gnunet
+
+./bootstrap
+
+export GNUNET_PREFIX=/usr
+export CFLAGS="-g -Wall -O0"
+
+./configure --prefix=$GNUNET_PREFIX --enable-logging=verbose --disable-documentation
+
+$SUDO_CMD addgroup gnunet || true
+
+$SUDO_CMD usermod -aG gnunet $USER || true
+
+make -j$(nproc || echo -n 1)
+
+$SUDO_CMD make install
diff --git a/contrib/scripts/build_cscope.sh b/contrib/scripts/build_cscope.sh
new file mode 100644
index 0000000000000000000000000000000000000000..ee48f9b5426cebb75cc59ec83d093335841609e7
--- /dev/null
+++ b/contrib/scripts/build_cscope.sh
@@ -0,0 +1,4 @@
+#!/bin/sh
+
+find . -name "*.c" -o -name "*.cpp" -o -name "*.h" -o -name "*.hpp" -o -name "*.py" -o -name "*.sh" > cscope.files
+cscope -q -R -b -i cscope.files
diff --git a/contrib/scripts/changelog_delta.sh b/contrib/scripts/changelog_delta.sh
new file mode 100644
index 0000000000000000000000000000000000000000..f115f1ef179ad1b2d19e8a6a26c94e7a965d0b60
--- /dev/null
+++ b/contrib/scripts/changelog_delta.sh
@@ -0,0 +1,3 @@
+#!/bin/bash
+LASTHASH=$(head -n1 ChangeLog | cut -d " " -f 7 | tr -d \( | tr -d \))
+git log --invert-grep --grep="^-" --no-merges --no-color --format="%aD (%h)%n%s - %cN%n" $LASTHASH..HEAD
diff --git a/contrib/scripts/debug b/contrib/scripts/debug
new file mode 100755
index 0000000000000000000000000000000000000000..c20ebd7dc5b09c00c1f0b5ae9048eb8a72e1a63e
--- /dev/null
+++ b/contrib/scripts/debug
@@ -0,0 +1,37 @@
+#!/bin/sh
+# /proc/sys/kernel/core_pattern should be core.%p.%E
+
+COREPID=$1
+
+COREFILES=`ls -1 *core.$COREPID* 2>/dev/null | wc -l`
+COREFILE=`ls -1 *core.$COREPID* 2>/dev/null | head -n 1`
+
+if [ $COREFILES -gt 1 ]; then
+    echo "Multiple files, using $COREFILE"
+fi
+
+
+if [ $COREFILES -eq 0 ]; then
+    SERVICENAME=$1
+    COREFILES=`ls -1 core.*.*$SERVICENAME 2>/dev/null | wc -l`
+    COREFILE=`ls -1 core.*.*$SERVICENAME 2>/dev/null | head -n 1`
+
+    if [ $COREFILES -gt 1 ]; then
+	echo "Multiple files, using $COREFILE"
+    fi
+fi
+
+if [ $COREFILES -eq 0 ]; then
+    echo "Core file for $1 not found"
+    exit 1
+fi
+
+echo "Using $COREFILE"
+
+EXECPATH=${COREFILE#*!}
+EXECPATH=`echo $EXECPATH | sed -e 's/!/\//g'`
+echo $EXECPATH
+echo ""
+echo ""
+
+gdb --core $COREFILE /$EXECPATH
diff --git a/contrib/scripts/doc/texinfo-hacks.el b/contrib/scripts/doc/texinfo-hacks.el
new file mode 100644
index 0000000000000000000000000000000000000000..bfb5c98fac786e4fe0840e1e93a637624139bf9d
--- /dev/null
+++ b/contrib/scripts/doc/texinfo-hacks.el
@@ -0,0 +1,18 @@
+;;;; hacks.el --- a few functions to help me work on the manual
+;;;; Jim Blandy <jimb@red-bean.com> --- October 1998
+;;;; -- imported from https://git.savannah.gnu.org/cgit/guile.git/tree/doc/hacks.el
+;;;; This code should be covered by the same license as GNU Guile (GPL3).
+
+(defun jh-exemplify-region (start end)
+  (interactive "r")
+  (save-excursion
+    (save-restriction
+      (narrow-to-region start end)
+
+      ;; Texinfo doesn't handle tabs well.
+      (untabify (point-min) (point-max))
+
+      ;; Quote any characters special to texinfo.
+      (goto-char (point-min))
+      (while (re-search-forward "[{}@]" nil t)
+	(replace-match "@\\&")))))
diff --git a/contrib/scripts/find_typedefs.py b/contrib/scripts/find_typedefs.py
new file mode 100644
index 0000000000000000000000000000000000000000..965be3c3477be9666f5133b8fecf21e0082684de
--- /dev/null
+++ b/contrib/scripts/find_typedefs.py
@@ -0,0 +1,100 @@
+# XXX (F841): local variable 'li' is assigned to but never used
+
+import os
+import re
+import sys
+
+debug = False
+
+
+def get_td_from_function_signature(line, file, num):
+    left_paren = line.find('(')
+    if left_paren > 0:
+        left_paren += 1
+        li = line[left_paren:]
+        right_paren = line.find(')')
+        if right_paren > 0 and right_paren > left_paren and line[
+            right_paren:].find('(') >= 0:
+            fname = line[:right_paren]
+            fname = fname.lstrip(' ').lstrip('*').lstrip(' ').rstrip(' ')
+            if len(fname) > 0:
+                if debug:
+                    print("from {0}:{1}".format(file, num))
+                print("-T {0}".format(fname))
+
+
+def get_td_from_simple_type(line, file, num):
+    line = line.rstrip(' ').rstrip('\t').rstrip(' ').rstrip('\t')
+    right_space = line.rfind(' ')
+    right_tab = line.rfind('\t')
+    sep = right_tab if right_tab > right_space else right_space
+    sep += 1
+    tname = line[sep:]
+    tname = tname.lstrip('*')
+    if len(tname) > 0:
+        if debug:
+            print("from {0}:{1}".format(file, num))
+        print("-T {0}".format(tname))
+
+
+def find_typedefs(file):
+    with open(file, 'rb') as f:
+        td = False
+        td_struct = False
+        td_level = 0
+        td_line = []
+        data = f.read()
+        for i, l in enumerate(data.splitlines(False)):
+            # Don't try to be too smart: only count lines that begin with 'typedef '
+            l = l.rstrip(' ').rstrip('\t')
+            if len(l) == 0:
+                continue
+            if not td:
+                if l[:8] != 'typedef ':
+                    continue
+                else:
+                    td = True
+                    if l[8:].lstrip(' ').lstrip('\t')[:6] == 'struct':
+                        td_struct = True
+            if td_struct:
+                leftcbrace = l.find('{')
+                if leftcbrace >= 0:
+                    if td_level == 0:
+                        td_line.append(l[:leftcbrace])
+                    l = l[leftcbrace + 1:]
+                    td_level += 1
+                rightcbrace = l.rfind('}')
+                if rightcbrace >= 0:
+                    td_level -= 1
+                    if td_level == 0:
+                        td_line.append(l[rightcbrace + 1:])
+            else:
+                td_line.append(l)
+            if len(l) > 0 and l[-1] == ';' and (not td_struct or td_level == 0):
+                td_line = ' '.join(td_line)
+                td_line = td_line[:-1]
+                if len(td_line) > 0:
+                    if td_line[-1] == ')':
+                        get_td_from_function_signature(td_line, file, i)
+                    else:
+                        get_td_from_simple_type(td_line, file, i)
+                td_line = []
+                td = False
+                td_struct = False
+                td_level = 0
+
+
+def scan_dir(d):
+    for dirpath, dirs, files in os.walk(d):
+        for f in files:
+            if re.match(r'(?!lt_).+\.(c|cc|h)$', f):
+                file = os.path.join(dirpath, f)
+                find_typedefs(file)
+
+
+if __name__ == '__main__':
+    if len(sys.argv[1:]) == 0:
+        arg = os.getcwd()
+    else:
+        arg = sys.argv[1]
+        scan_dir(arg)
diff --git a/contrib/scripts/gdb-iterate-dll.py b/contrib/scripts/gdb-iterate-dll.py
new file mode 100644
index 0000000000000000000000000000000000000000..28c435ccbd00f009869bef1e9cb8e8569f4df39a
--- /dev/null
+++ b/contrib/scripts/gdb-iterate-dll.py
@@ -0,0 +1,41 @@
+from gdb import *
+
+
+def search_dll(head, field, match, pfield):
+    """
+    Search in a DLL by iterates over it.
+
+    head: name of the symbol denoting the head of the DLL
+    field: the field that should be search for match
+    match: the mathing value for field
+    pfield: the field whose value is to be printed for matched elements; None to
+      print all fields of the matched elemented
+    """
+
+    (symbol, _) = lookup_symbol(head)
+    if symbol is None:
+        print("Can't find symbol: " + head)
+        return
+    symbol_val = symbol.value()
+    while symbol_val:
+        symbol_val_def = symbol_val.dereference()
+        field_val = symbol_val_def[field]
+        if field_val.type.code == gdb.TYPE_CODE_INT:
+            val = int(field_val)
+            res = (match == val)
+        elif (field_val.type.code == gdb.TYPE_CODE_STRING
+              ) or (field_val.type.code == gdb.TYPE_CODE_ARRAY):
+            val = str(field_val)
+            res = (match == val)
+        elif (field_val.type.code == gdb.TYPE_CODE_TYPEDEF):
+            val = str(field_val)
+            res = match in val
+        else:
+            continue
+
+        if res:
+            if pfield is None:
+                print(symbol_val_def)
+            else:
+                print(symbol_val_def[pfield])
+        symbol_val = symbol_val_def["next"]
diff --git a/contrib/scripts/generate-monkey-db.sh b/contrib/scripts/generate-monkey-db.sh
new file mode 100755
index 0000000000000000000000000000000000000000..2afe5550174b1a9b46b812d78981ed5e7d7f2311
--- /dev/null
+++ b/contrib/scripts/generate-monkey-db.sh
@@ -0,0 +1,17 @@
+#!/bin/sh
+
+BASEPATH="$(dirname $0)"
+OLDDIR="${pwd}"
+GN_HOME="/usr/local/bin"
+
+export CC="cparser"
+export CFLAGS="-m32 --seaspider"
+
+cd $BASEPATH/.. && ./configure --prefix=$GN_HOME --with-extractor=$GN_HOME --with-microhttpd=$GN_HOME --with-libgcrypt=$GN_HOME && make && seaspider
+if test "$?" -ne 0
+then
+	echo "FAIL: building GNUnet"
+	exit 1
+fi
+
+cd $OLDDIR
diff --git a/contrib/scripts/gnunet-logread/.gitignore b/contrib/scripts/gnunet-logread/.gitignore
new file mode 100644
index 0000000000000000000000000000000000000000..070182b2f86cb40b55f27b9d18dce2bafaa87082
--- /dev/null
+++ b/contrib/scripts/gnunet-logread/.gitignore
@@ -0,0 +1,2 @@
+gnunet-logread
+gnunet-logread-ipc-sdedit
diff --git a/contrib/scripts/lint/lint-man.sh b/contrib/scripts/lint/lint-man.sh
new file mode 100755
index 0000000000000000000000000000000000000000..8915e9ece2855eccbf7a8151fe897fccaba618ff
--- /dev/null
+++ b/contrib/scripts/lint/lint-man.sh
@@ -0,0 +1,38 @@
+#!/bin/sh
+#
+# SPDX-License-Identifier: 0BSD
+# spit out ONLY error messages using groff.
+
+existence()
+{
+    command -v "$1" >/dev/null 2>&1
+}
+
+if existence groff;
+then
+    echo "groff check"
+    for f in `find . -name \*\.[1-9]`;
+    do
+        LC_ALL=en_US.UTF-8 \
+              MANROFFSEQ='' \
+              MANWIDTH=80 \
+              groff -m mandoc -b -z -w w $f;
+    done
+    # FIXME below, grande stupidity.
+    rm groff_lint.log
+    echo "Wrong use of B"
+    for f in `find . -name \*\.[1-9]`;
+    do
+        awk '/^\.B$/ {print FILENAME":"NR":"$0}' $f >> groff_lint.log || true
+    done
+fi
+
+echo "mandoc check"
+# spit out ONLY error messages with mandoc:
+if existence mandoc;
+then
+    mandoc -T lint `find . -name \*\.[1-9]`
+fi
+
+#LC_ALL=en_US.UTF-8 MANROFFSEQ='' MANWIDTH=80 /run/current-system/profile/bin/man --warnings -E UTF-8 -l -Tutf8 -Z <*.5> >report5.log
+#LC_ALL=en_US.UTF-8 MANROFFSEQ='' MANWIDTH=80 /run/current-system/profile/bin/man --warnings -E UTF-8 -l -Tutf8 -Z <*.1> >report1.log
diff --git a/contrib/scripts/lint/lint-python.sh b/contrib/scripts/lint/lint-python.sh
new file mode 100755
index 0000000000000000000000000000000000000000..0e46719ffbf7804b1d85a2ee065f9596d2baa571
--- /dev/null
+++ b/contrib/scripts/lint/lint-python.sh
@@ -0,0 +1,79 @@
+#!/bin/sh
+# check python style (and 2 to 3 migration)
+#
+# behold, the worst lowest effort shell script
+# ...given that we have more generic checking
+# for executables in other scripts already
+
+existence()
+{
+    command -v "$1" >/dev/null 2>&1
+}
+
+# It is assumed that you are in 'lint'.
+LOGFILE="python-lint.log"
+
+# invoke from root of source!
+if [ $(basename $(pwd)) = "scripts" ]
+then
+   return 1
+else
+    if [ -e "${LOGFILE}" ]
+    then
+        rm ${LOGFILE}
+    fi
+
+    if existence python;
+    then
+        python --version >> ${LOGFILE}
+    fi
+
+    if existence python2;
+    then
+        python2 --version >> ${LOGFILE}
+    fi
+
+    if existence python3;
+    then
+        python3 --version >> ${LOGFILE}
+    fi
+
+    if existence python3.7;
+    then
+        python3.7 --version >> ${LOGFILE}
+    fi
+
+    if existence flake8;
+    then
+        echo >> ${LOGFILE}
+        echo "flake8:" >> ${LOGFILE}
+        echo >> ${LOGFILE}
+        flake8 >> ${LOGFILE}
+    fi
+
+    if existence flake8-3.7;
+    then
+        echo >> ${LOGFILE}
+        echo "flake8:" >> ${LOGFILE}
+        echo >> ${LOGFILE}
+        flake8-3.7 >> ${LOGFILE}
+    fi
+
+    if existence 2to3;
+    then
+        echo >> ${LOGFILE}
+        echo "2to3" >> ${LOGFILE}
+        echo >> ${LOGFILE}
+        2to3 -v -d . >> ${LOGFILE}
+        2to3 -v -p . >> ${LOGFILE}
+    fi
+
+    if existence 2to3-3.7;
+    then
+        echo >> ${LOGFILE}
+        echo "2to3" >> ${LOGFILE}
+        echo >> ${LOGFILE}
+        2to3-3.7 -v -d . >> ${LOGFILE}
+        2to3-3.7 -v -p . >> ${LOGFILE}
+    fi
+fi
diff --git a/contrib/scripts/process_log.sh b/contrib/scripts/process_log.sh
new file mode 100755
index 0000000000000000000000000000000000000000..7b2363a0eee5b3bd874d38bbd83529a685a1c0a3
--- /dev/null
+++ b/contrib/scripts/process_log.sh
@@ -0,0 +1,38 @@
+#!/bin/sh
+
+# Usage: service should print "STARTING SERVICE (srvc) for peer [PEER]" where:
+# - "srvc" is the service name (in lowercase, as in the log output).
+#   It cannot contain parenthesis in its name.
+# - "PEER" is the peer ID. Should be 4 alfanumeric characters
+
+grep "STARTING SERVICE " log > __tmp_peers
+
+SED_EXPR=""
+while read -r line; do
+    SRVC=`echo "$line" | sed -e 's/.*(\([^)]*\)).*/\1/'`
+    PEER=`echo "$line" | sed -e 's/.*\[\(....\)\].*/\1/'`
+    PID=`echo "$line" | sed -e "s/.*$SRVC-\([0-9]*\).*/\1/"`
+    echo "$SRVC $PID => $PEER"
+    
+    SED_EXPR="${SED_EXPR}s/$SRVC-\([a-z2]*\)-$PID/$SRVC \1 $PEER/;"
+    SED_EXPR="${SED_EXPR}s/$SRVC-$PID/$SRVC XXX $PEER/;"
+    SED_EXPR="${SED_EXPR}s/$SRVC-api-[0-9]/$SRVC-api-                                            /;"
+done < __tmp_peers
+rm __tmp_peers
+
+sed -e "$SED_EXPR" log > .log
+echo "$0 sed regex: $SED_EXPR" >> .log
+
+if [ -n "$(uname -a | grep -q 'Linux')" ]; then
+    # GNU coreutils:
+    SIZE=`stat -c%s .log`
+else
+    # NetBSD, FreeBSD (and others?):
+    SIZE=`stat -f%z .log`
+fi
+
+# echo $SIZE
+
+if [ "`ps aux | grep "kwrite .lo[g]"`" = "" -a "$SIZE" -lt "10000000" ]; then
+    kwrite .log --geometry 960x1140-960 &
+fi
diff --git a/contrib/scripts/pydmesg b/contrib/scripts/pydmesg
new file mode 100755
index 0000000000000000000000000000000000000000..9b21359f0bc24471b0804724b2744134a596bd9b
--- /dev/null
+++ b/contrib/scripts/pydmesg
@@ -0,0 +1,73 @@
+#!/usr/bin/env python
+# coding=utf8
+
+# Copyright (C) 2010 Saúl ibarra Corretgé <saghul@gmail.com>
+#
+
+"""
+pydmesg: dmesg with human-readable timestamps
+"""
+
+import re
+import subprocess
+import sys
+
+from datetime import datetime, timedelta
+
+
+_datetime_format = "%Y-%m-%d %H:%M:%S"
+_dmesg_line_regex = re.compile("^\[(?P<time>\d+\.\d+)\](?P<line>.*)$")
+
+def exec_process(cmdline, silent, input=None, **kwargs):
+    """Execute a subprocess and returns the returncode, stdout buffer and stderr buffer.
+       Optionally prints stdout and stderr while running."""
+    try:
+        sub = subprocess.Popen(cmdline, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE, **kwargs)
+        stdout, stderr = sub.communicate(input=input)
+        returncode = sub.returncode
+        if not silent:
+            sys.stdout.write(stdout)
+            sys.stderr.write(stderr)
+    except OSError,e:
+        if e.errno == 2:
+            raise RuntimeError('"%s" is not present on this system' % cmdline[0])
+        else:
+            raise
+    if returncode != 0:
+        raise RuntimeError('Got return value %d while executing "%s", stderr output was:\n%s' % (returncode, " ".join(cmdline), stderr.rstrip("\n")))
+    return stdout
+
+def human_dmesg():
+    now = datetime.now()
+    uptime_diff = None
+    try:
+        with open('/proc/uptime') as f:
+            uptime_diff = f.read().strip().split()[0]
+    except IndexError:
+        return
+    else:
+        try:
+            uptime = now - timedelta(seconds=int(uptime_diff.split('.')[0]), microseconds=int(uptime_diff.split('.')[1]))
+        except IndexError:
+            return
+
+    dmesg_data = exec_process(['dmesg'], True)
+    for line in dmesg_data.split('\n'):
+        if not line:
+            continue
+        match = _dmesg_line_regex.match(line)
+        if match:
+            try:
+                seconds = int(match.groupdict().get('time', '').split('.')[0])
+                nanoseconds = int(match.groupdict().get('time', '').split('.')[1])
+                microseconds = int(round(nanoseconds * 0.001))
+                line = match.groupdict().get('line', '')
+                t = uptime + timedelta(seconds=seconds, microseconds=microseconds)
+            except IndexError:
+                pass
+            else:
+                print "[%s]%s" % (t.strftime(_datetime_format), line)
+
+
+if __name__ == '__main__':
+    human_dmesg()
diff --git a/contrib/scripts/regression.sh b/contrib/scripts/regression.sh
new file mode 100755
index 0000000000000000000000000000000000000000..8d05bdc418f20cd7e3c4d0dbadb0d06dcabaef48
--- /dev/null
+++ b/contrib/scripts/regression.sh
@@ -0,0 +1,54 @@
+#!/bin/sh
+cd
+cd gnunet
+svn up > /dev/null
+H=`hostname`
+echo "================START===================" >> regression.$H
+RUN=`date +%0y%0m%0d%0k%0M`
+uname -a >> regression.$H
+date >> regression.$H
+echo "Run $RUN" >> regression.$H
+svn up >> regression.$H
+export GNUNET_PREFIX=$HOME
+export PATH=$HOME/bin:$PATH
+./bootstrap >> regression.$H.$RUN  2>&1
+./configure --prefix=$HOME --with-extractor=$HOME --with-microhttpd=$HOME  >> regression.$H.$RUN  2>&1
+if [ $? != 0 ]
+then
+  echo configure failed >> regression.$H
+  exit
+fi
+KEEP=0
+make clean >> regression.$H.$RUN 2>&1
+make install >> regression.$H.$RUN 2>&1
+cd src
+for n in `ls --hide "Makefile*"`
+do
+  cd $n
+  if [ -f Makefile ]
+  then
+    make check >> ../regression.$H.$RUN.$n  2>&1
+    if [ $? != 0 ]
+    then
+      echo Tests for $n failed >> ../regression.$H
+      echo "--------- Details for $n -----------" >> ../regression.$H
+      cat regression.$H.$RUN.$n >> ../regression.$H
+      echo "----- End of Details for $n --------" >> ../regression.$H
+      KEEP=1
+    else
+      echo Tests for $n succeeded >> ../regression.$H
+    fi
+  fi
+  cd ..
+done
+echo "================END====================" >> regression.$H
+
+if [ $KEEP = 0]
+then
+  rm regression.$H.$RUN*
+  rm regression.$H
+else
+  svn add regression.$H > /dev/null
+  svn commit -m "Regression in tests on $H" regression.$H
+fi
+
diff --git a/contrib/scripts/revisionary.sh b/contrib/scripts/revisionary.sh
new file mode 100755
index 0000000000000000000000000000000000000000..a39660d52d5dea167c60de23d42b8eca5eb7c2f8
--- /dev/null
+++ b/contrib/scripts/revisionary.sh
@@ -0,0 +1,98 @@
+#!/usr/local/bin/bash
+
+STARTREVISION=14033
+ENDREVISION=15268
+CURRENTREVISION=$STARTREVISION 
+HOME_DIR='/home/gnunet/FreeBSD7-AMD64-wachs/freebsd7-amd64-wachs/build'
+
+
+CMD_UPDATE="svn up --force --accept theirs-full -r"
+CMD_CLEANUP="killall -s 31 -r gnunet-*; make distclean;"
+CMD_PREPARATION="./bootstrap; ./configure --prefix=/tmp/gnb --with-extractor=/usr/local"
+CMD_BUILD="make all"
+CMD_TEST="cd src/transport ; make test_transport_api_tcp; ./test_transport_api_tcp"
+
+#LOGGING=""
+LOGGING=" 1> /dev/null 2> errors.txt"
+LOGFILE="log.txt"
+
+output ()
+{
+  eval echo $1
+  eval echo $1 >> $LOGFILE
+}
+
+
+while [ $CURRENTREVISION -le $ENDREVISION ]; do
+  output 'Testing revision $CURRENTREVISION'
+# updating
+  output ' -> updating '
+  eval cd $HOME_DIR
+  CMD="$CMD_UPDATE $CURRENTREVISION $LOGGING"
+  eval $CMD
+  result=$?
+  if [ $result -eq 0 ]; then
+    output "    updating OK"
+  else
+    output "    updating FAILED"
+    (( CURRENTREVISION++ )) 
+    continue
+  fi
+
+# clean up
+  output " -> cleanup "
+  CMD="$CMD_CLEANUP $LOGGING"
+  eval $CMD
+  result=$?
+  if [ $result -eq 0 ]; then
+    output "    cleanup OK"
+  else
+    output "    cleanup FAILED"
+    (( CURRENTREVISION++ ))     
+    continue
+  fi
+# preparing 
+  output " -> preparation "
+  CMD="$CMD_PREPARATION $LOGGING"
+  #echo $CMD
+  eval $CMD
+  result=$?
+  if [ $result -eq 0 ]; then
+    output "    preparation OK"
+  else
+    output "    preparation FAILED"
+    (( CURRENTREVISION++ )) 
+    continue
+  fi
+# building
+  output  " -> building "
+  CMD="$CMD_BUILD $LOGGING"
+  #echo $CMD
+  eval $CMD
+  result=$?
+  if [ $result -eq 0 ]; then
+    output "    building OK"
+  else
+    output "    building FAILED"
+    (( CURRENTREVISION++ )) 
+    continue
+  fi
+# testing
+  output " -> testing "
+  CMD="$CMD_TEST $LOGGING"
+  #echo $CMD
+  eval $CMD
+  result=$?
+  testresult=result
+  if [ $result -eq 0 ]; then
+    output "    testing OK"
+  else
+    output "    testing FAILED"
+    output 'Revision $CURRENTREVISION FAILED'
+  fi
+  (( CURRENTREVISION++ ))
+done
+
+exit
+
+
diff --git a/contrib/scripts/testbed_cleanup.sh b/contrib/scripts/testbed_cleanup.sh
new file mode 100755
index 0000000000000000000000000000000000000000..ee0200d44177f63d5a182cc07fb98480725f2851
--- /dev/null
+++ b/contrib/scripts/testbed_cleanup.sh
@@ -0,0 +1,14 @@
+#!/bin/sh
+
+###################################################################################
+# Script to clean a previous run of testbed which has crashed. This scripts kills #
+# the peers and cleans the temporary files created for those peers		  #
+# 										  #
+# Author: Sree Harsha Totakura							  #
+###################################################################################
+
+for host in `cut -d : -f 1 < infiniband_cluster.hosts | cut -d @ -f 2`
+do
+    echo "ssh --> $host"
+    ssh $host 'pkill -SIGKILL gnunet; rm -rf /tmp/gnunet-pipe*; rm -rf /tmp/testbed*'
+done
diff --git a/contrib/scripts/visualize_stats.sh b/contrib/scripts/visualize_stats.sh
new file mode 100755
index 0000000000000000000000000000000000000000..aaa5e657b80b5919711aa83b1b9c499939b6242d
--- /dev/null
+++ b/contrib/scripts/visualize_stats.sh
@@ -0,0 +1,86 @@
+#!/bin/bash
+#
+# This script polls gnunet-stats repeatedly to create statistics plots. 
+# Use 'collect' to collect statistics and 'plot' to plot whats been
+# collected. All plots will be written to $STATDIR as separate .png files.
+#
+# WARNING: calling 'collect' will delete all files in $STATDIR.
+#
+# Requires: gnuplot
+#
+# Note: gnuplot syntax has changed across versions. This
+# script perhaps will not produce color images with older gnuplots.
+# The script should work atleast with gnuplot 3.8k patchlevel 1.
+#
+
+SLEEP=120
+GNUNET=$HOME/
+STATDIR=$GNUNET/stats
+IMAGEVIEWER='display'
+TMP=/tmp/.gnuplot_error
+
+##########################################################################
+
+mkdir -p $STATDIR
+
+case "$1" in
+  collect)
+    rm -f $STATDIR/*
+  
+    STARTTIME=`date +%s`
+    IFS=":"
+    
+    while true; do
+	NOW=`date +%s`
+	RELAT=$[$NOW-$STARTTIME]
+	gnunet-statistics | while read KEY VALUE; do
+		KEY=`echo $KEY | tr / .`
+		# Collect stats of previous round
+		if [ -e "$STATDIR/$KEY.dat" ]; then
+			PREV=`tail --lines=1 "$STATDIR/$KEY.dat" | sed -e "s/.* //g"`
+		else
+			PREV=$VALUE
+		fi
+
+		# Write new stats
+		echo $RELAT $VALUE >>"$STATDIR/$KEY.dat"
+		echo $RELAT $PREV $VALUE >>"$STATDIR/$KEY.diff"
+	
+	done
+	sleep $SLEEP
+    done
+  ;;
+  plot)
+	# Plot incremental
+        ls -1 $STATDIR/*.dat | while read FILENAME; do
+	        BASENAME=`basename "$FILENAME" | sed -e "s/ *\..*//g"`
+		echo "set terminal png;set output '$FILENAME.png';set title '$BASENAME - incr';plot '$FILENAME' using (\$1/60):(\$2) title '' with lines;" | nice gnuplot 2> $TMP
+         EC=`cat $TMP | grep "empty" | grep "Warning" | wc -l`
+         if test $EC -ge 1
+	 then
+	   rm "$FILENAME.png"
+	 fi
+	done
+        
+	# Plot diff
+	ls -1 $STATDIR/*.diff | while read FILENAME; do
+	        BASENAME=`basename "$FILENAME" | sed -e "s/ *\..*//g"`
+		echo "set terminal png;set output '$FILENAME.png';set title '$BASENAME - diff';plot '$FILENAME' using (\$1/60):(\$3-\$2) title '' with lines;" | nice gnuplot 2> $TMP
+         EC=`cat $TMP | grep "empty" | grep "Warning" | wc -l`
+         if test $EC -ge 1 
+         then
+          rm "$FILENAME.png"
+         fi
+
+  	done
+  ;;
+  view)
+	$IMAGEVIEWER $STATDIR/*.png
+  ;;
+  *)
+     echo $"Usage: $0 {collect|plot|view}"
+     exit 1
+    
+esac
+
+  
diff --git a/contrib/scripts/zonewalk-to-types.sh b/contrib/scripts/zonewalk-to-types.sh
new file mode 100755
index 0000000000000000000000000000000000000000..dfe15a8e3406b0823d98d55417f564f29e9c4514
--- /dev/null
+++ b/contrib/scripts/zonewalk-to-types.sh
@@ -0,0 +1,35 @@
+#!/bin/sh
+# This script is in the public domain.
+# Converts the output of gnunet-zonewalk (DNS resolutions)
+# into a proper input for gnunet-gns-benchmark.
+
+NUM_CLIENTS=3
+# How many different groups of names should we
+# create?  1/N will be in the 'shared' group.
+
+# FILE ($1) contains results from DNS lookup; strip
+# everything but the hostnames, remove duplicates
+# and then randomize the order.
+cat $1 | grep -v SOA | awk '{print $1}' | sort | uniq | shuf > $1.tmp
+TOTAL=`cat $1.tmp | wc -l`
+GROUP_SIZE=`expr $TOTAL / \( $NUM_CLIENTS + 1 \)`
+echo "Creating $NUM_CLIENTS benchmark sets with 2x $GROUP_SIZE entries each."
+# First group (0) is to be shared among all clients
+for i in `seq 1 $NUM_CLIENTS`
+do
+  cat $1.tmp | head -n $GROUP_SIZE | awk "{print 0 \" \" \$1}" > $1.$i.tmp
+done
+
+# Second group (1) is unique per client
+OFF=$GROUP_SIZE
+for i in `seq 1 $NUM_CLIENTS`
+do
+  END=`expr $OFF + $GROUP_SIZE`
+  cat $1.tmp | head -n $END | tail -n $GROUP_SIZE | awk "{print 1 \" \" \$1}" >> $1.$i.tmp
+# Shuffle again, so we mix the different request categories in terms of
+# when we issue the queries.
+  cat $1.$i.tmp | shuf > $1.$i
+  OFF="$END"
+  rm $1.$i.tmp
+done
+rm $1.tmp
diff --git a/contrib/sounds/vonlynX-bdbAm-lo.wav b/contrib/sounds/vonlynX-bdbAm-lo.wav
new file mode 100644
index 0000000000000000000000000000000000000000..7e479f97a185253f056aca09d13418fcebdb4311
Binary files /dev/null and b/contrib/sounds/vonlynX-bdbAm-lo.wav differ
diff --git a/contrib/sounds/vonlynX-bdbG9-lo.wav b/contrib/sounds/vonlynX-bdbG9-lo.wav
new file mode 100644
index 0000000000000000000000000000000000000000..b60c634c0c0e34601bc77bdc8fd7a09227df466e
Binary files /dev/null and b/contrib/sounds/vonlynX-bdbG9-lo.wav differ
diff --git a/contrib/sounds/vonlynX-ringtones.txt b/contrib/sounds/vonlynX-ringtones.txt
new file mode 100644
index 0000000000000000000000000000000000000000..a1d70696fd84054416ae4ba3512e189a611dbaa9
--- /dev/null
+++ b/contrib/sounds/vonlynX-ringtones.txt
@@ -0,0 +1 @@
+vonlynX-bdbAm-lo.wav, vonlynX-bdbG9-lo.wav: CC-BY-SA // carlo von lynX
diff --git a/contrib/testbed_configs/regex_profiler_infiniband.conf b/contrib/testbed_configs/regex_profiler_infiniband.conf
new file mode 100644
index 0000000000000000000000000000000000000000..2a748ac51ef2d393f0508e4f3756caa3943caf69
--- /dev/null
+++ b/contrib/testbed_configs/regex_profiler_infiniband.conf
@@ -0,0 +1,106 @@
+[testbed]
+START_ON_DEMAND = NO
+PORT = 11999
+ACCEPT_FROM = 127.0.0.1; 192.168.1.0/24;
+HOSTNAME = localhost
+MAX_PARALLEL_OVERLAY_CONNECT_OPERATIONS = 25
+MAX_PARALLEL_TOPOLOGY_CONFIG_OPERATIONS = 5
+#MAX_PARALLEL_OPERATIONS = 1000
+#MAX_PARALLEL_SERVICE_CONNECTIONS = 1000
+
+[regexprofiler]
+BINARY = /home/szengel/gnunet/src/cadet/.libs/gnunet-daemon-regexprofiler
+REGEX_PREFIX = "GNVPN-0001-PAD"
+
+[cadet]
+START_ON_DEMAND = YES
+ACCEPT_FROM = 127.0.0.1; 192.168.1.0/24;
+APP_ANNOUNCE_TIME = 240 s
+ID_ANNOUNCE_TIME = 120 m
+CONNECT_TIMEOUT = 30 s
+PORT = 12001
+DHT_REPLICATION_LEVEL = 3
+
+[dht]
+START_ON_DEMAND = YES
+ACCEPT_FROM = 127.0.0.1; 192.168.1.0/24;
+HOSTNAME = localhost
+# Do not allow DHT to create extra connections, beyond those testbed created
+DISABLE_TRY_CONNECT = NO
+FORCE_NSE = 1
+
+[dhtcache]
+DATABASE = heap
+QUOTA = 100 MB
+# Disable RC-file for Bloom filter?  (for benchmarking with limited IO availability)
+DISABLE_BF_RC = YES
+DISABLE_BF = YES
+
+[datacache-sqlite]
+# Keep datacache in-memory? (reduces IO)
+IN_MEMORY = YES
+
+[fs]
+START_ON_DEMAND = NO
+
+[resolver]
+START_ON_DEMAND = NO
+HOSTNAME = localhost
+
+[transport]
+START_ON_DEMAND = YES
+PLUGINS = tcp
+ACCEPT_FROM = 127.0.0.1; 192.168.1.0/24;
+ACCEPT_FROM6 = ::1;
+NEIGHBOUR_LIMIT = 50
+#PORT = 12004
+
+[ats]
+WAN_QUOTA_OUT = 3932160
+WAN_QUOTA_IN = 3932160
+
+[core]
+START_ON_DEMAND = YES
+
+[transport-tcp]
+TIMEOUT = 300 s
+PORT = 12006
+ACCEPT_FROM = 127.0.0.1; 192.168.1.0/24;
+
+[transport-udp]
+TIMEOUT = 300 s
+PORT = 12007
+ACCEPT_FROM = 127.0.0.1; 192.168.1.0/24;
+
+[statistics]
+PORT = 12008
+START_ON_DEMAND = YES
+ACCEPT_FROM = 127.0.0.1; 192.168.1.0/24;
+DISABLE = NO
+
+[TESTING]
+NUM_PEERS = 5
+HOSTKEYSFILE = ../../contrib/testing_hostkeys.dat
+MAX_CONCURRENT_SSH = 10
+USE_PROGRESSBARS = YES
+PEERGROUP_TIMEOUT = 2400 s
+
+[PATHS]
+SERVICEHOME = $GNUNET_TMP/perf-regex/
+
+[dns]
+START_ON_DEMAND = NO
+
+[nse]
+START_ON_DEMAND = YES
+# Minimize proof-of-work CPU consumption by NSE
+WORKBITS = 1
+
+[vpn]
+START_ON_DEMAND = NO
+
+[nat]
+# Allow running on systems with only loopback?
+RETURN_LOCAL_ADDRESSES = YES
+# Disable redundant addresses...
+DISABLEV6 = YES
diff --git a/contrib/testbed_configs/testbed_cluster.conf b/contrib/testbed_configs/testbed_cluster.conf
new file mode 100644
index 0000000000000000000000000000000000000000..62c83ec78ced2ee3130a777685ae128d0d2eba69
--- /dev/null
+++ b/contrib/testbed_configs/testbed_cluster.conf
@@ -0,0 +1,85 @@
+[testbed]
+START_ON_DEMAND = NO
+PORT = 12113
+ACCEPT_FROM = 127.0.0.1; 192.168.1.0/24; 10.0.0.0/8;
+HOSTNAME = localhost
+OVERLAY_TOPOLOGY = RANDOM
+OVERLAY_RANDOM_LINKS = 10000
+OPERATION_TIMEOUT = 45 s
+# LOG_FILE = $GNUNET_TMP/testbed.log
+SETUP_TIMEOUT = 30m
+MAX_OPEN_FDS = 512
+
+[fs]
+START_ON_DEMAND = NO
+
+[resolver]
+START_ON_DEMAND = NO
+
+[cadet]
+START_ON_DEMAND = NO
+PORT = 71
+
+[dht]
+START_ON_DEMAND = NO
+PORT = 70
+DISABLE_TRY_CONNECT = YES
+
+[statistics]
+START_ON_DEMAND = NO
+PORT = 72
+
+[dhtcache]
+QUOTA = 1 MB
+DATABASE = sqlite
+
+[transport]
+PLUGINS = udp
+DEBUG = NO
+ACCEPT_FROM6 = ::1;
+ACCEPT_FROM = 127.0.0.1;
+NEIGHBOUR_LIMIT = 10
+
+[core]
+PORT = 12092
+START_ON_DEMAND = YES
+USE_EPHEMERAL_KEYS = NO
+
+[arm]
+#PORT = 12366
+DEBUG = NO
+
+[transport-udp]
+TIMEOUT = 300 s
+PORT = 12368
+BROADCAST = NO
+
+[PATHS]
+SERVICEHOME = $GNUNET_TMP/test-testbed/
+
+[dns]
+START_ON_DEMAND = NO
+
+[nse]
+START_ON_DEMAND = NO
+
+[vpn]
+START_ON_DEMAND = NO
+
+[nat]
+RETURN_LOCAL_ADDRESSES = YES
+
+[gns]
+START_ON_DEMAND = NO
+
+[peerinfo]
+NO_IO = YES
+
+[consensus]
+START_ON_DEMAND = NO
+
+[dv]
+START_ON_DEMAND = NO
+
+[lockmanager]
+START_ON_DEMAND = NO
diff --git a/contrib/testbed_configs/testbed_infiniband.conf b/contrib/testbed_configs/testbed_infiniband.conf
new file mode 100644
index 0000000000000000000000000000000000000000..812945eea58b4b0d4d61474c71faece004193588
--- /dev/null
+++ b/contrib/testbed_configs/testbed_infiniband.conf
@@ -0,0 +1,85 @@
+[testbed]
+START_ON_DEMAND = NO
+PORT = 12113
+ACCEPT_FROM = 127.0.0.1; 192.168.1.0/24;
+HOSTNAME = localhost
+OVERLAY_TOPOLOGY = RANDOM
+OVERLAY_RANDOM_LINKS = 1000
+OPERATION_TIMEOUT = 45 s
+# LOG_FILE = $GNUNET_TMP/testbed.log
+SETUP_TIMEOUT = 30m
+MAX_OPEN_FDS = 512
+
+[fs]
+START_ON_DEMAND = NO
+
+[resolver]
+START_ON_DEMAND = NO
+
+[cadet]
+START_ON_DEMAND = NO
+PORT = 71
+
+[dht]
+START_ON_DEMAND = NO
+PORT = 70
+DISABLE_TRY_CONNECT = YES
+
+[statistics]
+START_ON_DEMAND = NO
+PORT = 72
+
+[dhtcache]
+QUOTA = 1 MB
+DATABASE = sqlite
+
+[transport]
+PLUGINS = udp
+DEBUG = NO
+ACCEPT_FROM6 = ::1;
+ACCEPT_FROM = 127.0.0.1;
+NEIGHBOUR_LIMIT = 10
+
+[core]
+PORT = 12092
+START_ON_DEMAND = YES
+USE_EPHEMERAL_KEYS = NO
+
+[arm]
+#PORT = 12366
+DEBUG = NO
+
+[transport-udp]
+TIMEOUT = 300 s
+PORT = 12368
+BROADCAST = NO
+
+[PATHS]
+SERVICEHOME = $GNUNET_TMP/test-testbed/
+
+[dns]
+START_ON_DEMAND = NO
+
+[nse]
+START_ON_DEMAND = NO
+
+[vpn]
+START_ON_DEMAND = NO
+
+[nat]
+RETURN_LOCAL_ADDRESSES = YES
+
+[gns]
+START_ON_DEMAND = NO
+
+[peerinfo]
+NO_IO = YES
+
+[consensus]
+START_ON_DEMAND = NO
+
+[dv]
+START_ON_DEMAND = NO
+
+[lockmanager]
+START_ON_DEMAND = NO
diff --git a/contrib/testbed_configs/testbed_supermuc.conf b/contrib/testbed_configs/testbed_supermuc.conf
new file mode 100644
index 0000000000000000000000000000000000000000..47bfee43cf0048d1c57a7c75d9ec59d678ac29aa
--- /dev/null
+++ b/contrib/testbed_configs/testbed_supermuc.conf
@@ -0,0 +1,73 @@
+[testbed]
+START_ON_DEMAND = NO
+PORT = 12113
+ACCEPT_FROM = 127.0.0.1;10.0.0.0/8;
+HOSTNAME = localhost
+MAX_PARALLEL_TOPOLOGY_CONFIG_OPERATIONS = 5
+MAX_PARALLEL_OPERATIONS = 500
+OVERLAY_TOPOLOGY = 2D_TORUS
+OVERLAY_RANDOM_LINKS = 4000
+OPERATION_TIMEOUT = 10 s
+# LOG_FILE = $GNUNET_TMP/testbed.log
+#PREFIX = xterm -geometry 100x85 -T peer1 -e libtool --mode=execute gdb --args
+MAX_OPEN_FDS=512
+SETUP_TIMEOUT = 30 m
+
+[fs]
+START_ON_DEMAND = NO
+
+[resolver]
+START_ON_DEMAND = NO
+
+[cadet]
+START_ON_DEMAND = NO
+PORT = 71
+
+[dht]
+START_ON_DEMAND = NO
+PORT = 70
+DISABLE_TRY_CONNECT = YES
+
+[statistics]
+START_ON_DEMAND = NO
+PORT = 72
+
+[dhtcache]
+QUOTA = 1 MB
+DATABASE = sqlite
+
+[transport]
+PLUGINS = udp
+DEBUG = NO
+ACCEPT_FROM6 = ::1;
+ACCEPT_FROM = 127.0.0.1;
+NEIGHBOUR_LIMIT = 10
+
+[core]
+PORT = 12092
+START_ON_DEMAND = YES
+USE_EPHEMERAL_KEYS = NO
+
+[arm]
+#PORT = 12366
+DEBUG = NO
+#PREFIX = strace -r -T -o /${WORK}/trace/${PEERID}.strace
+
+[transport-udp]
+TIMEOUT = 300 s
+PORT = 12368
+BROADCAST = NO
+
+[PATHS]
+SERVICEHOME = $GNUNET_TMP/test-testbed/
+
+[nat]
+BEHIND_NAT = NO
+RETURN_LOCAL_ADDRESSES = NO
+
+[peerinfo]
+START_ON_DEMAND = NO
+NO_IO = YES
+
+[testing]
+USE_ABSTRACT_SOCKETS = YES
diff --git a/contrib/testbed_infiniband_results/30000_connections_90000_peers_30_poc.txt b/contrib/testbed_infiniband_results/30000_connections_90000_peers_30_poc.txt
new file mode 100644
index 0000000000000000000000000000000000000000..666b009428508e9baa7e8e6c76d7046c4b62b1a2
--- /dev/null
+++ b/contrib/testbed_infiniband_results/30000_connections_90000_peers_30_poc.txt
@@ -0,0 +1,37 @@
+/home/totakura/local/bin/gnunet-helper-testbed
+/home/totakura/local/bin/gnunet-helper-testbed
+/home/totakura/local/bin/gnunet-helper-testbed
+/home/totakura/local/bin/gnunet-helper-testbed
+/home/totakura/local/bin/gnunet-helper-testbed
+/home/totakura/local/bin/gnunet-helper-testbed
+/home/totakura/local/bin/gnunet-helper-testbed
+/home/totakura/local/bin/gnunet-helper-testbed
+/home/totakura/local/bin/gnunet-helper-testbed
+/home/totakura/local/bin/gnunet-helper-testbed
+/home/totakura/local/bin/gnunet-helper-testbed
+/home/totakura/local/bin/gnunet-helper-testbed
+/home/totakura/local/bin/gnunet-helper-testbed
+/home/totakura/local/bin/gnunet-helper-testbed
+/home/totakura/local/bin/gnunet-helper-testbed
+/home/totakura/local/bin/gnunet-helper-testbed
+/home/totakura/local/bin/gnunet-helper-testbed
+/home/totakura/local/bin/gnunet-helper-testbed
+/home/totakura/local/bin/gnunet-helper-testbed
+/home/totakura/local/bin/gnunet-helper-testbed
+/home/totakura/local/bin/gnunet-helper-testbed
+/home/totakura/local/bin/gnunet-helper-testbed
+/home/totakura/local/bin/gnunet-helper-testbed
+/home/totakura/local/bin/gnunet-helper-testbed
+/home/totakura/local/bin/gnunet-helper-testbed
+/home/totakura/local/bin/gnunet-helper-testbed
+/home/totakura/local/bin/gnunet-helper-testbed
+/home/totakura/local/bin/gnunet-helper-testbed
+/home/totakura/local/bin/gnunet-helper-testbed
+29 controllers started successfully
+90000 peers created successfully in 385.34 seconds
+90000 peers started successfully in 102.31 seconds
+Establishing links. Please wait
+......FFFFFFFFFFFFFFFFFFFFFFFF.....F......................................F.....................FFFFFFFF....F...F...........................................................................................................F............................F........................................................................F.....................F...................................F.....F...F........................F.............................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................F.....................................................................................................................................................F..........................................................................................................................................................................................F......................................................................................................................................................................................F....................................................................................................................................................................F............................................................................................................................................................................F............................................................................................................................................................................F.................................................................................................................................................................................F...........................................................................................................................................................F........................................................................................................................................................F.................................................................F...............................................................................................F.....................................................................................................................................................................................F.....................................................................F...............................................................................................F............................................................................................................................................................................F...........................................................................F..............................................................................................F....................................................................................................................................................................................F...................................................................F.............................................................................................F..................................................................................................................................................................................F.....................................................................F................................................................................................F.............................................................................................................................................................................F.....................................................................F..............................................................................................F.............................................................................................................................................................................F.....................................................................F.................................................................................................F....................................................................................................................................................................................F.....................................................................F..............................................................................................F................................................................................................................................................................................F.........................................................................F.................................................................................................F...............................................................................................................................................................................F..................................................................F......................................................................................F........................................................................................................................................................F........................................................F...........................................................................F........................................................................................................................................F..................................................F.........................................................................F.......................................................................................................................................F.........................................................F...............................................................................F...........................................................................................................................................F.....................................................F.........................................................................F...............................................................................................................F...................................................F..............................................................F..........................................................................................................................F.................................................F..............................................................F.................................................................................................................F...............................................F...............................................................F................................................................................................................F........................................F.........................................................F..................................................................................................F........................................F..................................................F........................................................................................................F.........................F................................F..........................F.......................F..................F...............F....................................F....................F.....F................................F..............F..........................................................................F.........................................F.....................................................F......................................................................................................F.........................................F..................................................F..............................................................................................F.....................................F........................................F..................................................................................F...............F...................F..................................................F................................................................................F...............F..................F..........................................F...............................................................................F.................F................F..........................................F........................................................................F................F...............F.........................................F.............................................................................F.............F..............F............................................F...........................................................................F................F................F.........................................F............................................................................F................F...............F........................................F.........................................................................F...............F................F...........................................F..............................................................................F..............F..............F.........................................F............................................................F...........F............F................................F.............F.............................................................F...............F.................F..........................................F...............F.........................................................F................F.................F..........................................F..............F..............................................................F...............F................F...............................F...........F............................................F............F............F................................F..........F.............................................F...........F...........F...............................F...........F...........................................F...........F............F...............................F..........F...............................................F..........F...........F.....................F........F.............................F........F........F.....................F........F...............................F.....F........F....................F.......F..............................F.......F........F....................F........F..............................F.......F........F....................F........F...............................F........F.......F.....................F.......F.............................F........F........F....................F.......F.............................F........F........F.....................F.......F..............................F........F........F....................F........F..............................F........F........F...................F........F..............................F.....F.......F.....................F.......F...........................F........F........F.............F...F...............F....F....F..F................F........F.............................F.......F........F...F..................F........F..............................F........F........F...F.................F.......F..............................F.......F........F....F..................F........F.............................F.......F........F...F..................F.......F.............................F........F........F..F..................F.......F.............................F........F.......F...F.................F.......F...............................F........F.......F..F..................F.......F.............................F.......F.........F..F..................F.......F.............................F........F........F...F..................F.......F.............................F........F.......F....F.................F........F.............................F.......F........F...F.................F.......F.............................F.......F........F....F................F........F..............................F.......F........F..F..................F.......F...............................F......F.......F....F................F........F.............................F........F........F..F..................F........F..............................F........F.......F....F..................F......F..............................F.......F........F....F..................F.......F...............................F........F......F...F.................F...F..............F....F....F.F........F..F.......F.............................F......F.........F...F..............F...F.......F..............................F.......F........F....F................F..F......F..............................F........F.......F...F...............F...F.......F.............................F.......F........F..F...............F...F........F..............................F........F.......F...F...............F...F......F.............................F.......F........F...F..............F....F......F..............................F.......F........F..F................F..F........F............................F.......F........F..F.................F..F........F.............................F........F.......F....F...............F...F.......F..............................F.......F........F...F..............F...F.......F.............................F........F........F..F..............F...F.......F............................F........F........F...F...............F...F......F............................F........F........F..F................F..F........F............................F.......F.......F..F.FFFFFFF.FF...........F..F...F..............F...F....FF.F.F....F....F...F.......F...FFFFFFFFFFF...F..................FFFFFFFFFFFFF.F.F....F.FFFFFFFFFFF.FF..F...F....FF.F.F....F...F.F...F.F..F...........F.F.F.F.F...F.....FF..FF.FFFFFFFFFFFFF...FF.F.FF.......F......F..F......F..F......F...................F...F..F.F.F.FF....FF.F.FF....FFFFFFFFFF.F.F..FF...F.F.FF.F...F.F....F...F...F.F..F..........F.F.FF.FFFFFFFFFFFFFF...F.F..F......FFFFFF.F.F.F....FF.F.FF..FFFFFFFFF....F.F.FF.FF.F..F.F...FF.F.FF..F..F.FFFFFFFFFFFFFFFFFF
+Aborting due to very high failure rate
+30000 links established in 3322.23 seconds
+Overlay link operations have been retried 703 times upon timeouts
diff --git a/contrib/testbed_infiniband_results/6000_connections_10000_peers_100_poc.txt b/contrib/testbed_infiniband_results/6000_connections_10000_peers_100_poc.txt
new file mode 100644
index 0000000000000000000000000000000000000000..1ff9f799e652ef1067af270d85af35915e1f4ec6
--- /dev/null
+++ b/contrib/testbed_infiniband_results/6000_connections_10000_peers_100_poc.txt
@@ -0,0 +1,36 @@
+/home/totakura/local/bin/gnunet-helper-testbed
+/home/totakura/local/bin/gnunet-helper-testbed
+/home/totakura/local/bin/gnunet-helper-testbed
+/home/totakura/local/bin/gnunet-helper-testbed
+/home/totakura/local/bin/gnunet-helper-testbed
+/home/totakura/local/bin/gnunet-helper-testbed
+/home/totakura/local/bin/gnunet-helper-testbed
+/home/totakura/local/bin/gnunet-helper-testbed
+/home/totakura/local/bin/gnunet-helper-testbed
+/home/totakura/local/bin/gnunet-helper-testbed
+/home/totakura/local/bin/gnunet-helper-testbed
+/home/totakura/local/bin/gnunet-helper-testbed
+/home/totakura/local/bin/gnunet-helper-testbed
+/home/totakura/local/bin/gnunet-helper-testbed
+/home/totakura/local/bin/gnunet-helper-testbed
+/home/totakura/local/bin/gnunet-helper-testbed
+/home/totakura/local/bin/gnunet-helper-testbed
+/home/totakura/local/bin/gnunet-helper-testbed
+/home/totakura/local/bin/gnunet-helper-testbed
+/home/totakura/local/bin/gnunet-helper-testbed
+/home/totakura/local/bin/gnunet-helper-testbed
+/home/totakura/local/bin/gnunet-helper-testbed
+/home/totakura/local/bin/gnunet-helper-testbed
+/home/totakura/local/bin/gnunet-helper-testbed
+/home/totakura/local/bin/gnunet-helper-testbed
+/home/totakura/local/bin/gnunet-helper-testbed
+/home/totakura/local/bin/gnunet-helper-testbed
+/home/totakura/local/bin/gnunet-helper-testbed
+/home/totakura/local/bin/gnunet-helper-testbed
+29 controllers started successfully
+10000 peers created successfully in 35.98 seconds
+10000 peers started successfully in 4.81 seconds
+Establishing links. Please wait
+...............................................................................................................................................................................................................................................................................................................F.FFFFFFFFF................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................
+6000 links established in 168.63 seconds
+Overlay link operations have been retried 10 times upon timeouts
diff --git a/contrib/testbed_infiniband_results/6000_connections_10000_peers_20_poc.txt b/contrib/testbed_infiniband_results/6000_connections_10000_peers_20_poc.txt
new file mode 100644
index 0000000000000000000000000000000000000000..00504be786eec93c5d6c9c8395d509f2b5aed754
--- /dev/null
+++ b/contrib/testbed_infiniband_results/6000_connections_10000_peers_20_poc.txt
@@ -0,0 +1,36 @@
+/home/totakura/local/bin/gnunet-helper-testbed
+/home/totakura/local/bin/gnunet-helper-testbed
+/home/totakura/local/bin/gnunet-helper-testbed
+/home/totakura/local/bin/gnunet-helper-testbed
+/home/totakura/local/bin/gnunet-helper-testbed
+/home/totakura/local/bin/gnunet-helper-testbed
+/home/totakura/local/bin/gnunet-helper-testbed
+/home/totakura/local/bin/gnunet-helper-testbed
+/home/totakura/local/bin/gnunet-helper-testbed
+/home/totakura/local/bin/gnunet-helper-testbed
+/home/totakura/local/bin/gnunet-helper-testbed
+/home/totakura/local/bin/gnunet-helper-testbed
+/home/totakura/local/bin/gnunet-helper-testbed
+/home/totakura/local/bin/gnunet-helper-testbed
+/home/totakura/local/bin/gnunet-helper-testbed
+/home/totakura/local/bin/gnunet-helper-testbed
+/home/totakura/local/bin/gnunet-helper-testbed
+/home/totakura/local/bin/gnunet-helper-testbed
+/home/totakura/local/bin/gnunet-helper-testbed
+/home/totakura/local/bin/gnunet-helper-testbed
+/home/totakura/local/bin/gnunet-helper-testbed
+/home/totakura/local/bin/gnunet-helper-testbed
+/home/totakura/local/bin/gnunet-helper-testbed
+/home/totakura/local/bin/gnunet-helper-testbed
+/home/totakura/local/bin/gnunet-helper-testbed
+/home/totakura/local/bin/gnunet-helper-testbed
+/home/totakura/local/bin/gnunet-helper-testbed
+/home/totakura/local/bin/gnunet-helper-testbed
+/home/totakura/local/bin/gnunet-helper-testbed
+29 controllers started successfully
+10000 peers created successfully in 35.34 seconds
+10000 peers started successfully in 3.87 seconds
+Establishing links. Please wait
+...........................................................................................................................................................................................................................................................................................FFFF.....................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................
+6000 links established in 203.77 seconds
+Overlay link operations have been retried 4 times upon timeouts
diff --git a/contrib/testbed_infiniband_results/6000_connections_10000_peers_30_poc.txt b/contrib/testbed_infiniband_results/6000_connections_10000_peers_30_poc.txt
new file mode 100644
index 0000000000000000000000000000000000000000..daa5d9149253761b8179494ea516e8e813470cd8
--- /dev/null
+++ b/contrib/testbed_infiniband_results/6000_connections_10000_peers_30_poc.txt
@@ -0,0 +1,37 @@
+/home/totakura/local/bin/gnunet-helper-testbed
+/home/totakura/local/bin/gnunet-helper-testbed
+/home/totakura/local/bin/gnunet-helper-testbed
+/home/totakura/local/bin/gnunet-helper-testbed
+/home/totakura/local/bin/gnunet-helper-testbed
+/home/totakura/local/bin/gnunet-helper-testbed
+/home/totakura/local/bin/gnunet-helper-testbed
+/home/totakura/local/bin/gnunet-helper-testbed
+/home/totakura/local/bin/gnunet-helper-testbed
+/home/totakura/local/bin/gnunet-helper-testbed
+/home/totakura/local/bin/gnunet-helper-testbed
+/home/totakura/local/bin/gnunet-helper-testbed
+/home/totakura/local/bin/gnunet-helper-testbed
+/home/totakura/local/bin/gnunet-helper-testbed
+/home/totakura/local/bin/gnunet-helper-testbed
+/home/totakura/local/bin/gnunet-helper-testbed
+/home/totakura/local/bin/gnunet-helper-testbed
+/home/totakura/local/bin/gnunet-helper-testbed
+/home/totakura/local/bin/gnunet-helper-testbed
+/home/totakura/local/bin/gnunet-helper-testbed
+/home/totakura/local/bin/gnunet-helper-testbed
+/home/totakura/local/bin/gnunet-helper-testbed
+/home/totakura/local/bin/gnunet-helper-testbed
+/home/totakura/local/bin/gnunet-helper-testbed
+/home/totakura/local/bin/gnunet-helper-testbed
+/home/totakura/local/bin/gnunet-helper-testbed
+/home/totakura/local/bin/gnunet-helper-testbed
+/home/totakura/local/bin/gnunet-helper-testbed
+/home/totakura/local/bin/gnunet-helper-testbed
+29 controllers started successfully
+20000 peers created successfully in 79.97 seconds
+20000 peers started successfully in 10.22 seconds
+Establishing links. Please wait
+...............................................FFFFFFFFF.FFF
+Aborting due to very high failure rate
+12000 links established in 30.08 seconds
+Overlay link operations have been retried 12 times upon timeouts
diff --git a/contrib/testbed_infiniband_results/6000_connections_20000_peers.txt b/contrib/testbed_infiniband_results/6000_connections_20000_peers.txt
new file mode 100644
index 0000000000000000000000000000000000000000..b00832e5818e5248702324622645a3a4294808a7
--- /dev/null
+++ b/contrib/testbed_infiniband_results/6000_connections_20000_peers.txt
@@ -0,0 +1,25 @@
+/home/totakura/local/bin/gnunet-helper-testbed
+/home/totakura/local/bin/gnunet-helper-testbed
+/home/totakura/local/bin/gnunet-helper-testbed
+/home/totakura/local/bin/gnunet-helper-testbed
+/home/totakura/local/bin/gnunet-helper-testbed
+/home/totakura/local/bin/gnunet-helper-testbed
+/home/totakura/local/bin/gnunet-helper-testbed
+/home/totakura/local/bin/gnunet-helper-testbed
+/home/totakura/local/bin/gnunet-helper-testbed
+/home/totakura/local/bin/gnunet-helper-testbed
+/home/totakura/local/bin/gnunet-helper-testbed
+/home/totakura/local/bin/gnunet-helper-testbed
+/home/totakura/local/bin/gnunet-helper-testbed
+/home/totakura/local/bin/gnunet-helper-testbed
+/home/totakura/local/bin/gnunet-helper-testbed
+/home/totakura/local/bin/gnunet-helper-testbed
+/home/totakura/local/bin/gnunet-helper-testbed
+/home/totakura/local/bin/gnunet-helper-testbed
+/home/totakura/local/bin/gnunet-helper-testbed
+All slaves started successfully
+All peers created successfully in 55.53 seconds
+All peers started successfully in 26.02 seconds
+Establishing links. Please wait
+........................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................F...F.F.FF....................................................................................................F...............................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................
+6000 links established in 123.49 seconds
diff --git a/contrib/testbed_infiniband_results/6000_connections_40000_peers.txt b/contrib/testbed_infiniband_results/6000_connections_40000_peers.txt
new file mode 100644
index 0000000000000000000000000000000000000000..ccd5ec41cc3aa89cc26974da5f9c0320d6e6b2f4
--- /dev/null
+++ b/contrib/testbed_infiniband_results/6000_connections_40000_peers.txt
@@ -0,0 +1,36 @@
+/home/totakura/local/bin/gnunet-helper-testbed
+/home/totakura/local/bin/gnunet-helper-testbed
+/home/totakura/local/bin/gnunet-helper-testbed
+/home/totakura/local/bin/gnunet-helper-testbed
+/home/totakura/local/bin/gnunet-helper-testbed
+/home/totakura/local/bin/gnunet-helper-testbed
+/home/totakura/local/bin/gnunet-helper-testbed
+/home/totakura/local/bin/gnunet-helper-testbed
+/home/totakura/local/bin/gnunet-helper-testbed
+/home/totakura/local/bin/gnunet-helper-testbed
+/home/totakura/local/bin/gnunet-helper-testbed
+/home/totakura/local/bin/gnunet-helper-testbed
+/home/totakura/local/bin/gnunet-helper-testbed
+/home/totakura/local/bin/gnunet-helper-testbed
+/home/totakura/local/bin/gnunet-helper-testbed
+/home/totakura/local/bin/gnunet-helper-testbed
+/home/totakura/local/bin/gnunet-helper-testbed
+/home/totakura/local/bin/gnunet-helper-testbed
+/home/totakura/local/bin/gnunet-helper-testbed
+/home/totakura/local/bin/gnunet-helper-testbed
+/home/totakura/local/bin/gnunet-helper-testbed
+/home/totakura/local/bin/gnunet-helper-testbed
+/home/totakura/local/bin/gnunet-helper-testbed
+/home/totakura/local/bin/gnunet-helper-testbed
+/home/totakura/local/bin/gnunet-helper-testbed
+/home/totakura/local/bin/gnunet-helper-testbed
+/home/totakura/local/bin/gnunet-helper-testbed
+/home/totakura/local/bin/gnunet-helper-testbed
+/home/totakura/local/bin/gnunet-helper-testbed
+29 controllers started successfully
+40000 peers created successfully in 165.12 seconds
+40000 peers started successfully in 179.35 seconds
+Establishing links. Please wait
+................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................
+6000 links established in 101.62 seconds
+Overlay link operations have been retried 0 times upon timeouts
diff --git a/contrib/testbed_infiniband_results/6000_connections_60000_peers.txt b/contrib/testbed_infiniband_results/6000_connections_60000_peers.txt
new file mode 100644
index 0000000000000000000000000000000000000000..88606f99e0d232427bb34d89b2a37ca153d94ae3
--- /dev/null
+++ b/contrib/testbed_infiniband_results/6000_connections_60000_peers.txt
@@ -0,0 +1,61 @@
+/home/totakura/local/bin/gnunet-helper-testbed
+/home/totakura/local/bin/gnunet-helper-testbed
+/home/totakura/local/bin/gnunet-helper-testbed
+/home/totakura/local/bin/gnunet-helper-testbed
+/home/totakura/local/bin/gnunet-helper-testbed
+/home/totakura/local/bin/gnunet-helper-testbed
+/home/totakura/local/bin/gnunet-helper-testbed
+/home/totakura/local/bin/gnunet-helper-testbed
+/home/totakura/local/bin/gnunet-helper-testbed
+/home/totakura/local/bin/gnunet-helper-testbed
+/home/totakura/local/bin/gnunet-helper-testbed
+/home/totakura/local/bin/gnunet-helper-testbed
+/home/totakura/local/bin/gnunet-helper-testbed
+/home/totakura/local/bin/gnunet-helper-testbed
+/home/totakura/local/bin/gnunet-helper-testbed
+/home/totakura/local/bin/gnunet-helper-testbed
+/home/totakura/local/bin/gnunet-helper-testbed
+/home/totakura/local/bin/gnunet-helper-testbed
+/home/totakura/local/bin/gnunet-helper-testbed
+/home/totakura/local/bin/gnunet-helper-testbed
+/home/totakura/local/bin/gnunet-helper-testbed
+/home/totakura/local/bin/gnunet-helper-testbed
+/home/totakura/local/bin/gnunet-helper-testbed
+/home/totakura/local/bin/gnunet-helper-testbed
+/home/totakura/local/bin/gnunet-helper-testbed
+/home/totakura/local/bin/gnunet-helper-testbed
+/home/totakura/local/bin/gnunet-helper-testbed
+/home/totakura/local/bin/gnunet-helper-testbed
+/home/totakura/local/bin/gnunet-helper-testbed
+29 controllers started successfully
+60000 peers created successfully in 253.31 seconds
+60000 peers started successfully in 53.18 seconds
+Establishing links. Please wait
+..............FFFFFFFFFFF
+Aborting due to very high failure rate
+6000 links established in 30.14 seconds
+Overlay link operations have been retried 11 times upon timeouts
+F
+Aborting due to very high failure rate
+6000 links established in 30.14 seconds
+Overlay link operations have been retried 12 times upon timeouts
+F
+Aborting due to very high failure rate
+6000 links established in 30.14 seconds
+Overlay link operations have been retried 13 times upon timeouts
+F
+Aborting due to very high failure rate
+6000 links established in 30.14 seconds
+Overlay link operations have been retried 14 times upon timeouts
+F
+Aborting due to very high failure rate
+6000 links established in 30.14 seconds
+Overlay link operations have been retried 15 times upon timeouts
+F
+Aborting due to very high failure rate
+6000 links established in 30.14 seconds
+Overlay link operations have been retried 16 times upon timeouts
+F
+Aborting due to very high failure rate
+6000 links established in 30.14 seconds
+Overlay link operations have been retried 17 times upon timeouts
diff --git a/contrib/testbed_infiniband_results/6000_connections_60000_peers_5_poc.txt b/contrib/testbed_infiniband_results/6000_connections_60000_peers_5_poc.txt
new file mode 100644
index 0000000000000000000000000000000000000000..62ed9f8421e02a6737b7a855b024df91dfe27bdf
--- /dev/null
+++ b/contrib/testbed_infiniband_results/6000_connections_60000_peers_5_poc.txt
@@ -0,0 +1,36 @@
+/home/totakura/local/bin/gnunet-helper-testbed
+/home/totakura/local/bin/gnunet-helper-testbed
+/home/totakura/local/bin/gnunet-helper-testbed
+/home/totakura/local/bin/gnunet-helper-testbed
+/home/totakura/local/bin/gnunet-helper-testbed
+/home/totakura/local/bin/gnunet-helper-testbed
+/home/totakura/local/bin/gnunet-helper-testbed
+/home/totakura/local/bin/gnunet-helper-testbed
+/home/totakura/local/bin/gnunet-helper-testbed
+/home/totakura/local/bin/gnunet-helper-testbed
+/home/totakura/local/bin/gnunet-helper-testbed
+/home/totakura/local/bin/gnunet-helper-testbed
+/home/totakura/local/bin/gnunet-helper-testbed
+/home/totakura/local/bin/gnunet-helper-testbed
+/home/totakura/local/bin/gnunet-helper-testbed
+/home/totakura/local/bin/gnunet-helper-testbed
+/home/totakura/local/bin/gnunet-helper-testbed
+/home/totakura/local/bin/gnunet-helper-testbed
+/home/totakura/local/bin/gnunet-helper-testbed
+/home/totakura/local/bin/gnunet-helper-testbed
+/home/totakura/local/bin/gnunet-helper-testbed
+/home/totakura/local/bin/gnunet-helper-testbed
+/home/totakura/local/bin/gnunet-helper-testbed
+/home/totakura/local/bin/gnunet-helper-testbed
+/home/totakura/local/bin/gnunet-helper-testbed
+/home/totakura/local/bin/gnunet-helper-testbed
+/home/totakura/local/bin/gnunet-helper-testbed
+/home/totakura/local/bin/gnunet-helper-testbed
+/home/totakura/local/bin/gnunet-helper-testbed
+29 controllers started successfully
+60000 peers created successfully in 254.00 seconds
+60000 peers started successfully in 50.20 seconds
+Establishing links. Please wait
+.FFFF.F.................F.............................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................
+6000 links established in 2305.66 seconds
+Overlay link operations have been retried 6 times upon timeouts
diff --git a/contrib/testbed_infiniband_results/6000_connections_80000_peers_20_poc.txt b/contrib/testbed_infiniband_results/6000_connections_80000_peers_20_poc.txt
new file mode 100644
index 0000000000000000000000000000000000000000..502bc72e30758fa67b77c51f116189da4b605419
--- /dev/null
+++ b/contrib/testbed_infiniband_results/6000_connections_80000_peers_20_poc.txt
@@ -0,0 +1,38 @@
+/home/totakura/local/bin/gnunet-helper-testbed
+/home/totakura/local/bin/gnunet-helper-testbed
+/home/totakura/local/bin/gnunet-helper-testbed
+/home/totakura/local/bin/gnunet-helper-testbed
+/home/totakura/local/bin/gnunet-helper-testbed
+/home/totakura/local/bin/gnunet-helper-testbed
+/home/totakura/local/bin/gnunet-helper-testbed
+/home/totakura/local/bin/gnunet-helper-testbed
+/home/totakura/local/bin/gnunet-helper-testbed
+/home/totakura/local/bin/gnunet-helper-testbed
+/home/totakura/local/bin/gnunet-helper-testbed
+/home/totakura/local/bin/gnunet-helper-testbed
+/home/totakura/local/bin/gnunet-helper-testbed
+/home/totakura/local/bin/gnunet-helper-testbed
+/home/totakura/local/bin/gnunet-helper-testbed
+/home/totakura/local/bin/gnunet-helper-testbed
+/home/totakura/local/bin/gnunet-helper-testbed
+/home/totakura/local/bin/gnunet-helper-testbed
+/home/totakura/local/bin/gnunet-helper-testbed
+/home/totakura/local/bin/gnunet-helper-testbed
+/home/totakura/local/bin/gnunet-helper-testbed
+/home/totakura/local/bin/gnunet-helper-testbed
+/home/totakura/local/bin/gnunet-helper-testbed
+/home/totakura/local/bin/gnunet-helper-testbed
+/home/totakura/local/bin/gnunet-helper-testbed
+/home/totakura/local/bin/gnunet-helper-testbed
+/home/totakura/local/bin/gnunet-helper-testbed
+/home/totakura/local/bin/gnunet-helper-testbed
+/home/totakura/local/bin/gnunet-helper-testbed
+29 controllers started successfully
+80000 peers created successfully in 360.78 seconds
+80000 peers started successfully in 77.87 seconds
+Establishing links. Please wait
+............FFFFFFFFFFFF...F..........FF...F...................FFFFFFF.......FF.F.....F........................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................
+Aborting due to very high failure rate
+6000 links established in 1283.11 seconds
+Overlay link operations have been retried 62 times upon timeouts
+t
diff --git a/contrib/testbed_infiniband_results/6000_connections_80000_peers_5_poc.txt b/contrib/testbed_infiniband_results/6000_connections_80000_peers_5_poc.txt
new file mode 100644
index 0000000000000000000000000000000000000000..b3f4e6415d3bd01ded2c9c983d19e8a24b08bf5d
--- /dev/null
+++ b/contrib/testbed_infiniband_results/6000_connections_80000_peers_5_poc.txt
@@ -0,0 +1,22 @@
+/home/totakura/local/bin/gnunet-helper-testbed
+/home/totakura/local/bin/gnunet-helper-testbed
+/home/totakura/local/bin/gnunet-helper-testbed
+/home/totakura/local/bin/gnunet-helper-testbed
+/home/totakura/local/bin/gnunet-helper-testbed
+/home/totakura/local/bin/gnunet-helper-testbed
+/home/totakura/local/bin/gnunet-helper-testbed
+/home/totakura/local/bin/gnunet-helper-testbed
+/home/totakura/local/bin/gnunet-helper-testbed
+/home/totakura/local/bin/gnunet-helper-testbed
+/home/totakura/local/bin/gnunet-helper-testbed
+/home/totakura/local/bin/gnunet-helper-testbed
+/home/totakura/local/bin/gnunet-helper-testbed
+/home/totakura/local/bin/gnunet-helper-testbed
+/home/totakura/local/bin/gnunet-helper-testbed
+/home/totakura/local/bin/gnunet-helper-testbed
+/home/totakura/local/bin/gnunet-helper-testbed
+/home/totakura/local/bin/gnunet-helper-testbed
+/home/totakura/local/bin/gnunet-helper-testbed
+/home/totakura/local/bin/gnunet-helper-testbed
+/home/totakura/local/bin/gnunet-helper-testbed
+/home/totakura/local/bin/gnunet-helper-testbed
diff --git a/contrib/vagrant/Vagrantfile b/contrib/vagrant/Vagrantfile
new file mode 100644
index 0000000000000000000000000000000000000000..d6b671b24c3010b727283852b5d2b8390f92a771
--- /dev/null
+++ b/contrib/vagrant/Vagrantfile
@@ -0,0 +1,55 @@
+# -*- mode: ruby -*-
+# vi: set ft=ruby :
+#
+# Source https://github.com/alxn/vpp/blob/master/build-root/vagrant/Vagrantfile
+
+Vagrant.configure(2) do |config|
+
+  config.vm.box = "bento/ubuntu-16.04"
+  config.vm.box_version = "2.2.9"
+  config.vm.provision 'shell', path: 'bootstrap.ubuntu.sh'
+
+  # Add .gnupg dir in so folks can sign patches
+  # Note, as gnupg puts socket files in that dir, we have
+  # to be cautious and make sure we are dealing with a plain file
+  homedir = File.expand_path("~/")
+  Dir["#{homedir}/.gnupg/**/*"].each do |fname|
+    if File.file?(fname)
+      destname = fname.sub(Regexp.escape("#{homedir}/"),'')
+      config.vm.provision "file", source: fname, destination: destname
+    end
+  end
+
+  # Copy in the .gitconfig if it exists
+  if File.file?(File.expand_path("~/.gitconfig"))
+    config.vm.provision  "file", source: "~/.gitconfig", destination: ".gitconfig"
+  end
+
+  # vagrant-cachier caches apt/yum etc to speed subsequent
+  # vagrant up
+  # to enable, run
+  # vagrant plugin install vagrant-cachier
+  #
+  if Vagrant.has_plugin?("vagrant-cachier")
+    config.cache.scope = :box
+  end
+
+  # use http proxy if avaiable
+  if ENV['http_proxy'] && Vagrant.has_plugin?("vagrant-proxyconf")
+   config.proxy.http     = "$http_proxy"
+   config.proxy.https    = "$https_proxy"
+   config.proxy.no_proxy = "localhost,127.0.0.1"
+  end
+
+  config.vm.synced_folder "../../", "/gnunet", disabled: false
+  config.vm.provider "virtualbox" do |vb|
+    vb.memory = "4096"
+  end
+  config.vm.provider "vmware_fusion" do |fusion,override|
+    fusion.vmx["memsize"] = "4096"
+  end
+  config.vm.provider "vmware_workstation" do |vws,override|
+    vws.vmx["memsize"] = "4096"
+    vws.vmx["numvcpus"] = "4"
+  end
+end
diff --git a/contrib/vagrant/bootstrap.ubuntu.sh b/contrib/vagrant/bootstrap.ubuntu.sh
new file mode 100644
index 0000000000000000000000000000000000000000..f0b7c454efae1c6c0f2769bd40c1f05642f6dfed
--- /dev/null
+++ b/contrib/vagrant/bootstrap.ubuntu.sh
@@ -0,0 +1,48 @@
+#/bin/sh
+# Source https://gnunet.org/dependencies and README
+
+apt-get update
+
+# Install required tools
+apt-get -y install git build-essential gnupg curl openssl gnutls-bin miniupnpc
+
+# Autotools required for compiling
+apt-get -y install autoconf automake libtool autopoint
+
+# Tools for debugging
+apt-get -y install gdb valgrind
+
+# Direct dependencies obtained from README
+apt-get -y install libmicrohttpd-dev
+apt-get -y install libextractor-dev
+apt-get -y install libunistring-dev
+apt-get -y install libidn11-dev
+apt-get -y install libgcrypt20-dev
+apt-get -y install libgnutls30-dev
+apt-get -y install libltdl-dev
+apt-get -y install libcurl3
+apt-get -y install sqlite3 libsqlite3-dev
+apt-get -y install zlib1g-dev
+# apt-get -y install texlive-full # Skipped > 1GB
+# optional for gnunet-conversation
+# apt-get -y install libpulse-dev libopus-dev libogg-dev gstreamer1.0
+# optional for gnunet-qr
+apt-get -y install libzbar-dev
+# optional for experimental code
+apt-get -y install libglpk-dev
+#
+apt-get -y install libbluetooth-dev libjansson-dev
+
+# Compilation process
+addgroup gnunetdns
+adduser --system --home "/var/lib/gnunet" --group gnunet --shell /bin/sh
+# cd /gnunet
+# . bootstrap
+# export GNUNET_PREFIX=/usr/local/lib # or other directory of your choice
+# ./configure --prefix=$GNUNET_PREFIX/.. --with-extractor=$LE_PREFIX
+# make
+# make install
+# make check
+# echo "/usr/local/lib/gnunet" > /etc/ld.so.conf.d/libgnunet.conf
+# ldconfig
+# sudo -u gnunet gnunet-arm -s
diff --git a/contrib/web/log.php b/contrib/web/log.php
new file mode 100644
index 0000000000000000000000000000000000000000..b2ca9ed6cde69f7cd88386b6851ba249532b7bf2
--- /dev/null
+++ b/contrib/web/log.php
@@ -0,0 +1,379 @@
+<?php
+
+$path='log';
+$lines = array();
+$peers = array();
+$comps = array();
+$ajax = FALSE;
+$colors = array('#F00', '#F80', '#FF0',
+                '#4F0', '#0A0',
+                '#22F', '#ADF', '#0FF', '#F0F', '#508', '#FAA',
+                '#FFF', '#AAA', '#666', '#222');
+
+function render_row ($d, $component, $pid, $level, $msg, $c)
+{
+  global $ajax;
+  global $peers;
+  if (!$ajax && $level == "DEBUG")
+    return;
+
+  list($comp,$peer) = explode (',', preg_replace ('/(.*)-(\d*)/', '\1,\2', $component));
+  $peer = array_key_exists ($peer, $peers) ? $peers[$peer] : $peer;
+  $date = $d ? $d->format('Y-m-d'). $d->format('H:i:s') : "";
+  echo "<tr class=\"$level P-$peer C-$comp\" id=\"$c\">";
+  echo "<td class=\"date\"><small>$date</td>";
+  echo '<td class="usec"><small>';
+  echo $d ? $d->format('u') : "";
+  echo '</small></td>';
+  echo "<td class=\"comp\">$comp</td><td class=\"peer\">$peer</td>";
+  echo "<td class=\"level\">$level</td><td><pre>$msg</pre></td>";
+  if ($level != "DEBUG")
+  {
+    echo '<td><div class="btn-group"><button class="btn btn-xs btn-default btn-showup"><span class="glyphicon glyphicon-chevron-up"></span></button>';
+    echo '<button class="btn btn-xs btn-default btn-showdown"><span class="glyphicon glyphicon-chevron-down"></span></button></div></td>';
+  }
+  else
+    echo '<td></td>';
+  echo '</tr>';
+}
+
+function render_rows ()
+{
+  global $lines;
+  foreach ($lines as $line) {
+    render_row ($line[0], $line[1], $line[2], $line[3], $line[4], $line[5]);
+  }
+}
+
+function process ($line, $c)
+{
+  global $lines;
+  global $peers;
+  global $comps;
+  $a = explode (' ', $line);
+  if (count($a) < 6)
+    return;
+  $date = DateTime::createFromFormat ("M d H:i:s-u", implode (' ', array_slice ($a, 0, 3)));
+  $component = $a[3];
+  $level = $a[4];
+  $msg = implode (' ', array_slice ($a, 5));
+
+  if (FALSE !== strpos($line, "STARTING SERVICE")) {
+    $id = preg_replace ("/.*\[(....)\].*\n/", '\1', $line);
+    $pid = preg_replace ("/.*[a-z-]*-([0-9]*).*\n/", '\1', $line);
+    $peers[$pid] = $id;
+  }
+
+  $lines[] = array ($date, $component, 0, $level, $msg, $c);
+  $comp = preg_replace ('/(.*)-\d*/', '\1', $component);
+  $comps[$comp] = 1;
+}
+
+if (array_key_exists ('a', $_GET)) {
+  $start = (int)$_GET['a'];
+  $ajax= TRUE;
+}
+else
+{
+  $start = null;
+}
+if (array_key_exists ('z', $_GET)) {
+  $stop = (int)$_GET['z'];
+  $ajax= TRUE;
+}
+else
+{
+  $stop = null;
+}
+$t0 = microtime(true);
+$handle = @fopen($path, 'r');
+if ($handle) {
+    $c = 0;
+    while (($line = fgets($handle)) !== false) {
+	if (!$start || $c >= $start) {
+	  process ($line, $c);
+	}
+	$c++;
+	if ($stop && $c > $stop)
+	  break;
+    }
+} else {
+   echo "<div class=\"alert alert-danger\">Error opening file $path.</div>";
+}
+
+$t1 = microtime(true);
+/* Ajax request: don't render container HTML, just table rows. */
+if ($start !== null || $stop !== null) {
+  render_rows();
+  die();
+}
+// echo $t1-$t0;
+ksort($peers);
+ksort($comps);
+?>
+<!DOCTYPE html>
+<html lang="en">
+<head>
+  <meta charset="utf-8">
+  <meta http-equiv="X-UA-Compatible" content="IE=edge">
+  <meta name="viewport" content="width=device-width, initial-scale=1">
+
+  <title>GNUnet log view</title>
+
+  <!-- Latest compiled and minified Bootstrap CSS -->
+  <link rel="stylesheet" href="//netdna.bootstrapcdn.com/bootstrap/3.1.0/css/bootstrap.min.css">
+  <!-- Optional theme -->
+  <link rel="stylesheet" href="//netdna.bootstrapcdn.com/bootstrap/3.1.0/css/bootstrap-theme.min.css">
+
+  <style>
+    body {
+      font-family: arial,sans-serif;
+    }
+    table {
+      color:#000;
+      margin-top: 40px;
+      font-size:12px;
+      border-collapse:collapse;
+    }
+    pre {
+      padding: 0px;
+      margin: 0px;
+      border: 0px;
+      background-color: transparent;
+    }
+    .alert {
+      display: none;
+      position: fixed;
+      width: 75%;
+      left: 50%;
+      margin: 5% 0 0 -37.5%;
+    }
+    .btn-toolbar {
+      position: fixed;
+      top: 0px;
+    }
+    .btn-xs {
+      font-size: 9px;
+      padding: 0 5px;
+    }
+    .level {
+      display: none;
+    }
+    .DEBUG {
+      background-color:#CCC;
+    }
+    .WARNING {
+      background-color:#EB9316;
+    }
+    .ERROR {
+      background-color:#D2322D;
+    }
+    .btn-group {
+      min-width: 48px;
+    }
+    table.table tbody tr td,
+    table.table tbody th td {
+      padding: 0px 0px 0px 2px;
+      margin-bottom: 0px;
+    }
+<?php
+    $c = 0;
+    foreach ($peers as $peer) {
+      echo "table.table tbody tr.P-$peer td.peer {\n";
+      echo '  background-color: ' . $colors[$c] . ";\n";
+      echo "}\n";
+      echo "#P-$peer { color: " . $colors[$c++] . "}\n";
+    } ?>
+  </style>
+</head>
+
+
+<body>
+<div class="btn-toolbar" role="toolbar">
+  <div class="btn-group">
+    <button id="ERROR" class="btn btn-danger btn-showlevel"><span class="glyphicon glyphicon-fire"></span> Error</button>
+    <button id="WARNING" class="btn btn-warning btn-showlevel"><span class="glyphicon glyphicon-exclamation-sign"></span> Warning</button>
+    <button id="INFO" class="btn btn-default btn-showlevel active"><span class="glyphicon glyphicon glyphicon-info-sign"></span> Info</button>
+    <button id="DEBUG" class="btn btn-primary btn-showlevel"><span class="glyphicon glyphicon glyphicon-wrench"></span> Debug</button>
+  </div>
+  <div id="btn-showpeer" class="btn-group">
+    <?php foreach($peers as $pid=>$id): ?>
+    <button id="P-<?php echo $id ?>" class="btn btn-default btn-element active"><?php echo $id ?></button>
+    <?php endforeach ?>
+    <button class="btn btn-default btn-showall">All</button>
+    <button class="btn btn-default btn-shownone">None</button>
+  </div>
+  <div id="btn-showcomp" class="btn-group">
+    <?php foreach($comps as $c=>$one): ?>
+    <button id="C-<?php echo $c ?>" class="btn btn-default btn-element active"><?php echo $c ?></button>
+    <?php endforeach ?>
+    <button class="btn btn-default btn-showall">All</button>
+    <button class="btn btn-default btn-shownone">None</button>
+  </div>
+</div>
+<div id="msg" class="alert alert-success"></div>
+<table class="table">
+  <thead>
+  <tr>
+    <th>Date Time</th>
+    <th>uSec</th>
+    <th>Comp</th>
+    <th>Peer</th>
+    <th class="level">Level</th>
+    <th>Message</th>
+    <th></th>
+  </tr>
+  </thead>
+  <tbody>
+<?php render_rows(); ?>
+  </tbody>default
+</table>
+<p>Processed in <?php echo $t1-$t0; ?> seconds.</p>
+<p>Rendered in <?php echo microtime(true)-$t1; ?> seconds.</p>
+  <!-- jQuery -->
+  <script src="http://code.jquery.com/jquery-1.10.1.min.js"></script>
+  <!-- Latest compiled and minified Bootstrap JavaScript -->
+  <script src="//netdna.bootstrapcdn.com/bootstrap/3.1.0/js/bootstrap.min.js"></script>
+
+  <script>
+
+    var types = ["ERROR", "WARNING", "INFO", "DEBUG"];
+    var peers = {<?php foreach($peers as $pid=>$id) echo "'$pid': '$id', "; ?>};
+    var msg_timeout;
+
+    function msg (content)
+    {
+      $("#msg").html(content);
+      $("#msg").stop(true);
+      $("#msg").fadeTo(100, 1).fadeTo(3000, 0.90).fadeOut(1000);
+    }
+
+    function showlevel (level)
+    {
+      $("tbody > tr").hide();
+      $(".btn-showlevel").removeClass("active");
+      $("#"+level).addClass("active");
+      for (var index = 0; index < types.length; ++index) {
+        $("#btn-showpeer > .btn-element.active").each(function(){
+	  var peer = this.id;
+	  $("#btn-showcomp > .btn-element.active").each(function(){
+	    $("."+types[index]+"."+peer+"."+this.id).show();
+	  });
+        });
+	if (types[index] == level)
+	  return;
+      }
+    }
+
+    function shownone(btn)
+    {
+      $(btn).parents(".btn-group").children(".btn-element.active").each(function(){$(this).click()});
+    }
+
+    function showall(btn)
+    {
+      $(btn).parents(".btn-group").children(".btn-element:not(.active)").each(function(){$(this).click()});
+    }
+
+    function showpeer (peer)
+    {
+      $("#"+peer).toggleClass("active");
+      if ($("#"+peer).hasClass("active")) {
+	$("#btn-showcomp > .btn-element.active").each(function(){
+	  for (var index = 0; index < types.length; ++index) {
+	    var className = "." + types[index] + "." + peer + "." + this.id;
+	    $(className).show();
+	    if ($("#"+types[index]).hasClass("active"))
+	      return;
+	  }
+	});
+      } else {
+        $("."+peer).hide();
+      }
+    }
+    
+    function showcomp (comp)
+    {
+      $("#"+comp).toggleClass("active");
+      if ($("#"+comp).hasClass("active")) {
+	$("#btn-showpeer > .btn-element.active").each(function(){
+	  for (var index = 0; index < types.length; ++index) {
+	    var className = "." + types[index] + "." + comp + "." + this.id;
+	    $(className).show();
+	    if ($("#"+types[index]).hasClass("active"))
+	      return;
+	  }
+	});
+      } else {
+        $("."+comp).hide();
+      }
+    }
+
+    function load_debug (btn, up)
+    {
+      var tr = $(btn).parents("tr");
+      var level;
+      var pos = parseInt(tr.attr("id"));
+      var first = pos + 1;
+      var last = pos - 1;
+      for (var index = 0; index < types.length; ++index) {
+        if (tr.hasClass(types[index]))
+        {
+          level = types[index];
+          break;
+        }
+      }
+      if (up) {
+	if (parseInt(tr.prev().attr("id")) == last) {
+	  msg ("Already loaded");
+	  return;
+	}
+	first = parseInt(tr.prevAll("."+level).first().attr("id")) + 1;
+	first = isNaN(first) ? 0 : first;
+      } else {
+	if (parseInt(tr.next().attr("id")) == first) {
+	  msg ("Already loaded");
+	  return;
+	}
+	last = parseInt(tr.nextAll("."+level).first().attr("id")) - 1;
+      }
+      if (first > last)
+	return;
+      $.ajax({
+	url: document.location,
+	data: { a: first, z: last }
+      }).done(function ( resp ) {
+	var loc = $("#"+(first-1));
+	var trs = $(resp);
+        for (var peer in peers) {
+          trs.filter(".P-"+peer).removeClass('P-'+peer).addClass('P-'+peers[peer]).find("td.peer").html(peers[peer]);
+        }
+	if (loc.length > 0)
+	  loc.after(trs);
+	else {
+	  $("#"+(last+1)).before(trs);
+	}
+	msg("Done loading " + (last-first+1) + " lines.");
+      });
+      //tr.nextUntil("."+tr.attr("class")).show();
+
+    }
+
+    function hide (btn)
+    {
+      var tr = $(btn).parents("tr");
+      tr.nextUntil("."+tr.attr("class")).hide();
+    }
+
+    $(function() {
+      $(".btn-showup").on ("click", function(){ load_debug(this, true) });
+      $(".btn-showdown").on ("click", function(){ load_debug(this, false) });
+      $(".btn-showlevel").on ("click", function(){ showlevel(this.id) });
+      $("#btn-showpeer > .btn-element").on ("click", function(){ showpeer(this.id) });
+      $("#btn-showcomp > .btn-element").on ("click", function(){ showcomp(this.id) });
+      $(".btn-showall").on ("click", function(){ showall(this) });
+      $(".btn-shownone").on ("click", function(){ shownone(this) });
+    });
+  </script>
+</body>
+</html>
diff --git a/doc/.gitignore b/doc/.gitignore
new file mode 100644
index 0000000000000000000000000000000000000000..b12f3e008b37af4d1e79524f3fe669aa6099460c
--- /dev/null
+++ b/doc/.gitignore
@@ -0,0 +1,22 @@
+*.aux
+*.out
+*.log
+*.pdf
+*.toc
+*.cp
+*.cps
+*~
+*.info
+*.info-1
+*.info-2
+*.info-3
+\#*\#
+version.texi
+mdate-sh
+stamp-vti
+texinfo.tex
+gnunet.t2p/
+gnunet-c-tutorial.t2p/
+*.t2p/
+documentation/manuals
+.\#*doxygen/gnunet.tag
diff --git a/doc/coverage.txt b/doc/coverage.txt
new file mode 100644
index 0000000000000000000000000000000000000000..7f9466e4b359261285b8212368942a1d2ccb7a20
--- /dev/null
+++ b/doc/coverage.txt
@@ -0,0 +1,67 @@
+Summary of test coverage (configure with --enable-coverage
+and run contrib/coverage.sh to generate a detailed report):
+* UTIL      : 77.8%
+* HELLO     : 93.4%
+* ARM       : 69.2%
+* RESOLVER  : 60.9%
+* STATISTICS: 84.1%
+* PEERINFO  : 71.5%
+* TRANSPORT : 68.6%
+* CORE      : 65.3%
+* DATACACHE : 79.8%
+* DATASTORE : 78.9%
+===================
+* TOTAL     : 74.6%
+
+Not yet tested (but presumably implemented):
+* HOSTLIST  :  0.0%
+* TOPOLOGY  :  0.0%
+
+
+TESTCASES WANTED:
+=================
+
+For these functions, it would be nice if we had testcases ("make check")
+that would cause them to be executed and check that they are working:
+* gnunet-service-peerinfo:
+  - change_host_trust / flush_trust 
+  - remove_garbage 
+  - discard_hosts_helper / cron_clean_data_hosts
+* gnunet-service-transport:
+  - try_unvalidated_addresses
+  - lookup_address_callback
+  - lookup_hello_callback
+  - plugin_env_lookup_address
+  - notify_clients_disconnect
+  - list_validated_addresses
+  - cleanup_validation
+  - disconnect_neighbour
+  - handle_set_quota
+* plugin_transport_tcp.c:
+  - tcp_plugin_cancel
+  - tcp_plugin_address_pretty_printer / append_port
+  - tcp_plugin_set_receive_quota
+  - delayed_done
+* transport_api:
+  - GNUNET_TRANSPORT_set_qutoa / send_set_quota
+  - hello_wait_timeout 
+  - transmit_ready
+  - transmit_timeout
+  - remove_from_any_list / remove_neighbour
+  - GNUNET_TRANSPORT_notify_transmit_ready_cancel
+  - Testcases for set_quota, timeouts, disconnects, transmit_ready_cancel
+  - gnunet-service-transport HELLO validation (how good is our coverage?)
+  - direct test of plugins compliance to plugin API
+* core_api:
+  - timeout_request
+  - solicit_traffic / copy_and_free
+  - GNUNET_CORE_peer_configure / produce_configure_message
+* gnunet-service-core:
+  - update_window
+  - find_client
+  - handle_client_request_configure
+  - set_key_retry_task
+  - align_and_deliver
+  - handle_transport_notify_disconnect
+* hostlist (everything)
+* topology (everything)
diff --git a/doc/doc.h b/doc/doc.h
new file mode 100644
index 0000000000000000000000000000000000000000..db079e94aa54f2c33a019cdf3020bfe55978d0eb
--- /dev/null
+++ b/doc/doc.h
@@ -0,0 +1,11 @@
+/**
+ * @mainpage GNUnet documentation
+ *
+ * @section Introduction
+ *
+ * See the [Modules](modules.html) section for documentation of the various services, APIs and libraries of GNUnet.
+ *
+ * Some additional documentation can be found under [Files](files.html), in the src/include/ directory.
+ *
+ * See also the [handbooks](https://docs.gnunet.org/) on installation, and for user and developer documentation.
+ */
diff --git a/doc/docstyle.css b/doc/docstyle.css
new file mode 100644
index 0000000000000000000000000000000000000000..8719248d03cd072c9fb998ba35ef3473dec4641d
--- /dev/null
+++ b/doc/docstyle.css
@@ -0,0 +1,76 @@
+html, body {
+    font-size: 1em;
+    text-align: left;
+    text-decoration: none;
+}
+html { background-color: #e7e7e7; }
+
+body {
+    max-width: 74.92em;
+    margin: 0 auto;
+    padding: .5em 1em 1em 1em;
+    background-color: white;
+    border: .1em solid #c0c0c0;
+}
+
+h1, h2, h3, h4 { color: #333; }
+h5, h6, dt { color: #222; }
+
+
+a h3 {
+    color: #005090;
+}
+
+a[href] { color: #005090; }
+a[href]:visited { color: #100070; }
+a[href]:active, a[href]:hover {
+    color: #100070;
+    text-decoration: none;
+}
+
+.linkrow {
+    margin: 3em 0;
+}
+
+.linkrow {
+    text-align: center;
+}
+
+div.example { padding: .8em 1.2em .4em; }
+pre.example { padding: .8em 1.2em; }
+div.example, pre.example {
+    margin: 1em 0 1em 3% ;
+    -webkit-border-radius: .3em;
+    -moz-border-radius: .3em;
+    border-radius: .3em;
+    border: 1px solid #d4cbb6;
+    background-color: #f2efe4;
+}
+div.example > pre.example {
+    padding: 0 0 .4em;
+    margin: 0;
+    border: none;
+}
+
+
+/* This makes the very long tables of contents in Gnulib and other
+   manuals easier to read. */
+.contents ul, .shortcontents ul { font-weight: bold; }
+.contents ul ul, .shortcontents ul ul { font-weight: normal; }
+.contents ul { list-style: none; }
+
+/* For colored navigation bars (Emacs manual): make the bar extend
+   across the whole width of the page and give it a decent height. */
+.header, .node { margin: 0 -1em; padding: 0 1em; }
+.header p, .node p { line-height: 2em; }
+
+/* For navigation links */
+.node a, .header a { display: inline-block; line-height: 2em; }
+.node a:hover, .header a:hover { background: #f2efe4; }
+
+table.cartouche {
+    border-collapse: collapse;
+    border-color: darkred;
+    border-style: solid;
+    border-width: 3px;
+}
diff --git a/doc/doxygen/logo.png b/doc/doxygen/logo.png
new file mode 100644
index 0000000000000000000000000000000000000000..aa24430469138b4a6c92cc70985590105c2cf912
Binary files /dev/null and b/doc/doxygen/logo.png differ
diff --git a/doc/handbook/.gitignore b/doc/handbook/.gitignore
new file mode 100644
index 0000000000000000000000000000000000000000..80ac74ea05b8812614612d50adab06fb8df5310b
--- /dev/null
+++ b/doc/handbook/.gitignore
@@ -0,0 +1,11 @@
+stamp-1
+version2.texi
+manual
+*.fn
+*.fns
+*.ky
+*.pg
+*.tp
+*.vr
+gnunet 
+gnunet.html
diff --git a/doc/handbook/chapters/developer.texi b/doc/handbook/chapters/developer.texi
index 6d8ddd3c2aec526ec552cbeddd6721f5a09e57dd..369e5327c1f95407b28c428b02ba9cdc083cbaa0 100644
--- a/doc/handbook/chapters/developer.texi
+++ b/doc/handbook/chapters/developer.texi
@@ -71,6 +71,8 @@ new chapters, sections or insightful comments.
 * PEERINFO Subsystem::
 * PEERSTORE Subsystem::
 * SET Subsystem::
+* SETI Subsystem::
+* SETU Subsystem::
 * STATISTICS Subsystem::
 * Distributed Hash Table (DHT)::
 * GNU Name System (GNS)::
@@ -6535,10 +6537,13 @@ destroyed as well.
 @node SET Subsystem
 @section SET Subsystem
 
-
+The SET subsystem is in process of being replaced by the SETU and
+SETI subsystems, which provide basically the same functionality,
+just using two different subsystems.  SETI and SETU should be used
+for new code.
 
 The SET service implements efficient set operations between two peers
-over a mesh tunnel.
+over a CADET tunnel.
 Currently, set union and set intersection are the only supported
 operations. Elements of a set consist of an @emph{element type} and
 arbitrary binary @emph{data}.
@@ -6907,6 +6912,513 @@ All Bloom filter operations use a salt to mingle keys before hashing them
 into buckets, such that future iterations have a fresh chance of
 succeeding if they failed due to collisions before.
 
+
+
+
+
+
+
+
+@cindex SETI Subsystem
+@node SETI Subsystem
+@section SETI Subsystem
+
+The SET service implements efficient set intersection between two peers
+over a CADET tunnel.
+Elements of a set consist of an @emph{element type} and
+arbitrary binary @emph{data}.
+The size of an element's data is limited to around 62 KB.
+
+@menu
+* Intersection Sets::
+* Set Intersection Modifications::
+* Set Intersection Operations::
+* Intersection Result Elements::
+* libgnunetseti::
+* The SETI Client-Service Protocol::
+* The SETI Intersection Peer-to-Peer Protocol::
+@end menu
+
+@node Intersection Sets
+@subsection Intersection Sets
+
+Sets created by a local client can be modified (by adding additional elements)
+and reused for multiple operations.  If elements are to be removed, a fresh
+set must be created by the client.
+
+@node Set Intersection Modifications
+@subsection Set Intersection Modifications
+
+Even when set operations are active, one can add elements
+to a set.
+However, these changes will only be visible to operations that have been
+created after the changes have taken place. That is, every set operation
+only sees a snapshot of the set from the time the operation was started.
+This mechanism is @emph{not} implemented by copying the whole set, but by
+attaching @emph{generation information} to each element and operation.
+
+@node Set Intersection Operations
+@subsection Set Intersection Operations
+
+Set operations can be started in two ways: Either by accepting an
+operation request from a remote peer, or by requesting a set operation
+from a remote peer.
+Set operations are uniquely identified by the involved @emph{peers}, an
+@emph{application id} and the @emph{operation type}.
+
+The client is notified of incoming set operations by @emph{set listeners}.
+A set listener listens for incoming operations of a specific operation
+type and application id.
+Once notified of an incoming set request, the client can accept the set
+request (providing a local set for the operation) or reject it.
+
+@node Intersection Result Elements
+@subsection Intersection Result Elements
+
+The SET service has two @emph{result modes} that determine how an
+operation's result set is delivered to the client:
+
+@itemize @bullet
+@item @strong{Return intersection.} All elements of set resulting from the set
+intersection are returned to the client.
+@item @strong{Removed Elements.} Only elements that are in the local
+peer's initial set but not in the intersection are returned.
+@end itemize
+
+@cindex libgnunetseti
+@node libgnunetseti
+@subsection libgnunetseti
+
+@menu
+* Intersection Set API::
+* Intersection Listeners::
+* Intersection Operations::
+* Supplying a Set for Intersection::
+* The Intersection Result Callback::
+@end menu
+
+@node Intersection Set API
+@subsubsection Intersection Set API
+
+New sets are created with @code{GNUNET_SETI_create}. Only the local peer's
+configuration (as each set has its own client connection) must be provided.
+The set exists until either the client calls @code{GNUNET_SET_destroy} or
+the client's connection to the service is disrupted.
+In the latter case, the client is notified by the return value of
+functions dealing with sets. This return value must always be checked.
+
+Elements are added with @code{GNUNET_SET_add_element}.
+
+@node Intersection Listeners
+@subsubsection Intersection Listeners
+
+Listeners are created with @code{GNUNET_SET_listen}. Each time time a
+remote peer suggests a set operation with an application id and operation
+type matching a listener, the listener's callback is invoked.
+The client then must synchronously call either @code{GNUNET_SET_accept}
+or @code{GNUNET_SET_reject}. Note that the operation will not be started
+until the client calls @code{GNUNET_SET_commit}
+(see Section "Supplying a Set").
+
+@node Intersection Operations
+@subsubsection Intersection Operations
+
+Operations to be initiated by the local peer are created with
+@code{GNUNET_SET_prepare}. Note that the operation will not be started
+until the client calls @code{GNUNET_SET_commit}
+(see Section "Supplying a Set").
+
+@node Supplying a Set for  Intersection
+@subsubsection Supplying a Set for Intersection
+
+To create symmetry between the two ways of starting a set operation
+(accepting and initiating it), the operation handles returned by
+@code{GNUNET_SET_accept} and @code{GNUNET_SET_prepare} do not yet have a
+set to operate on, thus they can not do any work yet.
+
+The client must call @code{GNUNET_SET_commit} to specify a set to use for
+an operation. @code{GNUNET_SET_commit} may only be called once per set
+operation.
+
+@node The Intersection Result Callback
+@subsubsection The Intersection Result Callback
+
+Clients must specify both a result mode and a result callback with
+@code{GNUNET_SET_accept} and @code{GNUNET_SET_prepare}. The result
+callback with a status indicating either that an element was received, or
+the operation failed or succeeded.
+The interpretation of the received element depends on the result mode.
+The callback needs to know which result mode it is used in, as the
+arguments do not indicate if an element is part of the full result set,
+or if it is in the difference between the original set and the final set.
+
+@node The SETI Client-Service Protocol
+@subsection The SETI Client-Service Protocol
+
+@menu
+* Creating Intersection Sets::
+* Listeners for Intersection::
+* Initiating Intersection Operations::
+* Modifying Intersection Sets::
+* Intersection Results and Operation Status::
+@end menu
+
+@node Creating Intersection Sets
+@subsubsection Creating Intersection Sets
+
+For each set of a client, there exists a client connection to the service.
+Sets are created by sending the @code{GNUNET_SERVICE_SETI_CREATE} message
+over a new client connection. Multiple operations for one set are
+multiplexed over one client connection, using a request id supplied by
+the client.
+
+@node Listeners for Intersection
+@subsubsection Listeners for Intersection
+
+Each listener also requires a seperate client connection. By sending the
+@code{GNUNET_SERVICE_SETI_LISTEN} message, the client notifies the service
+of the application id and operation type it is interested in. A client
+rejects an incoming request by sending @code{GNUNET_SERVICE_SETI_REJECT}
+on the listener's client connection.
+In contrast, when accepting an incoming request, a
+@code{GNUNET_SERVICE_SETI_ACCEPT} message must be sent over the@ set that
+is supplied for the set operation.
+
+@node Initiating Intersection Operations
+@subsubsection Initiating Intersection Operations
+
+Operations with remote peers are initiated by sending a
+@code{GNUNET_SERVICE_SETI_EVALUATE} message to the service. The@ client
+connection that this message is sent by determines the set to use.
+
+@node Modifying Intersection Sets
+@subsubsection Modifying Intersection Sets
+
+Sets are modified with the @code{GNUNET_SERVICE_SETI_ADD} message.
+
+
+@c %@menu
+@c %* Results and Operation Status::
+@c %* Iterating Sets::
+@c %@end menu
+
+@node Intersection Results and Operation Status
+@subsubsection Intersection Results and Operation Status
+
+The service notifies the client of result elements and success/failure of
+a set operation with the @code{GNUNET_SERVICE_SETI_RESULT} message.
+
+@node The SETI Intersection Peer-to-Peer Protocol
+@subsection The SETI Intersection Peer-to-Peer Protocol
+
+The intersection protocol operates over CADET and starts with a
+GNUNET_MESSAGE_TYPE_SETI_P2P_OPERATION_REQUEST being sent by the peer
+initiating the operation to the peer listening for inbound requests.
+It includes the number of elements of the initiating peer, which is used
+to decide which side will send a Bloom filter first.
+
+The listening peer checks if the operation type and application
+identifier are acceptable for its current state.
+If not, it responds with a GNUNET_MESSAGE_TYPE_SETI_RESULT and a status of
+GNUNET_SETI_STATUS_FAILURE (and terminates the CADET channel).
+
+If the application accepts the request, the listener sends back a
+@code{GNUNET_MESSAGE_TYPE_SETI_P2P_ELEMENT_INFO} if it has
+more elements in the set than the client.
+Otherwise, it immediately starts with the Bloom filter exchange.
+If the initiator receives a
+@code{GNUNET_MESSAGE_TYPE_SETI_P2P_ELEMENT_INFO} response,
+it beings the Bloom filter exchange, unless the set size is indicated to
+be zero, in which case the intersection is considered finished after
+just the initial handshake.
+
+
+@menu
+* The Bloom filter exchange in SETI::
+* Intersection Salt::
+@end menu
+
+@node The Bloom filter exchange in SETI
+@subsubsection The Bloom filter exchange in SETI
+
+In this phase, each peer transmits a Bloom filter over the remaining
+keys of the local set to the other peer using a
+@code{GNUNET_MESSAGE_TYPE_SETI_P2P_BF} message. This
+message additionally includes the number of elements left in the sender's
+set, as well as the XOR over all of the keys in that set.
+
+The number of bits 'k' set per element in the Bloom filter is calculated
+based on the relative size of the two sets.
+Furthermore, the size of the Bloom filter is calculated based on 'k' and
+the number of elements in the set to maximize the amount of data filtered
+per byte transmitted on the wire (while avoiding an excessively high
+number of iterations).
+
+The receiver of the message removes all elements from its local set that
+do not pass the Bloom filter test.
+It then checks if the set size of the sender and the XOR over the keys
+match what is left of its own set. If they do, it sends a
+@code{GNUNET_MESSAGE_TYPE_SETI_P2P_DONE} back to indicate
+that the latest set is the final result.
+Otherwise, the receiver starts another Bloom filter exchange, except
+this time as the sender.
+
+@node Intersection Salt
+@subsubsection Intersection Salt
+
+Bloom filter operations are probabilistic: With some non-zero probability
+the test may incorrectly say an element is in the set, even though it is
+not.
+
+To mitigate this problem, the intersection protocol iterates exchanging
+Bloom filters using a different random 32-bit salt in each iteration (the
+salt is also included in the message).
+With different salts, set operations may fail for different elements.
+Merging the results from the executions, the probability of failure drops
+to zero.
+
+The iterations terminate once both peers have established that they have
+sets of the same size, and where the XOR over all keys computes the same
+512-bit value (leaving a failure probability of 2-511).
+
+
+@cindex SETU Subsystem
+@node SETU Subsystem
+@section SETU Subsystem
+
+The SETU service implements efficient set union operations between two peers
+over a CADET tunnel.  Elements of a set consist of an @emph{element type} and
+arbitrary binary @emph{data}.  The size of an element's data is limited to
+around 62 KB.
+
+@menu
+* Union Sets::
+* Set Union Modifications::
+* Set Union Operations::
+* Union Result Elements::
+* libgnunetsetu::
+* The SETU Client-Service Protocol::
+* The SETU Union Peer-to-Peer Protocol::
+@end menu
+
+@node Union Sets
+@subsection Union Sets
+
+Sets created by a local client can be modified (by adding additional elements)
+and reused for multiple operations.  If elements are to be removed, a fresh
+set must be created by the client.
+
+@node Set Union Modifications
+@subsection Set Union Modifications
+
+Even when set operations are active, one can add elements
+to a set.
+However, these changes will only be visible to operations that have been
+created after the changes have taken place. That is, every set operation
+only sees a snapshot of the set from the time the operation was started.
+This mechanism is @emph{not} implemented by copying the whole set, but by
+attaching @emph{generation information} to each element and operation.
+
+@node Set Union Operations
+@subsection Set Union Operations
+
+Set operations can be started in two ways: Either by accepting an
+operation request from a remote peer, or by requesting a set operation
+from a remote peer.
+Set operations are uniquely identified by the involved @emph{peers}, an
+@emph{application id} and the @emph{operation type}.
+
+The client is notified of incoming set operations by @emph{set listeners}.
+A set listener listens for incoming operations of a specific operation
+type and application id.
+Once notified of an incoming set request, the client can accept the set
+request (providing a local set for the operation) or reject it.
+
+@node Union Result Elements
+@subsection Union Result Elements
+
+The SET service has three @emph{result modes} that determine how an
+operation's result set is delivered to the client:
+
+@itemize @bullet
+@item @strong{Locally added Elements.} Elements that are in the union
+but not already in the local peer's set are returned.
+@item @strong{Remote added Elements.} Additionally, notify the client
+if the remote peer lacked some elements and thus also return to the
+local client those elements that we are sending to the remote peer to
+be added to its union.  Obtaining these elements requires setting
+the @code{GNUNET_SETU_OPTION_SYMMETRIC} option.
+@end itemize
+
+@cindex libgnunetsetu
+@node libgnunetsetu
+@subsection libgnunetsetu
+
+@menu
+* Union Set API::
+* Union Listeners::
+* Union Operations::
+* Supplying a Set for Union::
+* The Union Result Callback::
+@end menu
+
+@node Union Set API
+@subsubsection Union Set API
+
+New sets are created with @code{GNUNET_SETU_create}. Only the local peer's
+configuration (as each set has its own client connection) must be provided.
+The set exists until either the client calls @code{GNUNET_SETU_destroy} or
+the client's connection to the service is disrupted.
+In the latter case, the client is notified by the return value of
+functions dealing with sets. This return value must always be checked.
+
+Elements are added with @code{GNUNET_SETU_add_element}.
+
+@node Union Listeners
+@subsubsection Union Listeners
+
+Listeners are created with @code{GNUNET_SETU_listen}. Each time time a
+remote peer suggests a set operation with an application id and operation
+type matching a listener, the listener's callback is invoked.
+The client then must synchronously call either @code{GNUNET_SETU_accept}
+or @code{GNUNET_SETU_reject}. Note that the operation will not be started
+until the client calls @code{GNUNET_SETU_commit}
+(see Section "Supplying a Set").
+
+@node Union Operations
+@subsubsection Union Operations
+
+Operations to be initiated by the local peer are created with
+@code{GNUNET_SETU_prepare}. Note that the operation will not be started
+until the client calls @code{GNUNET_SETU_commit}
+(see Section "Supplying a Set").
+
+@node Supplying a Set for Union
+@subsubsection Supplying a Set for Union
+
+To create symmetry between the two ways of starting a set operation
+(accepting and initiating it), the operation handles returned by
+@code{GNUNET_SETU_accept} and @code{GNUNET_SETU_prepare} do not yet have a
+set to operate on, thus they can not do any work yet.
+
+The client must call @code{GNUNET_SETU_commit} to specify a set to use for
+an operation. @code{GNUNET_SETU_commit} may only be called once per set
+operation.
+
+@node The Union Result Callback
+@subsubsection The Union Result Callback
+
+Clients must specify both a result mode and a result callback with
+@code{GNUNET_SETU_accept} and @code{GNUNET_SETU_prepare}. The result
+callback with a status indicating either that an element was received,
+transmitted to the other peer (if this information was requested), or
+if the operation failed or ultimately succeeded.
+
+@node The SETU Client-Service Protocol
+@subsection The SETU Client-Service Protocol
+
+@menu
+* Creating Union Sets::
+* Listeners for Union::
+* Initiating Union Operations::
+* Modifying Union Sets::
+* Union Results and Operation Status::
+@end menu
+
+@node Creating Union Sets
+@subsubsection Creating Union Sets
+
+For each set of a client, there exists a client connection to the service.
+Sets are created by sending the @code{GNUNET_SERVICE_SETU_CREATE} message
+over a new client connection. Multiple operations for one set are
+multiplexed over one client connection, using a request id supplied by
+the client.
+
+@node Listeners for Union
+@subsubsection Listeners for Union
+
+Each listener also requires a seperate client connection. By sending the
+@code{GNUNET_SERVICE_SETU_LISTEN} message, the client notifies the service
+of the application id and operation type it is interested in. A client
+rejects an incoming request by sending @code{GNUNET_SERVICE_SETU_REJECT}
+on the listener's client connection.
+In contrast, when accepting an incoming request, a
+@code{GNUNET_SERVICE_SETU_ACCEPT} message must be sent over the@ set that
+is supplied for the set operation.
+
+@node Initiating Union Operations
+@subsubsection Initiating Union Operations
+
+
+
+Operations with remote peers are initiated by sending a
+@code{GNUNET_SERVICE_SETU_EVALUATE} message to the service. The@ client
+connection that this message is sent by determines the set to use.
+
+@node Modifying Union Sets
+@subsubsection Modifying Union Sets
+
+Sets are modified with the @code{GNUNET_SERVICE_SETU_ADD} message.
+
+
+@c %@menu
+@c %* Results and Operation Status::
+@c %* Iterating Sets::
+@c %@end menu
+
+@node Union Results and Operation Status
+@subsubsection Union Results and Operation Status
+
+The service notifies the client of result elements and success/failure of
+a set operation with the @code{GNUNET_SERVICE_SETU_RESULT} message.
+
+
+@node The SETU Union Peer-to-Peer Protocol
+@subsection The SETU Union Peer-to-Peer Protocol
+
+
+The SET union protocol is based on Eppstein's efficient set reconciliation
+without prior context. You should read this paper first if you want to
+understand the protocol.
+
+The union protocol operates over CADET and starts with a
+GNUNET_MESSAGE_TYPE_SETU_P2P_OPERATION_REQUEST being sent by the peer
+initiating the operation to the peer listening for inbound requests.
+It includes the number of elements of the initiating peer, which is
+currently not used.
+
+The listening peer checks if the operation type and application
+identifier are acceptable for its current state. If not, it responds with
+a @code{GNUNET_MESSAGE_TYPE_SETU_RESULT} and a status of
+@code{GNUNET_SETU_STATUS_FAILURE} (and terminates the CADET channel).
+
+If the application accepts the request, it sends back a strata estimator
+using a message of type GNUNET_MESSAGE_TYPE_SETU_P2P_SE. The
+initiator evaluates the strata estimator and initiates the exchange of
+invertible Bloom filters, sending a GNUNET_MESSAGE_TYPE_SETU_P2P_IBF.
+
+During the IBF exchange, if the receiver cannot invert the Bloom filter or
+detects a cycle, it sends a larger IBF in response (up to a defined
+maximum limit; if that limit is reached, the operation fails).
+Elements decoded while processing the IBF are transmitted to the other
+peer using GNUNET_MESSAGE_TYPE_SETU_P2P_ELEMENTS, or requested from the
+other peer using GNUNET_MESSAGE_TYPE_SETU_P2P_ELEMENT_REQUESTS messages,
+depending on the sign observed during decoding of the IBF.
+Peers respond to a GNUNET_MESSAGE_TYPE_SETU_P2P_ELEMENT_REQUESTS message
+with the respective element in a GNUNET_MESSAGE_TYPE_SETU_P2P_ELEMENTS
+message. If the IBF fully decodes, the peer responds with a
+GNUNET_MESSAGE_TYPE_SETU_P2P_DONE message instead of another
+GNUNET_MESSAGE_TYPE_SETU_P2P_IBF.
+
+All Bloom filter operations use a salt to mingle keys before hashing them
+into buckets, such that future iterations have a fresh chance of
+succeeding if they failed due to collisions before.
+
+
+
+
+
+
 @cindex STATISTICS Subsystem
 @node STATISTICS Subsystem
 @section STATISTICS Subsystem
diff --git a/doc/handbook/chapters/user.texi b/doc/handbook/chapters/user.texi
index 998abb87f33e6d567f2388f28fcbb30782369f10..adc287e04ab8467ee74c202cd43b0200e5e8334d 100644
--- a/doc/handbook/chapters/user.texi
+++ b/doc/handbook/chapters/user.texi
@@ -78,7 +78,7 @@ respective public key (you will learn how below) and extend the
 configuration:
 
 @example
-$ gnunet-config -s gns -n .myfriend -V PUBLIC_KEY
+$ gnunet-config -s gns -o .myfriend -V PUBLIC_KEY
 @end example
 
 @node Managing Egos
@@ -1988,13 +1988,13 @@ as a guide.
 @node reclaimID Identity Provider
 @section reclaimID Identity Provider
 
-The reclaimID Identity Provider (IdP) is a decentralized IdP service.
+The re:claimID Identity Provider (IdP) is a decentralized IdP service.
 It allows its users to manage and authorize third parties to access
 their identity attributes such as email or shipping addresses.
 
 It basically mimics the concepts of centralized IdPs, such as those
 offered by Google or Facebook.
-Like other IdPs, reclaimID features an (optional) OpenID-Connect
+Like other IdPs, reclaimID features an (optional) OpenID Connect
 1.0-compliant protocol layer that can be used for websites to
 integrate reclaimID as an Identity Provider with little effort.
 
@@ -2038,38 +2038,45 @@ In the future there might be more value types such as X.509 certificate credenti
 If you want to allow a third party such as a website or friend to access to your attributes (or a subset thereof) execute:
 
 @example
-$ gnunet-reclaim -e "user" -r "PKEY" -i "attribute1,attribute2,..."
+$ TICKET=$(gnunet-reclaim -e "user" -r "$RP_KEY" -i "attribute1,attribute2,...")
 @end example
 
-Where "PKEY" is the public key of the third party and "attribute1,attribute2,..." is a comma-separated list of attribute names, such as "email,name,...", that you want to share.
-
 The command will return a "ticket" string.
-You must give this "ticket" to the requesting third party.
+You must give $TICKET to the requesting third party.
+
+$RP_KEY is the public key of the third party and "attribute1,attribute2,..." is a comma-separated list of attribute names, such as "email,name,...", that you want to share.
+
+The third party may retrieve the key in string format for use in the above
+call using "gnunet-identity":
+
+@example
+$ RP_KEY=$(gnunet-identity -d grep "relyingparty" | awk '@{print $3@}')
+@end example
 
 The third party can then retrieve your shared identity attributes using:
 
 @example
-$ gnunet-reclaim -e "friend" -C "ticket"
+$ gnunet-reclaim -e "relyingparty" -C "ticket"
 @end example
 
-Where "friend" is the name for "user" that the requesting party is using.
+Where "relyingparty" is the name for the identity behind $RP_KEY that the
+requesting party is using.
 This will retrieve and list the shared identity attributes.
 The above command will also work if the user is currently offline since the attributes are retrieved from GNS.
-Further, the "ticket" can be re-used later to retrieve up-to-date attributes in case "friend" has changed the value(s). For instance, because his email address changed.
+Further, $TICKET can be re-used later to retrieve up-to-date attributes in case "friend" has changed the value(s). For instance, because his email address changed.
 
 To list all given authorizations (tickets) you can execute:
 @example
-$ gnunet-reclaim -e "friend" -T (TODO there is only a C and REST API for this at this time)
+$ gnunet-reclaim -e "user" -T
 @end example
 
-
 @node Revoking Authorizations of Third Parties
 @subsection Revoking Authorizations of Third Parties
 
 If you want to revoke the access of a third party to your attributes you can execute:
 
 @example
-$ gnunet-reclaim -e "user" -R "ticket"
+$ gnunet-reclaim -e "user" -R $TICKET
 @end example
 
 This will prevent the third party from accessing the attribute in the future.
@@ -2080,30 +2087,26 @@ This behaviour is _exactly the same_ as with other IdPs.
 @node OpenID Connect
 @subsection OpenID Connect
 
-There is an OpenID Connect API for use with reclaimID.
+There is an @uref{OpenID Connect, https://openid.net/specs/openid-connect-core-1_0.html} API for use with re:claimID.
 However, its use is quite complicated to setup.
-As a proof-of-concept, you can look at https://gitlab.com/reclaimid.
-
-In the PoC and by convention for reclaimID, the OpenID Connect Endpoints are
-found at:
 
 @example
-http://api.reclaim/openid/authorize
-http://api.reclaim/openid/token
-http://api.reclaim/openid/userinfo
-http://api.reclaim/openid/login
+https://api.reclaim/openid/authorize
+http://localhost:7776/openid/token
+http://localhost:7776/openid/userinfo
+http://localhost:7776/openid/login
 @end example
 
 The token endpoint is protected using HTTP basic authentication.
 You can authenticate using any username and the password configured under:
 
 @example
-$ gnunet-config -s reclaim-rest-plugin -o PSW
+$ gnunet-config -s reclaim-rest-plugin -o OIDC_CLIENT_SECRET
 @end example
 
 The authorize endpoint is protected using a Cookie which can be obtained through
 a request against the login endpoint.
-This flow is meant to be used in the context of the OpenID Connect authorization
+This functionality is meant to be used in the context of the OpenID Connect authorization
 flow to collect user consent interactively.
 Without a Cookie, the authorize endpoint redirects to a URI configured under:
 
@@ -2111,17 +2114,22 @@ Without a Cookie, the authorize endpoint redirects to a URI configured under:
 $ gnunet-config -s reclaim-rest-plugin -o ADDRESS
 @end example
 
-Our PoC includes a user interface (https://gitlab.com/reclaimid) which
-integrates this process is an OpenID Connect compatible fashion.
-
 The token endpoint is protected using OAuth2 and expects the grant
 which is retrieved from the authorization endpoint according to the standard.
 
 The userinfo endpoint is protected using OAuth2 and expects a bearer access
 token which is retrieved from a token request.
 
-In order to create and register a client you need to execute the following
-steps:
+In order to make use of OpenID Connect flows as a user, you need to install
+the browser plugin:
+
+@itemize @bullet
+@item @uref{https://addons.mozilla.org/addon/reclaimid/, Firefox Add-on}
+@item @uref{https://chrome.google.com/webstore/detail/reclaimid/jiogompmdejcnacmlnjhnaicgkefcfll, Chrome Web Store}
+@end itemize
+
+In order to create and register an OpenID Connect client as a relying party,
+you need to execute the following steps:
 
 @example
 $ gnunet-identity -C <client_name>
@@ -2129,16 +2137,23 @@ $ gnunet-namestore -z <client_name> -a -n "@@" -t RECLAIM_OIDC_REDIRECT -V <redi
 $ gnunet-namestore -z <client_name> -a -n "@@" -t RECLAIM_OIDC_CLIENT -V "My OIDC Client" -e 1d -p
 @end example
 
-The client_id will be the public key of the client.
-As a redirect URI, you may use any globally unique DNS or GNS URI.
-The client description will be displayed to the user on authorization.
+The "client_id" for use in OpenID Connect is the public key of the client as
+displayed using:
+@example
+$ gnunet-identity -d grep "relyingparty" | awk '@{print $3@}'
+@end example
+
+The RECLAIM_OIDC_REDIRECT record contains your website redirect URI.
+You may use any globally unique DNS or GNS URI.
+The RECLAIM_OIDC_CLIENT record represents the client description which whill
+be displayed to users in an authorization request.
 
-Any website or relying party must use the endpoint
-https://api.reclaim/openid/authorize in its authorization redirects, e.g.
+Any website or relying party must use the authorization endpoint
+@uref{https://api.reclaim/openid/authorize} in its authorization redirects, e.g.
 
 @example
 <a href="https://api.reclaim/openid/authorize?client_id=<PKEY>\
-                                             &scope=email\
+                                             &scope=openid email\
                                              &redirect_uri=<redirect_uri>\
                                              &nonce=<random>">Login</a>
 @end example
@@ -2146,7 +2161,17 @@ https://api.reclaim/openid/authorize in its authorization redirects, e.g.
 This will direct the user's browser onto his local reclaimID instance.
 After giving consent, you will be provided with the OpenID Connect authorization
 code according to the specifications at your provided redirect URI.
-The example code for the PoC website can be found at https://gitlab.com/reclaimid/demo.
+
+The ID Tokens issues by the token endpoints are signed using HS512 with the
+shared secret configured under:
+
+@example
+$ gnunet-config -s reclaim-rest-plugin -o JWT_SECRET
+@end example
+
+The authorization code flow optionally supports @uref{https://tools.ietf.org/html/rfc7636, Proof Key for Code Exchange}.
+If PKCE is used, the client does not need to authenticate against the token
+endpoint.
 
 @node Using the Virtual Public Network
 @section Using the Virtual Public Network
diff --git a/doc/handbook/gendocs.sh b/doc/handbook/gendocs.sh
new file mode 100755
index 0000000000000000000000000000000000000000..79c92c9ad956a41c4d4bedf7c1a382c68369cf76
--- /dev/null
+++ b/doc/handbook/gendocs.sh
@@ -0,0 +1,506 @@
+#!/bin/sh -e
+# gendocs.sh -- generate a GNU manual in many formats.  This script is
+#   mentioned in maintain.texi.  See the help message below for usage details.
+
+scriptversion=2016-12-31.18
+
+# Copyright 2003-2017 Free Software Foundation, Inc.
+#
+# This program 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 of the License, or
+# (at your option) any later version.
+#
+# This program 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 this program.  If not, see <http://www.gnu.org/licenses/>.
+#
+# SPDX-License-Identifier: GPL3.0-or-later
+#
+# Original author: Mohit Agarwal.
+# Send bug reports and any other correspondence to bug-gnulib@gnu.org.
+#
+# The latest version of this script, and the companion template, is
+# available from the Gnulib repository:
+#
+# http://git.savannah.gnu.org/cgit/gnulib.git/tree/build-aux/gendocs.sh
+# http://git.savannah.gnu.org/cgit/gnulib.git/tree/doc/gendocs_template
+
+# TODO:
+# - image importing was only implemented for HTML generated by
+#   makeinfo.  But it should be simple enough to adjust.
+# - images are not imported in the source tarball.  All the needed
+#   formats (PDF, PNG, etc.) should be included.
+
+prog=`basename "$0"`
+srcdir=`pwd`
+
+scripturl="http://git.savannah.gnu.org/cgit/gnulib.git/plain/build-aux/gendocs.sh"
+templateurl="http://git.savannah.gnu.org/cgit/gnulib.git/plain/doc/gendocs_template"
+
+: ${SETLANG="env LANG= LC_MESSAGES= LC_ALL= LANGUAGE="}
+: ${MAKEINFO="makeinfo"}
+: ${TEXI2DVI="texi2dvi"}
+: ${DOCBOOK2HTML="docbook2html"}
+: ${DOCBOOK2PDF="docbook2pdf"}
+: ${DOCBOOK2TXT="docbook2txt"}
+: ${GENDOCS_TEMPLATE_DIR="."}
+: ${PERL='perl'}
+: ${TEXI2HTML="texi2html"}
+unset CDPATH
+unset use_texi2html
+
+MANUAL_TITLE=
+PACKAGE=
+EMAIL=webmasters@gnu.org  # please override with --email
+commonarg= # passed to all makeinfo/texi2html invcations.
+dirargs=   # passed to all tools (-I dir).
+dirs=      # -I directories.
+htmlarg="--css-ref=/software/gnulib/manual.css -c TOP_NODE_UP_URL=/manual"
+infoarg=--no-split
+generate_ascii=true
+generate_html=true
+generate_info=true
+generate_tex=true
+outdir=manual
+source_extra=
+split=node
+srcfile=
+texarg="-t @finalout"
+
+version="gendocs.sh $scriptversion
+
+Copyright 2017 Free Software Foundation, Inc.
+There is NO warranty.  You may redistribute this software
+under the terms of the GNU General Public License.
+For more information about these matters, see the files named COPYING."
+
+usage="Usage: $prog [OPTION]... PACKAGE MANUAL-TITLE
+
+Generate output in various formats from PACKAGE.texinfo (or .texi or
+.txi) source.  See the GNU Maintainers document for a more extensive
+discussion:
+  http://www.gnu.org/prep/maintain_toc.html
+
+Options:
+  --email ADR use ADR as contact in generated web pages; always give this.
+
+  -s SRCFILE   read Texinfo from SRCFILE, instead of PACKAGE.{texinfo|texi|txi}
+  -o OUTDIR    write files into OUTDIR, instead of manual/.
+  -I DIR       append DIR to the Texinfo search path.
+  --common ARG pass ARG in all invocations.
+  --html ARG   pass ARG to makeinfo or texi2html for HTML targets,
+                 instead of '$htmlarg'.
+  --info ARG   pass ARG to makeinfo for Info, instead of --no-split.
+  --no-ascii   skip generating the plain text output.
+  --no-html    skip generating the html output.
+  --no-info    skip generating the info output.
+  --no-tex     skip generating the dvi and pdf output.
+  --source ARG include ARG in tar archive of sources.
+  --split HOW  make split HTML by node, section, chapter; default node.
+  --tex ARG    pass ARG to texi2dvi for DVI and PDF, instead of -t @finalout.
+
+  --texi2html  use texi2html to make HTML target, with all split versions.
+  --docbook    convert through DocBook too (xml, txt, html, pdf).
+
+  --help       display this help and exit successfully.
+  --version    display version information and exit successfully.
+
+Simple example: $prog --email bug-gnu-emacs@gnu.org emacs \"GNU Emacs Manual\"
+
+Typical sequence:
+  cd PACKAGESOURCE/doc
+  wget \"$scripturl\"
+  wget \"$templateurl\"
+  $prog --email BUGLIST MANUAL \"GNU MANUAL - One-line description\"
+
+Output will be in a new subdirectory \"manual\" (by default;
+use -o OUTDIR to override).  Move all the new files into your web CVS
+tree, as explained in the Web Pages node of maintain.texi.
+
+Please use the --email ADDRESS option so your own bug-reporting
+address will be used in the generated HTML pages.
+
+MANUAL-TITLE is included as part of the HTML <title> of the overall
+manual/index.html file.  It should include the name of the package being
+documented.  manual/index.html is created by substitution from the file
+$GENDOCS_TEMPLATE_DIR/gendocs_template.  (Feel free to modify the
+generic template for your own purposes.)
+
+If you have several manuals, you'll need to run this script several
+times with different MANUAL values, specifying a different output
+directory with -o each time.  Then write (by hand) an overall index.html
+with links to them all.
+
+If a manual's Texinfo sources are spread across several directories,
+first copy or symlink all Texinfo sources into a single directory.
+(Part of the script's work is to make a tar.gz of the sources.)
+
+As implied above, by default monolithic Info files are generated.
+If you want split Info, or other Info options, use --info to override.
+
+You can set the environment variables MAKEINFO, TEXI2DVI, TEXI2HTML,
+and PERL to control the programs that get executed, and
+GENDOCS_TEMPLATE_DIR to control where the gendocs_template file is
+looked for.  With --docbook, the environment variables DOCBOOK2HTML,
+DOCBOOK2PDF, and DOCBOOK2TXT are also consulted.
+
+By default, makeinfo and texi2dvi are run in the default (English)
+locale, since that's the language of most Texinfo manuals.  If you
+happen to have a non-English manual and non-English web site, see the
+SETLANG setting in the source.
+
+Email bug reports or enhancement requests to bug-gnulib@gnu.org.
+"
+
+while test $# -gt 0; do
+  case $1 in
+    -s)          shift; srcfile=$1;;
+    -o)          shift; outdir=$1;;
+    -I)          shift; dirargs="$dirargs -I '$1'"; dirs="$dirs $1";;
+    --common)    shift; commonarg=$1;;
+    --docbook)   docbook=yes;;
+    --email)     shift; EMAIL=$1;;
+    --html)      shift; htmlarg=$1;;
+    --info)      shift; infoarg=$1;;
+    --no-ascii)  generate_ascii=false;;
+    --no-html)   generate_ascii=false;;
+    --no-info)   generate_info=false;;
+    --no-tex)    generate_tex=false;;
+    --source)    shift; source_extra=$1;;
+    --split)     shift; split=$1;;
+    --tex)       shift; texarg=$1;;
+    --texi2html) use_texi2html=1;;
+
+    --help)      echo "$usage"; exit 0;;
+    --version)   echo "$version"; exit 0;;
+    -*)
+      echo "$0: Unknown option \`$1'." >&2
+      echo "$0: Try \`--help' for more information." >&2
+      exit 1;;
+    *)
+      if test -z "$PACKAGE"; then
+        PACKAGE=$1
+      elif test -z "$MANUAL_TITLE"; then
+        MANUAL_TITLE=$1
+      else
+        echo "$0: extra non-option argument \`$1'." >&2
+        exit 1
+      fi;;
+  esac
+  shift
+done
+
+# makeinfo uses the dirargs, but texi2dvi doesn't.
+commonarg=" $dirargs $commonarg"
+
+# For most of the following, the base name is just $PACKAGE
+base=$PACKAGE
+
+if test -n "$srcfile"; then
+  # but here, we use the basename of $srcfile
+  base=`basename "$srcfile"`
+  case $base in
+    *.txi|*.texi|*.texinfo) base=`echo "$base"|sed 's/\.[texinfo]*$//'`;;
+  esac
+  PACKAGE=$base
+elif test -s "$srcdir/$PACKAGE.texinfo"; then
+  srcfile=$srcdir/$PACKAGE.texinfo
+elif test -s "$srcdir/$PACKAGE.texi"; then
+  srcfile=$srcdir/$PACKAGE.texi
+elif test -s "$srcdir/$PACKAGE.txi"; then
+  srcfile=$srcdir/$PACKAGE.txi
+else
+  echo "$0: cannot find .texinfo or .texi or .txi for $PACKAGE in $srcdir." >&2
+  exit 1
+fi
+
+if test ! -r $GENDOCS_TEMPLATE_DIR/gendocs_template; then
+  echo "$0: cannot read $GENDOCS_TEMPLATE_DIR/gendocs_template." >&2
+  echo "$0: it is available from $templateurl." >&2
+  exit 1
+fi
+
+# Function to return size of $1 in something resembling kilobytes.
+calcsize()
+{
+  size=`ls -ksl $1 | awk '{print $1}'`
+  echo $size
+}
+
+# copy_images OUTDIR HTML-FILE...
+# -------------------------------
+# Copy all the images needed by the HTML-FILEs into OUTDIR.
+# Look for them in . and the -I directories; this is simpler than what
+# makeinfo supports with -I, but hopefully it will suffice.
+copy_images()
+{
+  local odir
+  odir=$1
+  shift
+  $PERL -n -e "
+BEGIN {
+  \$me = '$prog';
+  \$odir = '$odir';
+  @dirs = qw(. $dirs);
+}
+" -e '
+/<img src="(.*?)"/g && ++$need{$1};
+
+END {
+  #print "$me: @{[keys %need]}\n";  # for debugging, show images found.
+  FILE: for my $f (keys %need) {
+    for my $d (@dirs) {
+      if (-f "$d/$f") {
+        use File::Basename;
+        my $dest = dirname ("$odir/$f");
+        #
+        use File::Path;
+        -d $dest || mkpath ($dest)
+          || die "$me: cannot mkdir $dest: $!\n";
+        #
+        use File::Copy;
+        copy ("$d/$f", $dest)
+          || die "$me: cannot copy $d/$f to $dest: $!\n";
+        next FILE;
+      }
+    }
+    die "$me: $ARGV: cannot find image $f\n";
+  }
+}
+' -- "$@" || exit 1
+}
+
+case $outdir in
+  /*) abs_outdir=$outdir;;
+  *)  abs_outdir=$srcdir/$outdir;;
+esac
+
+echo "Making output for $srcfile"
+echo " in `pwd`"
+mkdir -p "$outdir/"
+
+# 
+if $generate_info; then
+  cmd="$SETLANG $MAKEINFO -o $PACKAGE.info $commonarg $infoarg \"$srcfile\""
+  echo "Generating info... ($cmd)"
+  rm -f $PACKAGE.info* # get rid of any strays
+  eval "$cmd"
+  tar czf "$outdir/$PACKAGE.info.tar.gz" $PACKAGE.info*
+  ls -l "$outdir/$PACKAGE.info.tar.gz"
+  info_tgz_size=`calcsize "$outdir/$PACKAGE.info.tar.gz"`
+  # do not mv the info files, there's no point in having them available
+  # separately on the web.
+fi  # end info
+
+# 
+if $generate_tex; then
+  cmd="$SETLANG $TEXI2DVI $dirargs $texarg \"$srcfile\""
+  printf "\nGenerating dvi... ($cmd)\n"
+  eval "$cmd"
+  # compress/finish dvi:
+  gzip -f -9 $PACKAGE.dvi
+  dvi_gz_size=`calcsize $PACKAGE.dvi.gz`
+  mv $PACKAGE.dvi.gz "$outdir/"
+  ls -l "$outdir/$PACKAGE.dvi.gz"
+
+  cmd="$SETLANG $TEXI2DVI --pdf $dirargs $texarg \"$srcfile\""
+  printf "\nGenerating pdf... ($cmd)\n"
+  eval "$cmd"
+  pdf_size=`calcsize $PACKAGE.pdf`
+  mv $PACKAGE.pdf "$outdir/"
+  ls -l "$outdir/$PACKAGE.pdf"
+fi # end tex (dvi + pdf)
+
+# 
+if $generate_ascii; then
+  opt="-o $PACKAGE.txt --no-split --no-headers $commonarg"
+  cmd="$SETLANG $MAKEINFO $opt \"$srcfile\""
+  printf "\nGenerating ascii... ($cmd)\n"
+  eval "$cmd"
+  ascii_size=`calcsize $PACKAGE.txt`
+  gzip -f -9 -c $PACKAGE.txt >"$outdir/$PACKAGE.txt.gz"
+  ascii_gz_size=`calcsize "$outdir/$PACKAGE.txt.gz"`
+  mv $PACKAGE.txt "$outdir/"
+  ls -l "$outdir/$PACKAGE.txt" "$outdir/$PACKAGE.txt.gz"
+fi
+
+# 
+
+if $generate_html; then
+# Split HTML at level $1.  Used for texi2html.
+html_split()
+{
+  opt="--split=$1 --node-files $commonarg $htmlarg"
+  cmd="$SETLANG $TEXI2HTML --output $PACKAGE.html $opt \"$srcfile\""
+  printf "\nGenerating html by $1... ($cmd)\n"
+  eval "$cmd"
+  split_html_dir=$PACKAGE.html
+  (
+    cd ${split_html_dir} || exit 1
+    ln -sf ${PACKAGE}.html index.html
+    tar -czf "$abs_outdir/${PACKAGE}.html_$1.tar.gz" -- *.html
+  )
+  eval html_$1_tgz_size=`calcsize "$outdir/${PACKAGE}.html_$1.tar.gz"`
+  rm -f "$outdir"/html_$1/*.html
+  mkdir -p "$outdir/html_$1/"
+  mv ${split_html_dir}/*.html "$outdir/html_$1/"
+  rmdir ${split_html_dir}
+}
+
+if test -z "$use_texi2html"; then
+  opt="--no-split --html -o $PACKAGE.html $commonarg $htmlarg"
+  cmd="$SETLANG $MAKEINFO $opt \"$srcfile\""
+  printf "\nGenerating monolithic html... ($cmd)\n"
+  rm -rf $PACKAGE.html  # in case a directory is left over
+  eval "$cmd"
+  html_mono_size=`calcsize $PACKAGE.html`
+  gzip -f -9 -c $PACKAGE.html >"$outdir/$PACKAGE.html.gz"
+  html_mono_gz_size=`calcsize "$outdir/$PACKAGE.html.gz"`
+  copy_images "$outdir/" $PACKAGE.html
+  mv $PACKAGE.html "$outdir/"
+  ls -l "$outdir/$PACKAGE.html" "$outdir/$PACKAGE.html.gz"
+
+  # Before Texinfo 5.0, makeinfo did not accept a --split=HOW option,
+  # it just always split by node.  So if we're splitting by node anyway,
+  # leave it out.
+  if test "x$split" = xnode; then
+    split_arg=
+  else
+    split_arg=--split=$split
+  fi
+  #
+  opt="--html -o $PACKAGE.html $split_arg $commonarg $htmlarg"
+  cmd="$SETLANG $MAKEINFO $opt \"$srcfile\""
+  printf "\nGenerating html by $split... ($cmd)\n"
+  eval "$cmd"
+  split_html_dir=$PACKAGE.html
+  copy_images $split_html_dir/ $split_html_dir/*.html
+  (
+    cd $split_html_dir || exit 1
+    tar -czf "$abs_outdir/$PACKAGE.html_$split.tar.gz" -- *
+  )
+  eval \
+    html_${split}_tgz_size=`calcsize "$outdir/$PACKAGE.html_$split.tar.gz"`
+  rm -rf "$outdir/html_$split/"
+  mv $split_html_dir "$outdir/html_$split/"
+  du -s "$outdir/html_$split/"
+  ls -l "$outdir/$PACKAGE.html_$split.tar.gz"
+
+else # use texi2html:
+  opt="--output $PACKAGE.html $commonarg $htmlarg"
+  cmd="$SETLANG $TEXI2HTML $opt \"$srcfile\""
+  printf "\nGenerating monolithic html with texi2html... ($cmd)\n"
+  rm -rf $PACKAGE.html  # in case a directory is left over
+  eval "$cmd"
+  html_mono_size=`calcsize $PACKAGE.html`
+  gzip -f -9 -c $PACKAGE.html >"$outdir/$PACKAGE.html.gz"
+  html_mono_gz_size=`calcsize "$outdir/$PACKAGE.html.gz"`
+  mv $PACKAGE.html "$outdir/"
+
+  html_split node
+  html_split chapter
+  html_split section
+fi
+fi # end html
+
+# 
+printf "\nMaking .tar.gz for sources...\n"
+d=`dirname $srcfile`
+(
+  cd "$d"
+  srcfiles=`ls -d *.texinfo *.texi *.txi *.eps $source_extra 2>/dev/null` || true
+  tar czfh "$abs_outdir/$PACKAGE.texi.tar.gz" $srcfiles
+  ls -l "$abs_outdir/$PACKAGE.texi.tar.gz"
+)
+texi_tgz_size=`calcsize "$outdir/$PACKAGE.texi.tar.gz"`
+
+# 
+# Do everything again through docbook.
+if test -n "$docbook"; then
+  opt="-o - --docbook $commonarg"
+  cmd="$SETLANG $MAKEINFO $opt \"$srcfile\" >${srcdir}/$PACKAGE-db.xml"
+  printf "\nGenerating docbook XML... ($cmd)\n"
+  eval "$cmd"
+  docbook_xml_size=`calcsize $PACKAGE-db.xml`
+  gzip -f -9 -c $PACKAGE-db.xml >"$outdir/$PACKAGE-db.xml.gz"
+  docbook_xml_gz_size=`calcsize "$outdir/$PACKAGE-db.xml.gz"`
+  mv $PACKAGE-db.xml "$outdir/"
+
+  split_html_db_dir=html_node_db
+  opt="$commonarg -o $split_html_db_dir"
+  cmd="$DOCBOOK2HTML $opt \"${outdir}/$PACKAGE-db.xml\""
+  printf "\nGenerating docbook HTML... ($cmd)\n"
+  eval "$cmd"
+  (
+    cd ${split_html_db_dir} || exit 1
+    tar -czf "$abs_outdir/${PACKAGE}.html_node_db.tar.gz" -- *.html
+  )
+  html_node_db_tgz_size=`calcsize "$outdir/${PACKAGE}.html_node_db.tar.gz"`
+  rm -f "$outdir"/html_node_db/*.html
+  mkdir -p "$outdir/html_node_db"
+  mv ${split_html_db_dir}/*.html "$outdir/html_node_db/"
+  rmdir ${split_html_db_dir}
+
+  cmd="$DOCBOOK2TXT \"${outdir}/$PACKAGE-db.xml\""
+  printf "\nGenerating docbook ASCII... ($cmd)\n"
+  eval "$cmd"
+  docbook_ascii_size=`calcsize $PACKAGE-db.txt`
+  mv $PACKAGE-db.txt "$outdir/"
+
+  cmd="$DOCBOOK2PDF \"${outdir}/$PACKAGE-db.xml\""
+  printf "\nGenerating docbook PDF... ($cmd)\n"
+  eval "$cmd"
+  docbook_pdf_size=`calcsize $PACKAGE-db.pdf`
+  mv $PACKAGE-db.pdf "$outdir/"
+fi
+
+# 
+printf "\nMaking index.html for $PACKAGE...\n"
+if test -z "$use_texi2html"; then
+  CONDS="/%%IF  *HTML_SECTION%%/,/%%ENDIF  *HTML_SECTION%%/d;\
+         /%%IF  *HTML_CHAPTER%%/,/%%ENDIF  *HTML_CHAPTER%%/d"
+else
+  # should take account of --split here.
+  CONDS="/%%ENDIF.*%%/d;/%%IF  *HTML_SECTION%%/d;/%%IF  *HTML_CHAPTER%%/d"
+fi
+
+curdate=`$SETLANG date '+%B %d, %Y'`
+sed \
+   -e "s!%%TITLE%%!$MANUAL_TITLE!g" \
+   -e "s!%%EMAIL%%!$EMAIL!g" \
+   -e "s!%%PACKAGE%%!$PACKAGE!g" \
+   -e "s!%%DATE%%!$curdate!g" \
+   -e "s!%%HTML_MONO_SIZE%%!$html_mono_size!g" \
+   -e "s!%%HTML_MONO_GZ_SIZE%%!$html_mono_gz_size!g" \
+   -e "s!%%HTML_NODE_TGZ_SIZE%%!$html_node_tgz_size!g" \
+   -e "s!%%HTML_SECTION_TGZ_SIZE%%!$html_section_tgz_size!g" \
+   -e "s!%%HTML_CHAPTER_TGZ_SIZE%%!$html_chapter_tgz_size!g" \
+   -e "s!%%INFO_TGZ_SIZE%%!$info_tgz_size!g" \
+   -e "s!%%DVI_GZ_SIZE%%!$dvi_gz_size!g" \
+   -e "s!%%PDF_SIZE%%!$pdf_size!g" \
+   -e "s!%%ASCII_SIZE%%!$ascii_size!g" \
+   -e "s!%%ASCII_GZ_SIZE%%!$ascii_gz_size!g" \
+   -e "s!%%TEXI_TGZ_SIZE%%!$texi_tgz_size!g" \
+   -e "s!%%DOCBOOK_HTML_NODE_TGZ_SIZE%%!$html_node_db_tgz_size!g" \
+   -e "s!%%DOCBOOK_ASCII_SIZE%%!$docbook_ascii_size!g" \
+   -e "s!%%DOCBOOK_PDF_SIZE%%!$docbook_pdf_size!g" \
+   -e "s!%%DOCBOOK_XML_SIZE%%!$docbook_xml_size!g" \
+   -e "s!%%DOCBOOK_XML_GZ_SIZE%%!$docbook_xml_gz_size!g" \
+   -e "s,%%SCRIPTURL%%,$scripturl,g" \
+   -e "s!%%SCRIPTNAME%%!$prog!g" \
+   -e "$CONDS" \
+$GENDOCS_TEMPLATE_DIR/gendocs_template >"$outdir/index.html"
+
+echo "Done, see $outdir/ subdirectory for new files."
+
+# Local variables:
+# eval: (add-hook 'write-file-hooks 'time-stamp)
+# time-stamp-start: "scriptversion="
+# time-stamp-format: "%:y-%02m-%02d.%02H"
+# time-stamp-end: "$"
+# End:
diff --git a/doc/handbook/gendocs_template b/doc/handbook/gendocs_template
new file mode 100644
index 0000000000000000000000000000000000000000..178f6cb4c80f1d351ce3179830b0a941e6857de8
--- /dev/null
+++ b/doc/handbook/gendocs_template
@@ -0,0 +1,91 @@
+<!--#include virtual="/server/header.html" -->
+<!-- Parent-Version: 1.77 -->
+<title>%%TITLE%% - GNU Project - Free Software Foundation</title>
+<!--#include virtual="/server/banner.html" -->
+<h2>%%TITLE%%</h2>
+
+<address>Free Software Foundation</address>
+<address>last updated %%DATE%%</address>
+
+<p>This manual (%%PACKAGE%%) is available in the following formats:</p>
+
+<ul>
+<li><a href="%%PACKAGE%%.html">HTML
+    (%%HTML_MONO_SIZE%%K bytes)</a> - entirely on one web page.</li>
+<li><a href="html_node/index.html">HTML</a> - with one web page per
+    node.</li>
+%%IF HTML_SECTION%%
+<li><a href="html_section/index.html">HTML</a> - with one web page per
+    section.</li>
+%%ENDIF HTML_SECTION%%
+%%IF HTML_CHAPTER%%
+<li><a href="html_chapter/index.html">HTML</a> - with one web page per
+    chapter.</li>
+%%ENDIF HTML_CHAPTER%%
+<li><a href="%%PACKAGE%%.html.gz">HTML compressed
+    (%%HTML_MONO_GZ_SIZE%%K gzipped characters)</a> - entirely on
+    one web page.</li>
+<li><a href="%%PACKAGE%%.html_node.tar.gz">HTML compressed
+    (%%HTML_NODE_TGZ_SIZE%%K gzipped tar file)</a> -
+    with one web page per node.</li>
+%%IF HTML_SECTION%%
+<li><a href="%%PACKAGE%%.html_section.tar.gz">HTML compressed
+    (%%HTML_SECTION_TGZ_SIZE%%K gzipped tar file)</a> -
+    with one web page per section.</li>
+%%ENDIF HTML_SECTION%%
+%%IF HTML_CHAPTER%%
+<li><a href="%%PACKAGE%%.html_chapter.tar.gz">HTML compressed
+    (%%HTML_CHAPTER_TGZ_SIZE%%K gzipped tar file)</a> -
+    with one web page per chapter.</li>
+%%ENDIF HTML_CHAPTER%%
+<li><a href="%%PACKAGE%%.info.tar.gz">Info document
+    (%%INFO_TGZ_SIZE%%K bytes gzipped tar file)</a>.</li>
+<li><a href="%%PACKAGE%%.txt">ASCII text
+    (%%ASCII_SIZE%%K bytes)</a>.</li>
+<li><a href="%%PACKAGE%%.txt.gz">ASCII text compressed
+    (%%ASCII_GZ_SIZE%%K bytes gzipped)</a>.</li>
+<li><a href="%%PACKAGE%%.dvi.gz">TeX dvi file
+    (%%DVI_GZ_SIZE%%K bytes gzipped)</a>.</li>
+<li><a href="%%PACKAGE%%.pdf">PDF file
+    (%%PDF_SIZE%%K bytes)</a>.</li>
+<li><a href="%%PACKAGE%%.texi.tar.gz">Texinfo source
+    (%%TEXI_TGZ_SIZE%%K bytes gzipped tar file).</a></li>
+</ul>
+
+<p>You can <a href="http://shop.fsf.org/">buy printed copies of
+some manuals</a> (among other items) from the Free Software Foundation;
+this helps support FSF activities.</p>
+
+<p>(This page generated by the <a href="%%SCRIPTURL%%">%%SCRIPTNAME%%
+script</a>.)</p>
+
+<!-- If needed, change the copyright block at the bottom. In general,
+     all pages on the GNU web server should have the section about
+     verbatim copying.  Please do NOT remove this without talking
+     with the webmasters first.
+     Please make sure the copyright date is consistent with the document
+     and that it is like this: "2001, 2002", not this: "2001-2002". -->
+</div><!-- for id="content", starts in the include above -->
+<!--#include virtual="/server/footer.html" -->
+<div id="footer">
+<div class="unprintable">
+
+<p>Please send general FSF &amp; GNU inquiries to
+<a href="mailto:gnu@gnu.org">&lt;gnu@gnu.org&gt;</a>.
+There are also <a href="/contact/">other ways to contact</a>
+the FSF.  Broken links and other corrections or suggestions can be sent
+to <a href="mailto:%%EMAIL%%">&lt;%%EMAIL%%&gt;</a>.</p>
+</div>
+
+<p>Copyright &copy; 2017 Free Software Foundation, Inc.</p>
+
+<p>This page is licensed under a <a rel="license"
+href="http://creativecommons.org/licenses/by-nd/3.0/us/">Creative
+Commons Attribution-NoDerivs 3.0 United States License</a>.</p>
+
+<!--#include virtual="/server/bottom-notes.html" -->
+
+</div>
+</div>
+</body>
+</html>
diff --git a/doc/handbook/gendocs_template_min b/doc/handbook/gendocs_template_min
new file mode 100644
index 0000000000000000000000000000000000000000..112fa3bfb6387e80680b41d8339781bfd798e827
--- /dev/null
+++ b/doc/handbook/gendocs_template_min
@@ -0,0 +1,93 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
+    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
+
+<head>
+<title>%%TITLE%% - GNU Project - Free Software Foundation</title>
+<meta http-equiv="content-type" content='text/html; charset=utf-8' />
+<link rel="stylesheet" type="text/css" href="/gnu.css" />
+</head>
+
+<body>
+
+<h3>%%TITLE%%</h3>
+
+<address>Free Software Foundation</address>
+<address>last updated %%DATE%%</address>
+<p>
+<a href="/graphics/gnu-head.jpg">
+	<img src="/graphics/gnu-head-sm.jpg"
+             alt=" [image of the head of a GNU] " width="129" height="122"/>
+</a>
+</p>
+<hr />
+
+<p>This manual (%%PACKAGE%%) is available in the following formats:</p>
+
+<ul>
+<li><a href="%%PACKAGE%%.html">HTML
+    (%%HTML_MONO_SIZE%%K bytes)</a> - entirely on one web page.</li>
+<li><a href="html_node/index.html">HTML</a> - with one web page per
+    node.</li>
+%%IF HTML_SECTION%%
+<li><a href="html_section/index.html">HTML</a> - with one web page per
+    section.</li>
+%%ENDIF HTML_SECTION%%
+%%IF HTML_CHAPTER%%
+<li><a href="html_chapter/index.html">HTML</a> - with one web page per
+    chapter.</li>
+%%ENDIF HTML_CHAPTER%%
+<li><a href="%%PACKAGE%%.html.gz">HTML compressed
+    (%%HTML_MONO_GZ_SIZE%%K gzipped characters)</a> - entirely on
+    one web page.</li>
+<li><a href="%%PACKAGE%%.html_node.tar.gz">HTML compressed
+    (%%HTML_NODE_TGZ_SIZE%%K gzipped tar file)</a> -
+    with one web page per node.</li>
+%%IF HTML_SECTION%%
+<li><a href="%%PACKAGE%%.html_section.tar.gz">HTML compressed
+    (%%HTML_SECTION_TGZ_SIZE%%K gzipped tar file)</a> -
+    with one web page per section.</li>
+%%ENDIF HTML_SECTION%%
+%%IF HTML_CHAPTER%%
+<li><a href="%%PACKAGE%%.html_chapter.tar.gz">HTML compressed
+    (%%HTML_CHAPTER_TGZ_SIZE%%K gzipped tar file)</a> -
+    with one web page per chapter.</li>
+%%ENDIF HTML_CHAPTER%%
+<li><a href="%%PACKAGE%%.info.tar.gz">Info document
+    (%%INFO_TGZ_SIZE%%K bytes gzipped tar file)</a>.</li>
+<li><a href="%%PACKAGE%%.txt">ASCII text
+    (%%ASCII_SIZE%%K bytes)</a>.</li>
+<li><a href="%%PACKAGE%%.txt.gz">ASCII text compressed
+    (%%ASCII_GZ_SIZE%%K bytes gzipped)</a>.</li>
+<li><a href="%%PACKAGE%%.dvi.gz">TeX dvi file
+    (%%DVI_GZ_SIZE%%K bytes gzipped)</a>.</li>
+<li><a href="%%PACKAGE%%.pdf">PDF file
+    (%%PDF_SIZE%%K bytes)</a>.</li>
+<li><a href="%%PACKAGE%%.texi.tar.gz">Texinfo source
+    (%%TEXI_TGZ_SIZE%%K bytes gzipped tar file).</a></li>
+</ul>
+
+<p>(This page generated by the <a href="%%SCRIPTURL%%">%%SCRIPTNAME%%
+script</a>.)</p>
+
+<div id="footer" class="copyright">
+
+<p>Please send general FSF &amp; GNU inquiries to
+<a href="mailto:gnu@gnu.org">&lt;gnu@gnu.org&gt;</a>.
+There are also <a href="/contact/">other ways to contact</a>
+the FSF.  Broken links and other corrections or suggestions can be sent
+to <a href="mailto:%%EMAIL%%">&lt;%%EMAIL%%&gt;</a>.</p>
+</div>
+
+<p>Copyright &copy; 2017 Free Software Foundation, Inc.</p>
+
+<p>This page is licensed under a <a rel="license"
+href="http://creativecommons.org/licenses/by-nd/3.0/us/">Creative
+Commons Attribution-NoDerivs 3.0 United States License</a>.</p>
+
+<!--#include virtual="/server/bottom-notes.html" -->
+
+</div>
+</body>
+</html>
diff --git a/doc/handbook/images/ascension_interaction.png b/doc/handbook/images/ascension_interaction.png
new file mode 100644
index 0000000000000000000000000000000000000000..84e2e9c0fd3f999fdb01e36ad31b09bf6b738cfa
Binary files /dev/null and b/doc/handbook/images/ascension_interaction.png differ
diff --git a/doc/handbook/images/ascension_ssd.png b/doc/handbook/images/ascension_ssd.png
new file mode 100644
index 0000000000000000000000000000000000000000..3b142ab310c7dbb2f801455ee505ddb756f669f8
Binary files /dev/null and b/doc/handbook/images/ascension_ssd.png differ
diff --git a/doc/handbook/images/gns.eps b/doc/handbook/images/gns.eps
new file mode 100644
index 0000000000000000000000000000000000000000..3f3c28d989aa274217ed46125da4588cfdeca549
--- /dev/null
+++ b/doc/handbook/images/gns.eps
@@ -0,0 +1,585 @@
+%!PS-Adobe-3.0 EPSF-3.0
+%%Creator: graphviz version 2.40.1 (20161225.0304)
+%%Title: dataflow
+%%Pages: 1
+%%BoundingBox: 36 36 722 428
+%%EndComments
+save
+%%BeginProlog
+/DotDict 200 dict def
+DotDict begin
+
+/setupLatin1 {
+mark
+/EncodingVector 256 array def
+ EncodingVector 0
+
+ISOLatin1Encoding 0 255 getinterval putinterval
+EncodingVector 45 /hyphen put
+
+% Set up ISO Latin 1 character encoding
+/starnetISO {
+        dup dup findfont dup length dict begin
+        { 1 index /FID ne { def }{ pop pop } ifelse
+        } forall
+        /Encoding EncodingVector def
+        currentdict end definefont
+} def
+/Times-Roman starnetISO def
+/Times-Italic starnetISO def
+/Times-Bold starnetISO def
+/Times-BoldItalic starnetISO def
+/Helvetica starnetISO def
+/Helvetica-Oblique starnetISO def
+/Helvetica-Bold starnetISO def
+/Helvetica-BoldOblique starnetISO def
+/Courier starnetISO def
+/Courier-Oblique starnetISO def
+/Courier-Bold starnetISO def
+/Courier-BoldOblique starnetISO def
+cleartomark
+} bind def
+
+%%BeginResource: procset graphviz 0 0
+/coord-font-family /Times-Roman def
+/default-font-family /Times-Roman def
+/coordfont coord-font-family findfont 8 scalefont def
+
+/InvScaleFactor 1.0 def
+/set_scale {
+       dup 1 exch div /InvScaleFactor exch def
+       scale
+} bind def
+
+% styles
+/solid { [] 0 setdash } bind def
+/dashed { [9 InvScaleFactor mul dup ] 0 setdash } bind def
+/dotted { [1 InvScaleFactor mul 6 InvScaleFactor mul] 0 setdash } bind def
+/invis {/fill {newpath} def /stroke {newpath} def /show {pop newpath} def} bind def
+/bold { 2 setlinewidth } bind def
+/filled { } bind def
+/unfilled { } bind def
+/rounded { } bind def
+/diagonals { } bind def
+/tapered { } bind def
+
+% hooks for setting color 
+/nodecolor { sethsbcolor } bind def
+/edgecolor { sethsbcolor } bind def
+/graphcolor { sethsbcolor } bind def
+/nopcolor {pop pop pop} bind def
+
+/beginpage {	% i j npages
+	/npages exch def
+	/j exch def
+	/i exch def
+	/str 10 string def
+	npages 1 gt {
+		gsave
+			coordfont setfont
+			0 0 moveto
+			(\() show i str cvs show (,) show j str cvs show (\)) show
+		grestore
+	} if
+} bind def
+
+/set_font {
+	findfont exch
+	scalefont setfont
+} def
+
+% draw text fitted to its expected width
+/alignedtext {			% width text
+	/text exch def
+	/width exch def
+	gsave
+		width 0 gt {
+			[] 0 setdash
+			text stringwidth pop width exch sub text length div 0 text ashow
+		} if
+	grestore
+} def
+
+/boxprim {				% xcorner ycorner xsize ysize
+		4 2 roll
+		moveto
+		2 copy
+		exch 0 rlineto
+		0 exch rlineto
+		pop neg 0 rlineto
+		closepath
+} bind def
+
+/ellipse_path {
+	/ry exch def
+	/rx exch def
+	/y exch def
+	/x exch def
+	matrix currentmatrix
+	newpath
+	x y translate
+	rx ry scale
+	0 0 1 0 360 arc
+	setmatrix
+} bind def
+
+/endpage { showpage } bind def
+/showpage { } def
+
+/layercolorseq
+	[	% layer color sequence - darkest to lightest
+		[0 0 0]
+		[.2 .8 .8]
+		[.4 .8 .8]
+		[.6 .8 .8]
+		[.8 .8 .8]
+	]
+def
+
+/layerlen layercolorseq length def
+
+/setlayer {/maxlayer exch def /curlayer exch def
+	layercolorseq curlayer 1 sub layerlen mod get
+	aload pop sethsbcolor
+	/nodecolor {nopcolor} def
+	/edgecolor {nopcolor} def
+	/graphcolor {nopcolor} def
+} bind def
+
+/onlayer { curlayer ne {invis} if } def
+
+/onlayers {
+	/myupper exch def
+	/mylower exch def
+	curlayer mylower lt
+	curlayer myupper gt
+	or
+	{invis} if
+} def
+
+/curlayer 0 def
+
+%%EndResource
+%%EndProlog
+%%BeginSetup
+14 default-font-family set_font
+% /arrowlength 10 def
+% /arrowwidth 5 def
+
+% make sure pdfmark is harmless for PS-interpreters other than Distiller
+/pdfmark where {pop} {userdict /pdfmark /cleartomark load put} ifelse
+% make '<<' and '>>' safe on PS Level 1 devices
+/languagelevel where {pop languagelevel}{1} ifelse
+2 lt {
+    userdict (<<) cvn ([) cvn load put
+    userdict (>>) cvn ([) cvn load put
+} if
+
+%%EndSetup
+setupLatin1
+%%Page: 1 1
+%%PageBoundingBox: 36 36 722 428
+%%PageOrientation: Portrait
+0 0 1 beginpage
+gsave
+36 36 686 392 boxprim clip newpath
+1 1 set_scale 0 rotate 40 40 translate
+% DNS
+gsave
+1 setlinewidth
+0 0 0 nodecolor
+newpath 137.2989 384 moveto
+83.2989 384 lineto
+83.2989 348 lineto
+137.2989 348 lineto
+closepath stroke
+0 0 0 nodecolor
+14 /Times-Roman set_font
+96.2989 362.3 moveto 28 (DNS) alignedtext
+grestore
+% import
+gsave
+1 setlinewidth
+0 0 0 nodecolor
+newpath 110.2989 297 moveto
+.2008 279 lineto
+110.2989 261 lineto
+220.397 279 lineto
+closepath stroke
+0 0 0 nodecolor
+14 /Times-Roman set_font
+58.2989 275.3 moveto 104 (gnunet-zoneimport) alignedtext
+grestore
+% DNS->import
+gsave
+1 setlinewidth
+0 0 0 edgecolor
+newpath 110.2989 347.9735 moveto
+110.2989 336.1918 110.2989 320.5607 110.2989 307.1581 curveto
+stroke
+0 0 0 edgecolor
+newpath 113.799 307.0033 moveto
+110.2989 297.0034 lineto
+106.799 307.0034 lineto
+closepath fill
+1 setlinewidth
+solid
+0 0 0 edgecolor
+newpath 113.799 307.0033 moveto
+110.2989 297.0034 lineto
+106.799 307.0034 lineto
+closepath stroke
+0 0 0 edgecolor
+14 /Times-Roman set_font
+110.2989 318.8 moveto 37 (import) alignedtext
+grestore
+% namestore
+gsave
+1 setlinewidth
+0 0 0 nodecolor
+159.2989 192 47.3916 18 ellipse_path stroke
+0 0 0 nodecolor
+14 /Times-Roman set_font
+130.7989 188.3 moveto 57 (namestore) alignedtext
+grestore
+% import->namestore
+gsave
+1 setlinewidth
+0 0 0 edgecolor
+newpath 119.7466 262.2255 moveto
+126.7274 249.831 136.3701 232.7103 144.3867 218.4767 curveto
+stroke
+0 0 0 edgecolor
+newpath 147.5178 220.0495 moveto
+149.3756 209.6188 lineto
+141.4186 216.6143 lineto
+closepath fill
+1 setlinewidth
+solid
+0 0 0 edgecolor
+newpath 147.5178 220.0495 moveto
+149.3756 209.6188 lineto
+141.4186 216.6143 lineto
+closepath stroke
+0 0 0 edgecolor
+14 /Times-Roman set_font
+138.2989 231.8 moveto 35 (export) alignedtext
+grestore
+% namecache
+gsave
+1 setlinewidth
+0 0 0 nodecolor
+300.2989 105 50.0912 18 ellipse_path stroke
+0 0 0 nodecolor
+14 /Times-Roman set_font
+269.7989 101.3 moveto 61 (namecache) alignedtext
+grestore
+% namestore->namecache
+gsave
+1 setlinewidth
+0 0 0 edgecolor
+newpath 184.1823 176.6464 moveto
+206.9544 162.5955 240.8544 141.6785 266.1545 126.0678 curveto
+stroke
+0 0 0 edgecolor
+newpath 268.04 129.0171 moveto
+274.7125 120.7873 lineto
+264.3642 123.0598 lineto
+closepath fill
+1 setlinewidth
+solid
+0 0 0 edgecolor
+newpath 268.04 129.0171 moveto
+274.7125 120.7873 lineto
+264.3642 123.0598 lineto
+closepath stroke
+0 0 0 edgecolor
+14 /Times-Roman set_font
+238.2989 144.8 moveto 74 (pre-populates) alignedtext
+grestore
+% zonemaster
+gsave
+1 setlinewidth
+0 0 0 nodecolor
+newpath 159.2989 123 moveto
+86.5718 105 lineto
+159.2989 87 lineto
+232.0259 105 lineto
+closepath stroke
+0 0 0 nodecolor
+14 /Times-Roman set_font
+127.7989 101.3 moveto 63 (zonemaster) alignedtext
+grestore
+% namestore->zonemaster
+gsave
+1 setlinewidth
+0 0 0 edgecolor
+newpath 159.2989 173.9735 moveto
+159.2989 162.1918 159.2989 146.5607 159.2989 133.1581 curveto
+stroke
+0 0 0 edgecolor
+newpath 162.799 133.0033 moveto
+159.2989 123.0034 lineto
+155.799 133.0034 lineto
+closepath fill
+1 setlinewidth
+solid
+0 0 0 edgecolor
+newpath 162.799 133.0033 moveto
+159.2989 123.0034 lineto
+155.799 133.0034 lineto
+closepath stroke
+0 0 0 edgecolor
+14 /Times-Roman set_font
+159.2989 144.8 moveto 41 (notifies) alignedtext
+grestore
+% gns
+gsave
+1 setlinewidth
+0 0 0 nodecolor
+newpath 386.2989 210 moveto
+353.957 192 lineto
+386.2989 174 lineto
+418.6408 192 lineto
+closepath stroke
+0 0 0 nodecolor
+14 /Times-Roman set_font
+376.7989 188.3 moveto 19 (gns) alignedtext
+grestore
+% gns->namecache
+gsave
+1 setlinewidth
+0 0 0 edgecolor
+newpath 373.8052 180.5028 moveto
+366.3078 173.5201 356.6389 164.3674 348.2989 156 curveto
+339.8869 147.5605 330.8812 138.1087 322.969 129.6563 curveto
+stroke
+0 0 0 edgecolor
+newpath 325.434 127.1675 moveto
+316.0586 122.2327 lineto
+320.3103 131.937 lineto
+closepath fill
+1 setlinewidth
+solid
+0 0 0 edgecolor
+newpath 325.434 127.1675 moveto
+316.0586 122.2327 lineto
+320.3103 131.937 lineto
+closepath stroke
+0 0 0 edgecolor
+14 /Times-Roman set_font
+348.2989 144.8 moveto 24 (uses) alignedtext
+grestore
+% dht
+gsave
+1 setlinewidth
+0 0 0 nodecolor
+272.2989 18 27 18 ellipse_path stroke
+0 0 0 nodecolor
+14 /Times-Roman set_font
+263.2989 14.3 moveto 18 (dht) alignedtext
+grestore
+% gns->dht
+gsave
+1 setlinewidth
+0 0 0 edgecolor
+newpath 385.181 174.2737 moveto
+383.0587 152.2164 376.9318 114.1509 359.2989 87 curveto
+344.9772 64.9477 321.2191 46.8067 302.1458 34.6694 curveto
+stroke
+0 0 0 edgecolor
+newpath 303.8469 31.6069 moveto
+293.4925 29.3628 lineto
+300.1875 37.5742 lineto
+closepath fill
+1 setlinewidth
+solid
+0 0 0 edgecolor
+newpath 303.8469 31.6069 moveto
+293.4925 29.3628 lineto
+300.1875 37.5742 lineto
+closepath stroke
+0 0 0 edgecolor
+14 /Times-Roman set_font
+376.2989 101.3 moveto 40 (queries) alignedtext
+grestore
+% dns2gns
+gsave
+1 setlinewidth
+0 0 0 nodecolor
+newpath 336.3104 284.5623 moveto
+287.2989 297 lineto
+238.2874 284.5623 lineto
+238.3331 264.4377 lineto
+336.2646 264.4377 lineto
+closepath stroke
+0 0 0 nodecolor
+14 /Times-Roman set_font
+264.7989 275.3 moveto 45 (dns2gns) alignedtext
+grestore
+% dns2gns->gns
+gsave
+1 setlinewidth
+0 0 0 edgecolor
+newpath 304.0929 264.2416 moveto
+321.1237 249.2751 347.504 226.0924 365.7671 210.0431 curveto
+stroke
+0 0 0 edgecolor
+newpath 368.323 212.4564 moveto
+373.5243 203.2262 lineto
+363.7022 207.1983 lineto
+closepath fill
+1 setlinewidth
+solid
+0 0 0 edgecolor
+newpath 368.323 212.4564 moveto
+373.5243 203.2262 lineto
+363.7022 207.1983 lineto
+closepath stroke
+0 0 0 edgecolor
+14 /Times-Roman set_font
+343.2989 231.8 moveto 38 (lookup) alignedtext
+grestore
+% cmdline
+gsave
+1 setlinewidth
+0 0 0 nodecolor
+newpath 478.0186 284.5623 moveto
+416.2989 297 lineto
+354.5791 284.5623 lineto
+354.6367 264.4377 lineto
+477.961 264.4377 lineto
+closepath stroke
+0 0 0 nodecolor
+14 /Times-Roman set_font
+385.7989 275.3 moveto 61 (gnunet-gns) alignedtext
+grestore
+% cmdline->gns
+gsave
+1 setlinewidth
+0 0 0 edgecolor
+newpath 411.2098 264.2416 moveto
+406.7547 251.3219 400.1883 232.2795 394.9156 216.9885 curveto
+stroke
+0 0 0 edgecolor
+newpath 398.0825 215.4359 moveto
+391.5138 207.1232 lineto
+391.4649 217.7179 lineto
+closepath fill
+1 setlinewidth
+solid
+0 0 0 edgecolor
+newpath 398.0825 215.4359 moveto
+391.5138 207.1232 lineto
+391.4649 217.7179 lineto
+closepath stroke
+0 0 0 edgecolor
+14 /Times-Roman set_font
+403.2989 231.8 moveto 38 (lookup) alignedtext
+grestore
+% libnss_gns
+gsave
+1 setlinewidth
+0 0 0 nodecolor
+newpath 475.6981 371.5623 moveto
+416.2989 384 lineto
+356.8996 371.5623 lineto
+356.9551 351.4377 lineto
+475.6427 351.4377 lineto
+closepath stroke
+0 0 0 nodecolor
+14 /Times-Roman set_font
+387.2989 362.3 moveto 58 (libnss_gns) alignedtext
+grestore
+% libnss_gns->cmdline
+gsave
+1 setlinewidth
+0 0 0 edgecolor
+newpath 416.2989 351.2416 moveto
+416.2989 339.2263 416.2989 321.9156 416.2989 307.2516 curveto
+stroke
+0 0 0 edgecolor
+newpath 419.799 307.1553 moveto
+416.2989 297.1553 lineto
+412.799 307.1553 lineto
+closepath fill
+1 setlinewidth
+solid
+0 0 0 edgecolor
+newpath 419.799 307.1553 moveto
+416.2989 297.1553 lineto
+412.799 307.1553 lineto
+closepath stroke
+0 0 0 edgecolor
+14 /Times-Roman set_font
+416.2989 318.8 moveto 43 (invokes) alignedtext
+grestore
+% proxy
+gsave
+1 setlinewidth
+0 0 0 nodecolor
+newpath 677.8617 284.5623 moveto
+587.2989 297 lineto
+496.7361 284.5623 lineto
+496.8206 264.4377 lineto
+677.7771 264.4377 lineto
+closepath stroke
+0 0 0 nodecolor
+14 /Times-Roman set_font
+538.7989 275.3 moveto 97 (gnunet-gns-proxy) alignedtext
+grestore
+% proxy->gns
+gsave
+1 setlinewidth
+0 0 0 edgecolor
+newpath 553.202 264.2416 moveto
+513.9908 247.2697 450.3696 219.7321 414.0521 204.0126 curveto
+stroke
+0 0 0 edgecolor
+newpath 415.1432 200.6711 moveto
+404.5757 199.9109 lineto
+412.3626 207.0952 lineto
+closepath fill
+1 setlinewidth
+solid
+0 0 0 edgecolor
+newpath 415.1432 200.6711 moveto
+404.5757 199.9109 lineto
+412.3626 207.0952 lineto
+closepath stroke
+0 0 0 edgecolor
+14 /Times-Roman set_font
+499.2989 231.8 moveto 38 (lookup) alignedtext
+grestore
+% zonemaster->dht
+gsave
+1 setlinewidth
+0 0 0 edgecolor
+newpath 177.2041 91.2146 moveto
+195.8835 76.8331 225.3438 54.1513 246.5248 37.8438 curveto
+stroke
+0 0 0 edgecolor
+newpath 248.689 40.5947 moveto
+254.4775 31.7209 lineto
+244.4186 35.0482 lineto
+closepath fill
+1 setlinewidth
+solid
+0 0 0 edgecolor
+newpath 248.689 40.5947 moveto
+254.4775 31.7209 lineto
+244.4186 35.0482 lineto
+closepath stroke
+0 0 0 edgecolor
+14 /Times-Roman set_font
+223.2989 57.8 moveto 52 (publishes) alignedtext
+grestore
+endpage
+showpage
+grestore
+%%PageTrailer
+%%EndPage: 1
+%%Trailer
+end
+restore
+%%EOF
diff --git a/doc/handbook/images/structure.dot b/doc/handbook/images/structure.dot
index a53db90b8097b282cabd6909fcb80a3e9cf08baf..f3cf193d85e4990da5cbd6e014a349445e98f125 100644
--- a/doc/handbook/images/structure.dot
+++ b/doc/handbook/images/structure.dot
@@ -52,7 +52,7 @@ splines = true;
   gns -> dnsstub;
   gns -> identity;
   revocation -> core;
-  revocation -> set;
+  revocation -> setu;
   namestore -> identity;
   namestore -> gnsrecord;
   dnsparser -> gnsrecord [style=dotted,color=blue];
@@ -96,9 +96,11 @@ splines = true;
   transport -> fragmentation;
   consensus -> set;
   consensus -> cadet;
-  scalarproduct -> set;
+  scalarproduct -> seti;
   scalarproduct -> cadet;
   set -> cadet;
+  seti -> cadet;
+  setu -> cadet;
   peerinfo -> hello;
   fragmentation [shape=diamond];
   hello [shape=diamond];
diff --git a/doc/index.html b/doc/index.html
new file mode 100644
index 0000000000000000000000000000000000000000..93c0e7d9e0a67d13b19e604da5801af52e2819b4
--- /dev/null
+++ b/doc/index.html
@@ -0,0 +1,65 @@
+<html>
+  <head>
+    <title>GNUnet - GNUnet Manuals and Handbooks</title>
+    <meta charset="utf-8">
+    <meta name="keywords" content="gnunet,GNUnet,Manual,Manuals,preview,developer-preview,inofficial,GNU">
+    <meta name="description" content="The GNUnet Manuals">
+    <link href="style.css" rel="stylesheet">
+    <meta name="viewport" content="width=device-width, initial-scale=1">
+  </head>
+
+  <body>
+    <center>
+      <h1>GNUnet - GNUnet Manuals and Handbooks</h1>
+    </center>
+
+    <blockquote><address>
+        GNUnet e.V.<br/>
+        Fakult&auml;t f&uuml;r Informatik -- I8<br/>
+        Technische Universit&auml;t M&uuml;nchen<br/>
+        Boltzmannstra&szlig;e 3<br/>
+        85748 Garching<br/>
+        GERMANY<br/>
+    </address></blockquote>
+
+    <p>The following handbooks and manuals are available:</p>
+
+    <ul>
+      <li><a href="/handbook/gnunet.html">GNUnet Reference Manual</li>
+      <li><a href="/tutorial/gnunet-tutorial.html">GNUnet C Tutorial</li>
+      <li><a href="/doxygen/">GNUnet Doxygen</li>
+      <li><a href="https://rest.gnunet.org/">REST API</a></li>
+      <li><a href="https://bib.gnunet.org/">Bibliography</a></li>
+    </ul>
+
+    <div id="footer">
+      <div class="unprintable">
+
+        <p>Please send general FSF &amp; GNU inquiries to
+          <a href="mailto:gnu@gnu.org">&lt;gnu@gnu.org&gt;</a>.
+          There are also <a href="https://gnunet.org/en/contact/">other
+          ways to contact</a>
+          us.  Broken links and other corrections or suggestions can be sent
+          to <a href="mailto:gnunet-developers@gnu.org">&lt;gnunet-developers@gnu.org&gt;</a>.</p>
+      </div>
+
+      <p>Copyright &copy; 2001 - 2020 GNUnet e.V.</p>
+
+      <p>
+        <a rel="license" href="http://creativecommons.org/licenses/by-nd/4.0/">
+          <img alt="Creative Commons License"
+               style="border-width:0"
+               src="https://i.creativecommons.org/l/by-nd/4.0/88x31.png" />
+        </a>
+        <br />
+        This page is licensed under a
+        <a rel="license"
+           href="http://creativecommons.org/licenses/by-nd/4.0/">
+          Creative Commons Attribution-NoDerivatives 4.0 International License
+        </a>. Individual Manuals are licensed under the licenses mentioned within
+        the books (GNU Free Documentation License, GNU General Public License).
+      </p>
+    </div>
+
+  </body>
+</html>
diff --git a/doc/man/.gitignore b/doc/man/.gitignore
new file mode 100644
index 0000000000000000000000000000000000000000..38ed678729293d528cce03b60912a2746f338ba8
--- /dev/null
+++ b/doc/man/.gitignore
@@ -0,0 +1,5 @@
+gnunet.conf.5
+groff_lint.log
+*.html
+gnunet-c-tutorial.7
+gnunet-documentation.7
diff --git a/doc/man/gnunet-testing.1 b/doc/man/gnunet-testing.1
new file mode 100644
index 0000000000000000000000000000000000000000..7d40152accee324ed81be6f9b89889a15b6ddcc3
--- /dev/null
+++ b/doc/man/gnunet-testing.1
@@ -0,0 +1,94 @@
+.\" This file is part of GNUnet.
+.\" Copyright (C) 2001-2019 GNUnet e.V.
+.\"
+.\" Permission is granted to copy, distribute and/or modify this document
+.\" under the terms of the GNU Free Documentation License, Version 1.3 or
+.\" any later version published by the Free Software Foundation; with no
+.\" Invariant Sections, no Front-Cover Texts, and no Back-Cover Texts.  A
+.\" copy of the license is included in the file
+.\" FDL-1.3.
+.\"
+.\" A copy of the license is also available from the Free Software
+.\" Foundation Web site at http://www.gnu.org/licenses/fdl.html}.
+.\"
+.\" Alternately, this document is also available under the General
+.\" Public License, version 3 or later, as published by the Free Software
+.\" Foundation.  A copy of the license is included in the file
+.\" GPL3.
+.\"
+.\" A copy of the license is also available from the Free Software
+.\" Foundation Web site at http://www.gnu.org/licenses/gpl.html
+.\"
+.\" SPDX-License-Identifier: GPL3.0-or-later OR FDL1.3-or-later
+.\"
+.Dd January 4, 2012
+.Dt GNUNET-TESTING 1
+.Os
+.Sh NAME
+.Nm gnunet-testing
+.Nd command line tool to access the testing library
+.Sh SYNOPSIS
+.Nm
+.Op Fl C | -cfg
+.Op Fl c Ar FILENAME | Fl -config= Ns Ar FILENAME
+.Op Fl H | -hostkeys
+.Op Fl h | -help
+.Op Fl k | -key
+.Op Fl L Ar LOGLEVEL | Fl -loglevel= Ns Ar LOGLEVEL
+.Op Fl l Ar LOGFILE | Fl -logfile= Ns Ar LOFILE
+.Op Fl n | -number
+.Op Fl t | -template
+.Op Fl v | -version
+.Sh DESCRIPTION
+.Nm
+is a command line tool to access the testing library.
+.Sh OPTIONS
+.Bl -tag -width indent
+.It Fl C | -cfg
+Create unique configuration files.
+.It Fl c Ar FILENAME | Fl -config= Ns Ar FILENAME
+Use the configuration file
+.Ar FILENAME .
+.It Fl H | -hostkeys
+Host key file.
+.It Fl h | -help
+Print short help on options.
+.It Fl k | -key
+Create hostkey files from pre-computed hostkey list.
+.It Fl L Ar LOGLEVEL | Fl -loglevel= Ns Ar LOGLEVEL
+Use LOGLEVEL for logging.
+Valid values are DEBUG, INFO, WARNING and ERROR.
+.It Fl l Ar LOGFILE | Fl -logfile= Ns Ar LOFILE
+Configure logging to write logs to
+.Ar LOGFILE .
+.It Fl n | -number
+Number of unique configuration files or hostkeys to create.
+.It Fl t | -template
+Configuration template.
+.It Fl v | -version
+Print GNUnet version number.
+.El
+.Sh SEE ALSO
+The full documentation for gnunet is maintained as a Texinfo manual.
+If the
+.Xr info 1
+and gnunet programs are properly installed at your site, the command
+.Pp
+.Dl info gnunet
+.Pp
+should give you access to the complete handbook,
+.Pp
+.Dl info gnunet-c-tutorial
+.Pp
+will give you access to a tutorial for developers.
+.sp
+Depending on your installation, this information is also available in
+.Xr gnunet 7 and
+.Xr gnunet-c-tutorial 7 .
+.\".Sh HISTORY
+.\".Sh AUTHORS
+.Sh BUGS
+Report bugs by using
+.Lk https://bugs.gnunet.org
+or by sending electronic mail to
+.Aq Mt gnunet-developers@gnu.org .
diff --git a/doc/manual.css b/doc/manual.css
new file mode 100644
index 0000000000000000000000000000000000000000..0fe08b83cb4df83c71701f21999e6f4824cd6f64
--- /dev/null
+++ b/doc/manual.css
@@ -0,0 +1,52 @@
+/* Style-sheet to use for manuals (copied from Emacs) */
+
+@import url('style.css');
+
+/* makeinfo 6.5 converts @quotation to <blockquote>.  Highlight them.  */
+blockquote {
+    font-style: normal;
+    border-left: solid 10px red;
+    padding-left: 2.5%;
+    margin-left: 0px;
+}
+
+var { font-style: italic; }
+
+/* Lay out @lisp just like @example.  Copied from what /style.css
+   does for the 'example' class.  */
+div.lisp { padding: .8em 1.2em .4em; }
+pre.lisp { padding: .8em 1.2em; }
+div.lisp, pre.lisp {
+   margin: 1em 0 1em 3% ;
+   -webkit-border-radius: .3em;
+   -moz-border-radius: .3em;
+   border-radius: .3em;
+   border: 1px solid #d4cbb6;
+   background-color: #f2efe4;
+}
+div.lisp > pre.lisp {
+   padding: 0 0 .4em;
+   margin: 0;
+   border: none;
+}
+
+/* ----- coreutils specific styling ----- */
+
+/* layout.css indents "body p" when it should probably only indent "body > p"?
+   In any case, disable indenting of p in these sub elements.  */
+dd p,li p {
+    margin-left: 0;
+    margin-right: 0;
+}
+
+/* underlined links are distracting, especially within outlined tables.  */
+a { /*add :link for external links*/
+    text-decoration: none; /* don't underline links by default */
+    outline-style: none;   /* don't put dotted box around clicked links */
+}
+a:hover {
+    text-decoration: underline;
+}
+
+/* The shadow around the body is distracting.  */
+body { box-shadow: 0 0 0 0; }
diff --git a/doc/release_policy.rfc.txt b/doc/release_policy.rfc.txt
new file mode 100644
index 0000000000000000000000000000000000000000..8fd89f73c2d9de2be087e8cc26131230895996ca
--- /dev/null
+++ b/doc/release_policy.rfc.txt
@@ -0,0 +1,183 @@
+***********************************************************************
+********************* Release Policy (RFC) ****************************
+***********************************************************************
+
+We suggest this structure of the proposal document as part of a tiny
+social process in order to find a decision in a cooperativ and common
+way.
+
+
+I. Driver 
+=========
+(What is the problem and what solution did we find?)
+
+In the past it was sometimes unclear when and how the community would reach its
+next release. Members were lacking in orientation and felt demotivated. 
+
+Another minor concern not yet analysed in depth was the expectation to show the
+public that the GNUnet project is still active and making progress. With an old
+release distributed by popular linux distributions it was hard to showcase
+people the GNUnet features and encourage to participate in the project. 
+
+To show people how the GNUnet project is releasing its software we hereby
+document the current release model:
+
+* All main development (e.g. towards 0.12.x) continues on master.
+* Developers can continue to develop features in their own feature
+  branches, but are encouraged to frequently merge into master (as long as they
+  don't break the build) to avoid divergence and to detect issues from a
+  merge/rebase early.
+* 0.11.x releases *must* be protocol-compatible to 0.11.0. So once
+  master is NOT protocol-compatible to 0.11.0, development for 0.11.x
+  must continue in an 0.11-branch where we only cherry-pick those
+  changes from master that preserve protocol-compatibility.
+* better CI may allow us to detect breaking changes before merges in the future
+  (but we shall never fault anybody for breaking stuff in master in non-obvious
+  ways);
+* actual _release policy_:
+  - tests must pass
+  - no compiler warnings for -Wall
+  - acceptance tests (manual feature test) must succeed
+  - no known "release critical" bugs (where RC has no formal definition,
+    mostly we rather explicitly declare certain bugs as "not critical")
+  - Whenever API changes happen the person making that changes should update
+    dependencies or at least work with people who hack on the dependencies to
+    cooridnate the adjustments
+  o buildbots are happy (if running)
+  o static analysis is happy (if available, false-positives => ignore)
+  o documentation is reasonably up-to-date
+  + reasonable test coverage (if too terrible => move subsystem to experimental?)
+  + texinfo (HTML+PDF) and doxygen happy? Ideally without warnings!
+  + nobody screaming bloody murder because of almost-completed features/bugfixes
+    almost ready to be merged?
+  Legend: -: absolutely mandatory; o: important; +: nice to have
+
+
+For further information see: https://trunkbaseddevelopment.com/
+
+II. Evaluation Criteria 
+=======================
+(what are criterias to interprete the results as success if we review
+the problem and solution after a year or so)
+
+III. Concerns (of team members)
+===============================
+(if there are concerns of team members, write them down here to later
+review)
+
+I disagree that "bugs tend to accumulate until they are not managable".
+The real issue is that neither writing testcases nor fixing bugs are
+fun tasks volunteers like to do. As you write yourself: you want a
+sense of achievement, recognition, "new features".  So as long as that
+is what you are motivated to do, you will not get stable, well-tested
+code. I don't have a magic bullet to motivate you to write more tests,
+or to improve existing tests. -CG
+
+  Your argument is good. Two or three of us thought that the problem is about
+  missing releases which we feld demotivating. We thought, we were stucked
+  somewhere. But as you state, it is us not doing the necessary work. What I
+  still find useful is to document the release process. In consequence I
+  changed the problem statement. -xrs
+
+I also disagree that releases have to be 'known bug free'.  That bar is
+way too high. However, there are obviously 'critical' bugs, but what
+they are is another debate.  But not all bugs are critical. Also,
+I would distinguish between 'standard' and 'experimental' subsystems.
+Experimental subsystems should build. They don't have to run, or do
+anything useful. Not even tests have to pass for a release IMO. -CG
+
+  Thank you, I agree and changed it. -xrs
+
+Git is also not a "release model".  Git is a software development
+tool.  But introducing branches in Git won't fix bugs. It also won't
+improve test coverage. It won't test the code on a broad range of
+platforms.  It also doubt it will give you the recognition you crave.
+More importantly, what you describe is already happening, and
+partially has contributed to the problems. Bart kept his own CADET
+hacks in his personal branch for years, hence without much feedback or
+review.  The secushare team kept their patches in their own branch,
+hence revealing interesting failure modes when it was finally merged.
+Martin kept some of his ABE-logic in his own branch (that one was
+merged without me noticing major problems).  Anyway, what you propose
+as Option 1 is already largely done, except that certain CI tasks
+simply cannot be productively done pre-merge right now (and I'm all
+for improving that situation). -CG
+
+  With resprect to changes kept in branches the reason why I personally keep
+  changes back is because it takes very long for me to get something really
+  working in C. Before that I either not worth it or I don't want to blame
+  other before not being sure it's not my fault. 
+
+  Can we track branches? Can we write a little cronjob that checks for branches
+  that are to long undercover with the aim to recommend the responsible person
+  to merge soon?
+  - xrs
+
+Finally, there is one last elephant with respect to branches and
+merging that I would like you to consider. Given that GNUnet is highly
+modular, you have largely benefited from the modular architecture and
+been able to hack in your respective corners, unaffected by other
+modules (modulo bugs in dependencies).  That is great, and the desired
+development mode.  It has the critical advantage that bugs in modules
+that nobody depends upon (auction, rps, social) can be in 'master' and
+won't disturb anything. As most new development usually happens on the
+leaves of the dependency graph, that is great.  However, occasionally
+there are architectural changes. Not of the type where the graph
+changes, but where key API assumptions change. We recently had one for
+the GNU Name System with the dropping of ".gnu".  Before, CADET
+changed the semantics and paramter for 'port'.  In the future, CORE
+will introduce protocol versioning.  Whenever such a change happens,
+it usually falls upon the person making that change to update
+dependencies as well (or at least to work with people who hack on the
+dependencies to coordinate the adjustments).  That way, changing an
+API for in-tree dependencies is a minor nuisance.  However, if
+branches exist, making sure that API changes do not break _any_ branch
+somewhere is impractical.  So at least at times where "major" API
+rewrites are happening, it is important to minimize the number of
+branches. -CG
+
+  Thank you for clarifying. I added the API aspect above. -xrs
+  
+
+IV. Doing
+=========
+(who does what within which time frame?)
+
+Let me list what I think needs doing:
+
+1) Better CI setup: build on multiple platforms, build of
+   "arbitrary" branches, reporting of regressions with
+   decent diagnostics (!) to developers (not the crap
+   Gitlab gives where I don't even easily get a stack
+   trace on a core dump).
+2) A culture of fixing "other people"'s bugs: test case failures,
+   portability issues, Mantis reports, all the non-sexy
+   stuff.  Not the 'psycstore' was written by tg, so no
+   need for !tg to try to fix it, or the "I use sqlite, 
+   why should I bother with postgres?"-crap I have heard
+   too often.
+3) Improving test cases: better code coverage, more corner
+   cases, complex deployment scenarios (NAT!), etc.;
+   less manual testing by hand, more writing automated
+   tests.
+4) There are also some bigger architectural changes ahead
+   that I have mentioned in other places.  Without those,
+   we won't be able to serve non-expert users.  So help
+   with those would be welcome, but in terms of _process_
+   I think 1-3 is what matters.
+
+Note that none of this really adds up to a "release policy".
+
+  We should thing and talk about point 2 and 3 more in depth with the question
+  in mind, how to make this task more attractive for the community :-)
+
+
+V. Previous Versions
+====================
+(if we found some flaws in the solution, and we want to change the
+release policy, we document the old ones here als previous versions.
+the goal is establish a learn process.)
+
+IV. References
+==============
+(if there are references to paper, web pages and other sources.)
diff --git a/doc/reset.css b/doc/reset.css
new file mode 100644
index 0000000000000000000000000000000000000000..9a6c3065f81b6cfdedc2f6d3d219adeb74035091
--- /dev/null
+++ b/doc/reset.css
@@ -0,0 +1,114 @@
+/*
+Software License Agreement (BSD License)
+
+Copyright (c) 2006, Yahoo! Inc.
+All rights reserved.
+
+Redistribution and use of this software in source and
+binary forms, with or without modification, arepermitted
+provided that the following conditions are met:
+
+* Redistributions of source code must retain the above
+copyright notice, this list of conditions and the
+following disclaimer.
+
+* Redistributions in binary form must reproduce the above
+copyright notice, this list of conditions and the
+following disclaimer in the documentation and/or other
+materials provided with the distribution.
+
+* Neither the name of Yahoo! Inc. nor the names of its
+contributors may be used to endorse or promote products
+derived from this software without specific prior
+written permission of Yahoo! Inc.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+SUCH DAMAGE.
+*/
+
+html {
+    color: #000;
+    background: #FFF;
+}
+
+body, div, dl, dt, dd, ul, ol, li, h1, h2, h3, h4,
+h5, h6, pre, code, form, fieldset, legend, input,
+button, textarea, p, blockquote, th, td {
+    margin: 0;
+    padding: 0;
+}
+
+table {
+    border-collapse: collapse;
+    border-spacing: 0;
+}
+
+fieldset, img {
+    border: 0;
+}
+
+address, caption, cite, code, dfn, em, strong,
+th, var, optgroup {
+    font-style: inherit;
+    font-weight: inherit;
+}
+
+del, ins {
+    text-decoration: none;
+}
+
+li {
+    list-style:none;
+}
+
+caption, th {
+    text-align: left;
+}
+
+h1, h2, h3, h4, h5, h6 {
+    font-size: 100%;
+    font-weight: normal;
+}
+
+q:before, q:after {
+    content:'';
+}
+
+abbr, acronym {
+    border: 0;
+    font-variant: normal;
+}
+
+sup {
+    vertical-align: baseline;
+}
+sub {
+    vertical-align: baseline;
+}
+
+legend {
+    color: #000;
+}
+
+input, button, textarea, select, optgroup, option {
+    font-family: inherit;
+    font-size: inherit;
+    font-style: inherit;
+    font-weight: inherit;
+}
+
+input, button, textarea, select {
+    *font-size: 100%;
+}
diff --git a/doc/style.css b/doc/style.css
new file mode 100644
index 0000000000000000000000000000000000000000..e5271197bb7fa66f78ed02e5078fdc2b25ffe69f
--- /dev/null
+++ b/doc/style.css
@@ -0,0 +1,174 @@
+/* This stylesheet is used by manuals and a few older resources. */
+
+@import url('reset.css');
+
+
+/***  PAGE LAYOUT  ***/
+
+html, body {
+   font-size: 1em;
+   text-align: left;
+   text-decoration: none;
+}
+html { background-color: #e7e7e7; }
+
+body {
+   max-width: 74.92em;
+   margin: 0 auto;
+   padding: .5em 1em 1em 1em;
+   background-color: white;
+   border: .1em solid #c0c0c0;
+}
+
+
+/*** BASIC ELEMENTS ***/
+
+/* Size and positioning */
+
+p, pre, li, dt, dd, table, code, address { line-height: 1.3em; }
+
+h1 { font-size: 2em; margin: 1em 0 }
+h2 { font-size: 1.50em; margin: 1.0em 0 0.87em 0; }
+h3 { font-size: 1.30em; margin: 1.0em 0 0.87em 0; }
+h4 { font-size: 1.13em; margin: 1.0em 0 0.88em 0; }
+h5 { font-size: 1.00em; margin: 1.0em 0 1.00em 0; }
+
+p, pre { margin: 1em 0; }
+pre { overflow: auto; padding-bottom: .3em; }
+
+ul, ol, blockquote { margin-left: 1.5%; margin-right: 1.5%; }
+hr { margin: 1em 0; }
+/* Lists of underlined links are difficult to read. The top margin
+   gives a little more spacing between entries. */
+ul li { margin: .5em 1em; }
+ol li { margin: 1em; }
+ol ul li { margin: .5em 1em; }
+ul li p, ul ul li { margin-top: .3em; margin-bottom: .3em; }
+ul ul, ol ul { margin-top: 0; margin-bottom: 0; }
+
+/* Separate description lists from preceding text */
+dl { margin: 1em 0 0 0; }
+/* separate the "term" from subsequent "description" */
+dt { margin: .5em 0; }
+/* separate the "description" from subsequent list item
+   when the final <dd> child is an anonymous box */
+dd { margin: .5em 3% 1em 3%; }
+/* separate anonymous box (used to be the first element in <dd>)
+   from subsequent <p> */
+dd p { margin: .5em 0; }
+
+table {
+   display: block; overflow: auto;
+   margin-top: 1.5em; margin-bottom: 1.5em;
+}
+th { padding: .3em .5em; text-align: center; }
+td { padding: .2em .5em; }
+
+address { margin-bottom: 1em; }
+caption { margin-bottom: .5em; text-align: center; }
+sup { vertical-align: super; }
+sub { vertical-align: sub; }
+
+/* Style */
+
+h1, h2, h3, h4, h5, h6, strong, dt, th { font-weight: bold; }
+
+/* The default color (black) is too dark for large text in
+   bold font. */
+h1, h2, h3, h4 { color: #333; }
+h5, h6, dt { color: #222; }
+
+a[href] { color: #005090; }
+a[href]:visited { color: #100070; }
+a[href]:active, a[href]:hover {
+   color: #100070;
+   text-decoration: none;
+}
+
+h1 a[href]:visited, h2 a[href]:visited, h3 a[href]:visited,
+ h4 a[href]:visited { color: #005090; }
+h1 a[href]:hover, h2 a[href]:hover, h3 a[href]:hover,
+ h4 a[href]:hover { color: #100070; }
+
+ol { list-style: decimal outside;}
+ul { list-style: square outside; }
+ul ul, ol ul { list-style: circle; }
+li { list-style: inherit; }
+
+hr { background-color: #ede6d5; }
+table { border: 0; }
+
+abbr,acronym {
+   border-bottom:1px dotted #000;
+   text-decoration: none;
+   cursor:help;
+}
+del { text-decoration: line-through; }
+em { font-style: italic; }
+small { font-size: .9em; }
+
+img { max-width: 100%}
+
+
+/*** SIMPLE CLASSES ***/
+
+.center, .c { text-align: center; }
+.nocenter{ text-align: left; }
+
+.underline { text-decoration: underline; }
+.nounderline { text-decoration: none; }
+
+.no-bullet { list-style: none; }
+.inline-list li { display: inline }
+
+.netscape4, .no-display { display: none; }
+
+
+/*** MANUAL PAGES ***/
+
+/* This makes the very long tables of contents in Gnulib and other
+   manuals easier to read. */
+.contents ul, .shortcontents ul { font-weight: bold; }
+.contents ul ul, .shortcontents ul ul { font-weight: normal; }
+.contents ul { list-style: none; }
+
+/* For colored navigation bars (Emacs manual): make the bar extend
+   across the whole width of the page and give it a decent height. */
+.header, .node { margin: 0 -1em; padding: 0 1em; }
+.header p, .node p { line-height: 2em; }
+
+/* For navigation links */
+.node a, .header a { display: inline-block; line-height: 2em; }
+.node a:hover, .header a:hover { background: #f2efe4; }
+
+/* Inserts */
+table.cartouche td { padding: 1.5em; }
+
+div.display, div.lisp, div.smalldisplay,
+ div.smallexample, div.smalllisp { margin-left: 3%; }
+
+div.example { padding: .8em 1.2em .4em; }
+pre.example { padding: .8em 1.2em; }
+div.example, pre.example {
+   margin: 1em 0 1em 3% ;
+   -webkit-border-radius: .3em;
+   -moz-border-radius: .3em;
+   border-radius: .3em;
+   border: 1px solid #d4cbb6;
+   background-color: #f2efe4;
+}
+div.example > pre.example {
+   padding: 0 0 .4em;
+   margin: 0;
+   border: none;
+}
+
+pre.menu-comment { padding-top: 1.3em; margin: 0; }
+
+
+/*** FOR WIDE SCREENS ***/
+
+@media (min-width: 40em) {
+   body { padding: .5em 3em 1em 3em; }
+   div.header, div.node { margin: 0 -3em; padding: 0 3em; }
+}
diff --git a/doc/tutorial/.gitignore b/doc/tutorial/.gitignore
new file mode 100644
index 0000000000000000000000000000000000000000..11bb2078e10043a5682f4b7ac318e594d4ce96c2
--- /dev/null
+++ b/doc/tutorial/.gitignore
@@ -0,0 +1,11 @@
+stamp-1
+version2.texi
+tutorial
+*.fn
+*.fns
+*.ky
+*.pg
+*.tp
+*.vr
+tutorial
+tutorial.html
diff --git a/m4/.gitignore b/m4/.gitignore
new file mode 100644
index 0000000000000000000000000000000000000000..c4c8d29159e47c926b06e1a9c606eb6373ad3184
--- /dev/null
+++ b/m4/.gitignore
@@ -0,0 +1,6 @@
+libtool.m4
+ltoptions.m4
+ltsugar.m4
+ltversion.m4
+lt~obsolete.m4
+wchar_t.m4
diff --git a/m4/ac_define_dir.m4 b/m4/ac_define_dir.m4
new file mode 100644
index 0000000000000000000000000000000000000000..c4f07c50b3e2b30bdb9b96a55dbaabf085768576
--- /dev/null
+++ b/m4/ac_define_dir.m4
@@ -0,0 +1,35 @@
+dnl @synopsis AC_DEFINE_DIR(VARNAME, DIR [, DESCRIPTION])
+dnl
+dnl This macro _AC_DEFINEs VARNAME to the expansion of the DIR
+dnl variable, taking care of fixing up ${prefix} and such.
+dnl
+dnl VARNAME is offered as both a C preprocessor symbol, and an output
+dnl variable.
+dnl
+dnl Note that the 3 argument form is only supported with autoconf 2.13
+dnl and later (i.e. only where _AC_DEFINE supports 3 arguments).
+dnl
+dnl Examples:
+dnl
+dnl    AC_DEFINE_DIR(DATADIR, datadir)
+dnl    AC_DEFINE_DIR(PROG_PATH, bindir, [Location of installed binaries])
+dnl
+dnl @category Misc
+dnl @author Stepan Kasal <kasal@ucw.cz>
+dnl @author Andreas Schwab <schwab@suse.de>
+dnl @author Guido Draheim <guidod@gmx.de>
+dnl @author Alexandre Oliva
+dnl @version 2005-01-17
+dnl @license AllPermissive
+
+AC_DEFUN([AC_DEFINE_DIR], [
+  prefix_NONE=
+  exec_prefix_NONE=
+  test "x$prefix" = xNONE && prefix_NONE=yes && prefix=$ac_default_prefix
+  test "x$exec_prefix" = xNONE && exec_prefix_NONE=yes && exec_prefix=$prefix
+  eval ac_define_dir="\"[$]$2\""
+  AC_SUBST($1, "$ac_define_dir")
+  AC_DEFINE_UNQUOTED($1, "$ac_define_dir", [$3])
+  test "$prefix_NONE" && prefix=NONE
+  test "$exec_prefix_NONE" && exec_prefix=NONE
+])
diff --git a/m4/extensions.m4 b/m4/extensions.m4
new file mode 100644
index 0000000000000000000000000000000000000000..1330503f0d77cf417f4e1e54062f258246401afb
--- /dev/null
+++ b/m4/extensions.m4
@@ -0,0 +1,118 @@
+# serial 9  -*- Autoconf -*-
+# Enable extensions on systems that normally disable them.
+
+# Copyright (C) 2003, 2006-2011 Free Software Foundation, Inc.
+# This file 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 definition of AC_USE_SYSTEM_EXTENSIONS is stolen from CVS
+# Autoconf.  Perhaps we can remove this once we can assume Autoconf
+# 2.62 or later everywhere, but since CVS Autoconf mutates rapidly
+# enough in this area it's likely we'll need to redefine
+# AC_USE_SYSTEM_EXTENSIONS for quite some time.
+
+# If autoconf reports a warning
+#     warning: AC_COMPILE_IFELSE was called before AC_USE_SYSTEM_EXTENSIONS
+# or  warning: AC_RUN_IFELSE was called before AC_USE_SYSTEM_EXTENSIONS
+# the fix is
+#   1) to ensure that AC_USE_SYSTEM_EXTENSIONS is never directly invoked
+#      but always AC_REQUIREd,
+#   2) to ensure that for each occurrence of
+#        AC_REQUIRE([AC_USE_SYSTEM_EXTENSIONS])
+#      or
+#        AC_REQUIRE([gl_USE_SYSTEM_EXTENSIONS])
+#      the corresponding gnulib module description has 'extensions' among
+#      its dependencies. This will ensure that the gl_USE_SYSTEM_EXTENSIONS
+#      invocation occurs in gl_EARLY, not in gl_INIT.
+
+# AC_USE_SYSTEM_EXTENSIONS
+# ------------------------
+# Enable extensions on systems that normally disable them,
+# typically due to standards-conformance issues.
+# Remember that #undef in AH_VERBATIM gets replaced with #define by
+# AC_DEFINE.  The goal here is to define all known feature-enabling
+# macros, then, if reports of conflicts are made, disable macros that
+# cause problems on some platforms (such as __EXTENSIONS__).
+AC_DEFUN_ONCE([AC_USE_SYSTEM_EXTENSIONS],
+[AC_BEFORE([$0], [AC_COMPILE_IFELSE])dnl
+AC_BEFORE([$0], [AC_RUN_IFELSE])dnl
+
+  AC_REQUIRE([AC_CANONICAL_HOST])
+
+  AC_CHECK_HEADER([minix/config.h], [MINIX=yes], [MINIX=])
+  if test "$MINIX" = yes; then
+    AC_DEFINE([_POSIX_SOURCE], [1],
+      [Define to 1 if you need to in order for `stat' and other
+       things to work.])
+    AC_DEFINE([_POSIX_1_SOURCE], [2],
+      [Define to 2 if the system does not provide POSIX.1 features
+       except with this defined.])
+    AC_DEFINE([_MINIX], [1],
+      [Define to 1 if on MINIX.])
+  fi
+
+  dnl HP-UX 11.11 defines mbstate_t only if _XOPEN_SOURCE is defined to 500,
+  dnl regardless of whether the flags -Ae or _D_HPUX_SOURCE=1 are already
+  dnl provided.
+  case "$host_os" in
+    hpux*)
+      AC_DEFINE([_XOPEN_SOURCE], [500],
+        [Define to 500 only on HP-UX.])
+      ;;
+  esac
+
+  AH_VERBATIM([__EXTENSIONS__],
+[/* Enable extensions on AIX 3, Interix.  */
+#ifndef _ALL_SOURCE
+# undef _ALL_SOURCE
+#endif
+/* Enable GNU extensions on systems that have them.  */
+#ifndef _GNU_SOURCE
+# undef _GNU_SOURCE
+#endif
+/* Enable threading extensions on Solaris.  */
+#ifndef _POSIX_PTHREAD_SEMANTICS
+# undef _POSIX_PTHREAD_SEMANTICS
+#endif
+/* Enable extensions on HP NonStop.  */
+#ifndef _TANDEM_SOURCE
+# undef _TANDEM_SOURCE
+#endif
+/* Enable general extensions on Solaris.  */
+#ifndef __EXTENSIONS__
+# undef __EXTENSIONS__
+#endif
+])
+  AC_CACHE_CHECK([whether it is safe to define __EXTENSIONS__],
+    [ac_cv_safe_to_define___extensions__],
+    [AC_COMPILE_IFELSE(
+       [AC_LANG_PROGRAM([[
+#         define __EXTENSIONS__ 1
+          ]AC_INCLUDES_DEFAULT])],
+       [ac_cv_safe_to_define___extensions__=yes],
+       [ac_cv_safe_to_define___extensions__=no])])
+  test $ac_cv_safe_to_define___extensions__ = yes &&
+    AC_DEFINE([__EXTENSIONS__])
+  AC_DEFINE([_ALL_SOURCE])
+  AC_DEFINE([_GNU_SOURCE])
+  AC_DEFINE([_POSIX_PTHREAD_SEMANTICS])
+  AC_DEFINE([_TANDEM_SOURCE])
+])# AC_USE_SYSTEM_EXTENSIONS
+
+# gl_USE_SYSTEM_EXTENSIONS
+# ------------------------
+# Enable extensions on systems that normally disable them,
+# typically due to standards-conformance issues.
+AC_DEFUN_ONCE([gl_USE_SYSTEM_EXTENSIONS],
+[
+  dnl Require this macro before AC_USE_SYSTEM_EXTENSIONS.
+  dnl gnulib does not need it. But if it gets required by third-party macros
+  dnl after AC_USE_SYSTEM_EXTENSIONS is required, autoconf 2.62..2.63 emit a
+  dnl warning: "AC_COMPILE_IFELSE was called before AC_USE_SYSTEM_EXTENSIONS".
+  dnl Note: We can do this only for one of the macros AC_AIX, AC_GNU_SOURCE,
+  dnl AC_MINIX. If people still use AC_AIX or AC_MINIX, they are out of luck.
+  AC_REQUIRE([AC_GNU_SOURCE])
+
+  AC_REQUIRE([AC_USE_SYSTEM_EXTENSIONS])
+])
diff --git a/m4/extern-inline.m4 b/m4/extern-inline.m4
new file mode 100644
index 0000000000000000000000000000000000000000..c4c5e7f221b43de9929f27a6ce9b70317499b4ec
--- /dev/null
+++ b/m4/extern-inline.m4
@@ -0,0 +1,70 @@
+dnl 'extern inline' a la ISO C99.
+
+dnl Copyright 2012-2013 Free Software Foundation, Inc.
+dnl This file is free software; the Free Software Foundation
+dnl gives unlimited permission to copy and/or distribute it,
+dnl with or without modifications, as long as this notice is preserved.
+
+AC_DEFUN([gl_EXTERN_INLINE],
+[
+  AH_VERBATIM([extern_inline],
+[/* Please see the Gnulib manual for how to use these macros.
+
+   Suppress extern inline with HP-UX cc, as it appears to be broken; see
+   <http://lists.gnu.org/archive/html/bug-texinfo/2013-02/msg00030.html>.
+
+   Suppress extern inline with Sun C in standards-conformance mode, as it
+   mishandles inline functions that call each other.  E.g., for 'inline void f
+   (void) { } inline void g (void) { f (); }', c99 incorrectly complains
+   'reference to static identifier "f" in extern inline function'.
+   This bug was observed with Sun C 5.12 SunOS_i386 2011/11/16.
+
+   Suppress the use of extern inline on Apple's platforms, as Libc at least
+   through Libc-825.26 (2013-04-09) is incompatible with it; see, e.g.,
+   <http://lists.gnu.org/archive/html/bug-gnulib/2012-12/msg00023.html>.
+   Perhaps Apple will fix this some day.  */
+#if ((__GNUC__ \
+      ? defined __GNUC_STDC_INLINE__ && __GNUC_STDC_INLINE__ \
+      : (199901L <= __STDC_VERSION__ \
+         && !defined __HP_cc \
+         && !(defined __SUNPRO_C && __STDC__))) \
+     && !defined __APPLE__)
+# define _GL_INLINE inline
+# define _GL_EXTERN_INLINE extern inline
+#elif (2 < __GNUC__ + (7 <= __GNUC_MINOR__) && !defined __STRICT_ANSI__ \
+       && !defined __APPLE__)
+# if __GNUC_GNU_INLINE__
+   /* __gnu_inline__ suppresses a GCC 4.2 diagnostic.  */
+#  define _GL_INLINE extern inline __attribute__ ((__gnu_inline__))
+# else
+#  define _GL_INLINE extern inline
+# endif
+# define _GL_EXTERN_INLINE extern
+#else
+# define _GL_INLINE static _GL_UNUSED
+# define _GL_EXTERN_INLINE static _GL_UNUSED
+#endif
+
+#if 4 < __GNUC__ + (6 <= __GNUC_MINOR__)
+# if defined __GNUC_STDC_INLINE__ && __GNUC_STDC_INLINE__
+#  define _GL_INLINE_HEADER_CONST_PRAGMA
+# else
+#  define _GL_INLINE_HEADER_CONST_PRAGMA \
+     _Pragma ("GCC diagnostic ignored \"-Wsuggest-attribute=const\"")
+# endif
+  /* Suppress GCC's bogus "no previous prototype for 'FOO'"
+     and "no previous declaration for 'FOO'"  diagnostics,
+     when FOO is an inline function in the header; see
+     <http://gcc.gnu.org/bugzilla/show_bug.cgi?id=54113>.  */
+# define _GL_INLINE_HEADER_BEGIN \
+    _Pragma ("GCC diagnostic push") \
+    _Pragma ("GCC diagnostic ignored \"-Wmissing-prototypes\"") \
+    _Pragma ("GCC diagnostic ignored \"-Wmissing-declarations\"") \
+    _GL_INLINE_HEADER_CONST_PRAGMA
+# define _GL_INLINE_HEADER_END \
+    _Pragma ("GCC diagnostic pop")
+#else
+# define _GL_INLINE_HEADER_BEGIN
+# define _GL_INLINE_HEADER_END
+#endif])
+])
diff --git a/m4/fcntl-o.m4 b/m4/fcntl-o.m4
new file mode 100644
index 0000000000000000000000000000000000000000..43c93124ed5874a66282ed01b365a4fcfb9c1632
--- /dev/null
+++ b/m4/fcntl-o.m4
@@ -0,0 +1,134 @@
+# fcntl-o.m4 serial 4
+dnl Copyright (C) 2006, 2009-2014 Free Software Foundation, Inc.
+dnl This file is free software; the Free Software Foundation
+dnl gives unlimited permission to copy and/or distribute it,
+dnl with or without modifications, as long as this notice is preserved.
+
+dnl Written by Paul Eggert.
+
+# Test whether the flags O_NOATIME and O_NOFOLLOW actually work.
+# Define HAVE_WORKING_O_NOATIME to 1 if O_NOATIME works, or to 0 otherwise.
+# Define HAVE_WORKING_O_NOFOLLOW to 1 if O_NOFOLLOW works, or to 0 otherwise.
+AC_DEFUN([gl_FCNTL_O_FLAGS],
+[
+  dnl Persuade glibc <fcntl.h> to define O_NOATIME and O_NOFOLLOW.
+  dnl AC_USE_SYSTEM_EXTENSIONS was introduced in autoconf 2.60 and obsoletes
+  dnl AC_GNU_SOURCE.
+  m4_ifdef([AC_USE_SYSTEM_EXTENSIONS],
+    [AC_REQUIRE([AC_USE_SYSTEM_EXTENSIONS])],
+    [AC_REQUIRE([AC_GNU_SOURCE])])
+
+  AC_CHECK_HEADERS_ONCE([unistd.h])
+  AC_CHECK_FUNCS_ONCE([symlink])
+  AC_CACHE_CHECK([for working fcntl.h], [gl_cv_header_working_fcntl_h],
+    [AC_RUN_IFELSE(
+       [AC_LANG_PROGRAM(
+          [[#include <sys/types.h>
+           #include <sys/stat.h>
+           #if HAVE_UNISTD_H
+           # include <unistd.h>
+           #else /* on Windows with MSVC */
+           # include <io.h>
+           # include <stdlib.h>
+           # defined sleep(n) _sleep ((n) * 1000)
+           #endif
+           #include <fcntl.h>
+           #ifndef O_NOATIME
+            #define O_NOATIME 0
+           #endif
+           #ifndef O_NOFOLLOW
+            #define O_NOFOLLOW 0
+           #endif
+           static int const constants[] =
+            {
+              O_CREAT, O_EXCL, O_NOCTTY, O_TRUNC, O_APPEND,
+              O_NONBLOCK, O_SYNC, O_ACCMODE, O_RDONLY, O_RDWR, O_WRONLY
+            };
+          ]],
+          [[
+            int result = !constants;
+            #if HAVE_SYMLINK
+            {
+              static char const sym[] = "conftest.sym";
+              if (symlink ("/dev/null", sym) != 0)
+                result |= 2;
+              else
+                {
+                  int fd = open (sym, O_WRONLY | O_NOFOLLOW | O_CREAT, 0);
+                  if (fd >= 0)
+                    {
+                      close (fd);
+                      result |= 4;
+                    }
+                }
+              if (unlink (sym) != 0 || symlink (".", sym) != 0)
+                result |= 2;
+              else
+                {
+                  int fd = open (sym, O_RDONLY | O_NOFOLLOW);
+                  if (fd >= 0)
+                    {
+                      close (fd);
+                      result |= 4;
+                    }
+                }
+              unlink (sym);
+            }
+            #endif
+            {
+              static char const file[] = "confdefs.h";
+              int fd = open (file, O_RDONLY | O_NOATIME);
+              if (fd < 0)
+                result |= 8;
+              else
+                {
+                  struct stat st0;
+                  if (fstat (fd, &st0) != 0)
+                    result |= 16;
+                  else
+                    {
+                      char c;
+                      sleep (1);
+                      if (read (fd, &c, 1) != 1)
+                        result |= 24;
+                      else
+                        {
+                          if (close (fd) != 0)
+                            result |= 32;
+                          else
+                            {
+                              struct stat st1;
+                              if (stat (file, &st1) != 0)
+                                result |= 40;
+                              else
+                                if (st0.st_atime != st1.st_atime)
+                                  result |= 64;
+                            }
+                        }
+                    }
+                }
+            }
+            return result;]])],
+       [gl_cv_header_working_fcntl_h=yes],
+       [case $? in #(
+        4) gl_cv_header_working_fcntl_h='no (bad O_NOFOLLOW)';; #(
+        64) gl_cv_header_working_fcntl_h='no (bad O_NOATIME)';; #(
+        68) gl_cv_header_working_fcntl_h='no (bad O_NOATIME, O_NOFOLLOW)';; #(
+         *) gl_cv_header_working_fcntl_h='no';;
+        esac],
+       [gl_cv_header_working_fcntl_h=cross-compiling])])
+
+  case $gl_cv_header_working_fcntl_h in #(
+  *O_NOATIME* | no | cross-compiling) ac_val=0;; #(
+  *) ac_val=1;;
+  esac
+  AC_DEFINE_UNQUOTED([HAVE_WORKING_O_NOATIME], [$ac_val],
+    [Define to 1 if O_NOATIME works.])
+
+  case $gl_cv_header_working_fcntl_h in #(
+  *O_NOFOLLOW* | no | cross-compiling) ac_val=0;; #(
+  *) ac_val=1;;
+  esac
+  AC_DEFINE_UNQUOTED([HAVE_WORKING_O_NOFOLLOW], [$ac_val],
+    [Define to 1 if O_NOFOLLOW works.])
+])
diff --git a/m4/perl.m4 b/m4/perl.m4
new file mode 100644
index 0000000000000000000000000000000000000000..6f855c7a6ff5c1305b61ed9514a4bc89b8c1ea56
--- /dev/null
+++ b/m4/perl.m4
@@ -0,0 +1,48 @@
+# serial 9
+
+dnl From Jim Meyering.
+dnl Find a new-enough version of Perl.
+
+# Copyright (C) 1998-2001, 2003-2004, 2007, 2009-2018 Free Software Foundation,
+# Inc.
+#
+# This file 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.
+
+# GNUnet e.V. comment of origin: gnulib
+
+AC_DEFUN([gl_PERL],
+[
+  dnl FIXME: don't hard-code 5.005
+  AC_MSG_CHECKING([for perl5.005 or newer])
+  if test "${PERL+set}" = set; then
+    # 'PERL' is set in the user's environment.
+    candidate_perl_names="$PERL"
+    perl_specified=yes
+  else
+    candidate_perl_names='perl perl5'
+    perl_specified=no
+  fi
+
+  found=no
+  AC_SUBST([PERL])
+  PERL="$am_missing_run perl"
+  for perl in $candidate_perl_names; do
+    # Run test in a subshell; some versions of sh will print an error if
+    # an executable is not found, even if stderr is redirected.
+    if ( $perl -e 'require 5.005; use File::Compare' ) > /dev/null 2>&1; then
+      PERL=$perl
+      found=yes
+      break
+    fi
+  done
+
+  AC_MSG_RESULT([$found])
+  test $found = no && AC_MSG_WARN([
+WARNING: You don't seem to have perl5.005 or newer installed, or you lack
+         a usable version of the Perl File::Compare module.  As a result,
+         you may be unable to run a few tests or to regenerate certain
+         files if you modify the sources from which they are derived.
+] )
+])
diff --git a/m4/threadlib.m4 b/m4/threadlib.m4
new file mode 100644
index 0000000000000000000000000000000000000000..dc9a3d8e8442cac5529422d9c8ef3fe9ee52c415
--- /dev/null
+++ b/m4/threadlib.m4
@@ -0,0 +1,389 @@
+# threadlib.m4 serial 11 (gettext-0.18.2)
+dnl Copyright (C) 2005-2014 Free Software Foundation, Inc.
+dnl This file is free software; the Free Software Foundation
+dnl gives unlimited permission to copy and/or distribute it,
+dnl with or without modifications, as long as this notice is preserved.
+
+dnl From Bruno Haible.
+
+dnl gl_THREADLIB
+dnl ------------
+dnl Tests for a multithreading library to be used.
+dnl If the configure.ac contains a definition of the gl_THREADLIB_DEFAULT_NO
+dnl (it must be placed before the invocation of gl_THREADLIB_EARLY!), then the
+dnl default is 'no', otherwise it is system dependent. In both cases, the user
+dnl can change the choice through the options --enable-threads=choice or
+dnl --disable-threads.
+dnl Defines at most one of the macros USE_POSIX_THREADS, USE_SOLARIS_THREADS,
+dnl USE_PTH_THREADS, USE_WINDOWS_THREADS
+dnl Sets the variables LIBTHREAD and LTLIBTHREAD to the linker options for use
+dnl in a Makefile (LIBTHREAD for use without libtool, LTLIBTHREAD for use with
+dnl libtool).
+dnl Sets the variables LIBMULTITHREAD and LTLIBMULTITHREAD similarly, for
+dnl programs that really need multithread functionality. The difference
+dnl between LIBTHREAD and LIBMULTITHREAD is that on platforms supporting weak
+dnl symbols, typically LIBTHREAD is empty whereas LIBMULTITHREAD is not.
+dnl Adds to CPPFLAGS the flag -D_REENTRANT or -D_THREAD_SAFE if needed for
+dnl multithread-safe programs.
+
+AC_DEFUN([gl_THREADLIB_EARLY],
+[
+  AC_REQUIRE([gl_THREADLIB_EARLY_BODY])
+])
+
+dnl The guts of gl_THREADLIB_EARLY. Needs to be expanded only once.
+
+AC_DEFUN([gl_THREADLIB_EARLY_BODY],
+[
+  dnl Ordering constraints: This macro modifies CPPFLAGS in a way that
+  dnl influences the result of the autoconf tests that test for *_unlocked
+  dnl declarations, on AIX 5 at least. Therefore it must come early.
+  AC_BEFORE([$0], [gl_FUNC_GLIBC_UNLOCKED_IO])dnl
+  AC_BEFORE([$0], [gl_ARGP])dnl
+
+  AC_REQUIRE([AC_CANONICAL_HOST])
+  dnl _GNU_SOURCE is needed for pthread_rwlock_t on glibc systems.
+  dnl AC_USE_SYSTEM_EXTENSIONS was introduced in autoconf 2.60 and obsoletes
+  dnl AC_GNU_SOURCE.
+  m4_ifdef([AC_USE_SYSTEM_EXTENSIONS],
+    [AC_REQUIRE([AC_USE_SYSTEM_EXTENSIONS])],
+    [AC_REQUIRE([AC_GNU_SOURCE])])
+  dnl Check for multithreading.
+  m4_ifdef([gl_THREADLIB_DEFAULT_NO],
+    [m4_divert_text([DEFAULTS], [gl_use_threads_default=no])],
+    [m4_divert_text([DEFAULTS], [gl_use_threads_default=])])
+  AC_ARG_ENABLE([threads],
+AC_HELP_STRING([--enable-threads={posix|solaris|pth|windows}], [specify multithreading API])m4_ifdef([gl_THREADLIB_DEFAULT_NO], [], [
+AC_HELP_STRING([--disable-threads], [build without multithread safety])]),
+    [gl_use_threads=$enableval],
+    [if test -n "$gl_use_threads_default"; then
+       gl_use_threads="$gl_use_threads_default"
+     else
+changequote(,)dnl
+       case "$host_os" in
+         dnl Disable multithreading by default on OSF/1, because it interferes
+         dnl with fork()/exec(): When msgexec is linked with -lpthread, its
+         dnl child process gets an endless segmentation fault inside execvp().
+         dnl Disable multithreading by default on Cygwin 1.5.x, because it has
+         dnl bugs that lead to endless loops or crashes. See
+         dnl <http://cygwin.com/ml/cygwin/2009-08/msg00283.html>.
+         osf*) gl_use_threads=no ;;
+         cygwin*)
+               case `uname -r` in
+                 1.[0-5].*) gl_use_threads=no ;;
+                 *)         gl_use_threads=yes ;;
+               esac
+               ;;
+         *)    gl_use_threads=yes ;;
+       esac
+changequote([,])dnl
+     fi
+    ])
+  if test "$gl_use_threads" = yes || test "$gl_use_threads" = posix; then
+    # For using <pthread.h>:
+    case "$host_os" in
+      osf*)
+        # On OSF/1, the compiler needs the flag -D_REENTRANT so that it
+        # groks <pthread.h>. cc also understands the flag -pthread, but
+        # we don't use it because 1. gcc-2.95 doesn't understand -pthread,
+        # 2. putting a flag into CPPFLAGS that has an effect on the linker
+        # causes the AC_LINK_IFELSE test below to succeed unexpectedly,
+        # leading to wrong values of LIBTHREAD and LTLIBTHREAD.
+        CPPFLAGS="$CPPFLAGS -D_REENTRANT"
+        ;;
+    esac
+    # Some systems optimize for single-threaded programs by default, and
+    # need special flags to disable these optimizations. For example, the
+    # definition of 'errno' in <errno.h>.
+    case "$host_os" in
+      aix* | freebsd*) CPPFLAGS="$CPPFLAGS -D_THREAD_SAFE" ;;
+      solaris*) CPPFLAGS="$CPPFLAGS -D_REENTRANT" ;;
+    esac
+  fi
+])
+
+dnl The guts of gl_THREADLIB. Needs to be expanded only once.
+
+AC_DEFUN([gl_THREADLIB_BODY],
+[
+  AC_REQUIRE([gl_THREADLIB_EARLY_BODY])
+  gl_threads_api=none
+  LIBTHREAD=
+  LTLIBTHREAD=
+  LIBMULTITHREAD=
+  LTLIBMULTITHREAD=
+  if test "$gl_use_threads" != no; then
+    dnl Check whether the compiler and linker support weak declarations.
+    AC_CACHE_CHECK([whether imported symbols can be declared weak],
+      [gl_cv_have_weak],
+      [gl_cv_have_weak=no
+       dnl First, test whether the compiler accepts it syntactically.
+       AC_LINK_IFELSE(
+         [AC_LANG_PROGRAM(
+            [[extern void xyzzy ();
+#pragma weak xyzzy]],
+            [[xyzzy();]])],
+         [gl_cv_have_weak=maybe])
+       if test $gl_cv_have_weak = maybe; then
+         dnl Second, test whether it actually works. On Cygwin 1.7.2, with
+         dnl gcc 4.3, symbols declared weak always evaluate to the address 0.
+         AC_RUN_IFELSE(
+           [AC_LANG_SOURCE([[
+#include <stdio.h>
+#pragma weak fputs
+int main ()
+{
+  return (fputs == NULL);
+}]])],
+           [gl_cv_have_weak=yes],
+           [gl_cv_have_weak=no],
+           [dnl When cross-compiling, assume that only ELF platforms support
+            dnl weak symbols.
+            AC_EGREP_CPP([Extensible Linking Format],
+              [#ifdef __ELF__
+               Extensible Linking Format
+               #endif
+              ],
+              [gl_cv_have_weak="guessing yes"],
+              [gl_cv_have_weak="guessing no"])
+           ])
+       fi
+      ])
+    if test "$gl_use_threads" = yes || test "$gl_use_threads" = posix; then
+      # On OSF/1, the compiler needs the flag -pthread or -D_REENTRANT so that
+      # it groks <pthread.h>. It's added above, in gl_THREADLIB_EARLY_BODY.
+      AC_CHECK_HEADER([pthread.h],
+        [gl_have_pthread_h=yes], [gl_have_pthread_h=no])
+      if test "$gl_have_pthread_h" = yes; then
+        # Other possible tests:
+        #   -lpthreads (FSU threads, PCthreads)
+        #   -lgthreads
+        gl_have_pthread=
+        # Test whether both pthread_mutex_lock and pthread_mutexattr_init exist
+        # in libc. IRIX 6.5 has the first one in both libc and libpthread, but
+        # the second one only in libpthread, and lock.c needs it.
+        #
+        # If -pthread works, prefer it to -lpthread, since Ubuntu 14.04
+        # needs -pthread for some reason.  See:
+        # http://lists.gnu.org/archive/html/bug-gnulib/2014-09/msg00023.html
+        save_LIBS=$LIBS
+        for gl_pthread in '' '-pthread'; do
+          LIBS="$LIBS $gl_pthread"
+          AC_LINK_IFELSE(
+            [AC_LANG_PROGRAM(
+               [[#include <pthread.h>
+                 pthread_mutex_t m;
+                 pthread_mutexattr_t ma;
+               ]],
+               [[pthread_mutex_lock (&m);
+                 pthread_mutexattr_init (&ma);]])],
+            [gl_have_pthread=yes
+             LIBTHREAD=$gl_pthread LTLIBTHREAD=$gl_pthread
+             LIBMULTITHREAD=$gl_pthread LTLIBMULTITHREAD=$gl_pthread])
+          LIBS=$save_LIBS
+          test -n "$gl_have_pthread" && break
+        done
+
+        # Test for libpthread by looking for pthread_kill. (Not pthread_self,
+        # since it is defined as a macro on OSF/1.)
+        if test -n "$gl_have_pthread" && test -z "$LIBTHREAD"; then
+          # The program links fine without libpthread. But it may actually
+          # need to link with libpthread in order to create multiple threads.
+          AC_CHECK_LIB([pthread], [pthread_kill],
+            [LIBMULTITHREAD=-lpthread LTLIBMULTITHREAD=-lpthread
+             # On Solaris and HP-UX, most pthread functions exist also in libc.
+             # Therefore pthread_in_use() needs to actually try to create a
+             # thread: pthread_create from libc will fail, whereas
+             # pthread_create will actually create a thread.
+             case "$host_os" in
+               solaris* | hpux*)
+                 AC_DEFINE([PTHREAD_IN_USE_DETECTION_HARD], [1],
+                   [Define if the pthread_in_use() detection is hard.])
+             esac
+            ])
+        elif test -z "$gl_have_pthread"; then
+          # Some library is needed. Try libpthread and libc_r.
+          AC_CHECK_LIB([pthread], [pthread_kill],
+            [gl_have_pthread=yes
+             LIBTHREAD=-lpthread LTLIBTHREAD=-lpthread
+             LIBMULTITHREAD=-lpthread LTLIBMULTITHREAD=-lpthread])
+          if test -z "$gl_have_pthread"; then
+            # For FreeBSD 4.
+            AC_CHECK_LIB([c_r], [pthread_kill],
+              [gl_have_pthread=yes
+               LIBTHREAD=-lc_r LTLIBTHREAD=-lc_r
+               LIBMULTITHREAD=-lc_r LTLIBMULTITHREAD=-lc_r])
+          fi
+        fi
+        if test -n "$gl_have_pthread"; then
+          gl_threads_api=posix
+          AC_DEFINE([USE_POSIX_THREADS], [1],
+            [Define if the POSIX multithreading library can be used.])
+          if test -n "$LIBMULTITHREAD" || test -n "$LTLIBMULTITHREAD"; then
+            if case "$gl_cv_have_weak" in *yes) true;; *) false;; esac; then
+              AC_DEFINE([USE_POSIX_THREADS_WEAK], [1],
+                [Define if references to the POSIX multithreading library should be made weak.])
+              LIBTHREAD=
+              LTLIBTHREAD=
+            fi
+          fi
+        fi
+      fi
+    fi
+    if test -z "$gl_have_pthread"; then
+      if test "$gl_use_threads" = yes || test "$gl_use_threads" = solaris; then
+        gl_have_solaristhread=
+        gl_save_LIBS="$LIBS"
+        LIBS="$LIBS -lthread"
+        AC_LINK_IFELSE(
+          [AC_LANG_PROGRAM(
+             [[
+#include <thread.h>
+#include <synch.h>
+             ]],
+             [[thr_self();]])],
+          [gl_have_solaristhread=yes])
+        LIBS="$gl_save_LIBS"
+        if test -n "$gl_have_solaristhread"; then
+          gl_threads_api=solaris
+          LIBTHREAD=-lthread
+          LTLIBTHREAD=-lthread
+          LIBMULTITHREAD="$LIBTHREAD"
+          LTLIBMULTITHREAD="$LTLIBTHREAD"
+          AC_DEFINE([USE_SOLARIS_THREADS], [1],
+            [Define if the old Solaris multithreading library can be used.])
+          if case "$gl_cv_have_weak" in *yes) true;; *) false;; esac; then
+            AC_DEFINE([USE_SOLARIS_THREADS_WEAK], [1],
+              [Define if references to the old Solaris multithreading library should be made weak.])
+            LIBTHREAD=
+            LTLIBTHREAD=
+          fi
+        fi
+      fi
+    fi
+    if test "$gl_use_threads" = pth; then
+      gl_save_CPPFLAGS="$CPPFLAGS"
+      AC_LIB_LINKFLAGS([pth])
+      gl_have_pth=
+      gl_save_LIBS="$LIBS"
+      LIBS="$LIBS $LIBPTH"
+      AC_LINK_IFELSE(
+        [AC_LANG_PROGRAM([[#include <pth.h>]], [[pth_self();]])],
+        [gl_have_pth=yes])
+      LIBS="$gl_save_LIBS"
+      if test -n "$gl_have_pth"; then
+        gl_threads_api=pth
+        LIBTHREAD="$LIBPTH"
+        LTLIBTHREAD="$LTLIBPTH"
+        LIBMULTITHREAD="$LIBTHREAD"
+        LTLIBMULTITHREAD="$LTLIBTHREAD"
+        AC_DEFINE([USE_PTH_THREADS], [1],
+          [Define if the GNU Pth multithreading library can be used.])
+        if test -n "$LIBMULTITHREAD" || test -n "$LTLIBMULTITHREAD"; then
+          if case "$gl_cv_have_weak" in *yes) true;; *) false;; esac; then
+            AC_DEFINE([USE_PTH_THREADS_WEAK], [1],
+              [Define if references to the GNU Pth multithreading library should be made weak.])
+            LIBTHREAD=
+            LTLIBTHREAD=
+          fi
+        fi
+      else
+        CPPFLAGS="$gl_save_CPPFLAGS"
+      fi
+    fi
+    if test -z "$gl_have_pthread"; then
+      case "$gl_use_threads" in
+        yes | windows | win32) # The 'win32' is for backward compatibility.
+          if { case "$host_os" in
+                 mingw*) true;;
+                 *) false;;
+               esac
+             }; then
+            gl_threads_api=windows
+            AC_DEFINE([USE_WINDOWS_THREADS], [1],
+              [Define if the native Windows multithreading API can be used.])
+          fi
+          ;;
+      esac
+    fi
+  fi
+  AC_MSG_CHECKING([for multithread API to use])
+  AC_MSG_RESULT([$gl_threads_api])
+  AC_SUBST([LIBTHREAD])
+  AC_SUBST([LTLIBTHREAD])
+  AC_SUBST([LIBMULTITHREAD])
+  AC_SUBST([LTLIBMULTITHREAD])
+])
+
+AC_DEFUN([gl_THREADLIB],
+[
+  AC_REQUIRE([gl_THREADLIB_EARLY])
+  AC_REQUIRE([gl_THREADLIB_BODY])
+])
+
+
+dnl gl_DISABLE_THREADS
+dnl ------------------
+dnl Sets the gl_THREADLIB default so that threads are not used by default.
+dnl The user can still override it at installation time, by using the
+dnl configure option '--enable-threads'.
+
+AC_DEFUN([gl_DISABLE_THREADS], [
+  m4_divert_text([INIT_PREPARE], [gl_use_threads_default=no])
+])
+
+
+dnl Survey of platforms:
+dnl
+dnl Platform           Available  Compiler    Supports   test-lock
+dnl                    flavours   option      weak       result
+dnl ---------------    ---------  ---------   --------   ---------
+dnl Linux 2.4/glibc    posix      -lpthread       Y      OK
+dnl
+dnl GNU Hurd/glibc     posix
+dnl
+dnl Ubuntu 14.04       posix      -pthread        Y      OK
+dnl
+dnl FreeBSD 5.3        posix      -lc_r           Y
+dnl                    posix      -lkse ?         Y
+dnl                    posix      -lpthread ?     Y
+dnl                    posix      -lthr           Y
+dnl
+dnl FreeBSD 5.2        posix      -lc_r           Y
+dnl                    posix      -lkse           Y
+dnl                    posix      -lthr           Y
+dnl
+dnl FreeBSD 4.0,4.10   posix      -lc_r           Y      OK
+dnl
+dnl NetBSD 1.6         --
+dnl
+dnl OpenBSD 3.4        posix      -lpthread       Y      OK
+dnl
+dnl Mac OS X 10.[123]  posix      -lpthread       Y      OK
+dnl
+dnl Solaris 7,8,9      posix      -lpthread       Y      Sol 7,8: 0.0; Sol 9: OK
+dnl                    solaris    -lthread        Y      Sol 7,8: 0.0; Sol 9: OK
+dnl
+dnl HP-UX 11           posix      -lpthread       N (cc) OK
+dnl                                               Y (gcc)
+dnl
+dnl IRIX 6.5           posix      -lpthread       Y      0.5
+dnl
+dnl AIX 4.3,5.1        posix      -lpthread       N      AIX 4: 0.5; AIX 5: OK
+dnl
+dnl OSF/1 4.0,5.1      posix      -pthread (cc)   N      OK
+dnl                               -lpthread (gcc) Y
+dnl
+dnl Cygwin             posix      -lpthread       Y      OK
+dnl
+dnl Any of the above   pth        -lpth                  0.0
+dnl
+dnl Mingw              windows                    N      OK
+dnl
+dnl BeOS 5             --
+dnl
+dnl The test-lock result shows what happens if in test-lock.c EXPLICIT_YIELD is
+dnl turned off:
+dnl   OK if all three tests terminate OK,
+dnl   0.5 if the first test terminates OK but the second one loops endlessly,
+dnl   0.0 if the first test already loops endlessly.
diff --git a/pkgconfig/gnunet_config.h.in b/pkgconfig/gnunet_config.h.in
new file mode 100644
index 0000000000000000000000000000000000000000..9ffb6a2e25680ea602dbd14303d8b3d44a0c0780
--- /dev/null
+++ b/pkgconfig/gnunet_config.h.in
@@ -0,0 +1,767 @@
+/* gnunet_config.h.in.  Generated from configure.ac by autoheader.  */
+
+#define _GNU_SOURCE  1
+
+/* Define to 1 if the `closedir' function returns void instead of `int'. */
+#undef CLOSEDIR_VOID
+
+/* This is a Cygwin system */
+#undef CYGWIN
+
+/* This is an Apple Darwin system */
+#undef DARWIN
+
+/* Define to 1 if translation of program messages to the user's native
+   language is requested. */
+#undef ENABLE_NLS
+
+/* Build a Mac OS X Framework */
+#undef FRAMEWORK_BUILD
+
+/* This is a FreeBSD system */
+#undef FREEBSD
+
+/* This should be the default choice for the name of the first network
+   interface */
+#undef GNUNET_DEFAULT_INTERFACE
+
+/* Define to 1 if you have the `argz_add' function. */
+#undef HAVE_ARGZ_ADD
+
+/* Define to 1 if you have the `argz_append' function. */
+#undef HAVE_ARGZ_APPEND
+
+/* Define to 1 if you have the `argz_count' function. */
+#undef HAVE_ARGZ_COUNT
+
+/* Define to 1 if you have the `argz_create_sep' function. */
+#undef HAVE_ARGZ_CREATE_SEP
+
+/* Define to 1 if you have the <argz.h> header file. */
+#undef HAVE_ARGZ_H
+
+/* Define to 1 if you have the `argz_insert' function. */
+#undef HAVE_ARGZ_INSERT
+
+/* Define to 1 if you have the `argz_next' function. */
+#undef HAVE_ARGZ_NEXT
+
+/* Define to 1 if you have the `argz_stringify' function. */
+#undef HAVE_ARGZ_STRINGIFY
+
+/* Define to 1 if you have the <arpa/inet.h> header file. */
+#undef HAVE_ARPA_INET_H
+
+/* Define to 1 if you have the `atoll' function. */
+#undef HAVE_ATOLL
+
+/* Define to 1 if you have the MacOS X function CFLocaleCopyCurrent in the
+   CoreFoundation framework. */
+#undef HAVE_CFLOCALECOPYCURRENT
+
+/* Define to 1 if you have the MacOS X function CFPreferencesCopyAppValue in
+   the CoreFoundation framework. */
+#undef HAVE_CFPREFERENCESCOPYAPPVALUE
+
+/* Define to 1 if your system has a working `chown' function. */
+#undef HAVE_CHOWN
+
+/* Define to 1 if you have the `clock_gettime' function. */
+#undef HAVE_CLOCK_GETTIME
+
+/* Define to 1 if you have the `closedir' function. */
+#undef HAVE_CLOSEDIR
+
+/* Define to 1 if you have the <ctype.h> header file. */
+#undef HAVE_CTYPE_H
+
+/* Define if the GNU dcgettext() function is already present or preinstalled.
+   */
+#undef HAVE_DCGETTEXT
+
+/* Define to 1 if you have the declaration of `cygwin_conv_path', and to 0 if
+   you don't. */
+#undef HAVE_DECL_CYGWIN_CONV_PATH
+
+/* Define to 1 if you have the declaration of `gcry_mpi_lshift', and to 0 if
+   you don't. */
+#undef HAVE_DECL_GCRY_MPI_LSHIFT
+
+/* Define to 1 if you have the <dirent.h> header file, and it defines `DIR'.
+   */
+#undef HAVE_DIRENT_H
+
+/* Define if you have the GNU dld library. */
+#undef HAVE_DLD
+
+/* Define to 1 if you have the <dld.h> header file. */
+#undef HAVE_DLD_H
+
+/* Define to 1 if you have the `dlerror' function. */
+#undef HAVE_DLERROR
+
+/* Define to 1 if you have the <dlfcn.h> header file. */
+#undef HAVE_DLFCN_H
+
+/* Define to 1 if you have the <dl.h> header file. */
+#undef HAVE_DL_H
+
+/* Define to 1 if you don't have `vprintf' but do have `_doprnt.' */
+#undef HAVE_DOPRNT
+
+/* Define to 1 if you have the `dup2' function. */
+#undef HAVE_DUP2
+
+/* Define if you have the _dyld_func_lookup function. */
+#undef HAVE_DYLD
+
+/* Define to 1 if you have the <errno.h> header file. */
+#undef HAVE_ERRNO_H
+
+/* Define to 1 if the system has the type `error_t'. */
+#undef HAVE_ERROR_T
+
+/* We have libesmtp */
+#undef HAVE_ESMTP
+
+/* Define to 1 if you have the <extractor.h> header file. */
+#undef HAVE_EXTRACTOR_H
+
+/* Define to 1 if you have the <fcntl.h> header file. */
+#undef HAVE_FCNTL_H
+
+/* Define to 1 if you have the `fdatasync' function. */
+#undef HAVE_FDATASYNC
+
+/* Define to 1 if you have the `floor' function. */
+#undef HAVE_FLOOR
+
+/* Define to 1 if you have the `fork' function. */
+#undef HAVE_FORK
+
+/* Define to 1 if you have the `freeifaddrs' function. */
+#undef HAVE_FREEIFADDRS
+
+/* Define to 1 if fseeko (and presumably ftello) exists and is declared. */
+#undef HAVE_FSEEKO
+
+/* Define to 1 if you have the `ftruncate' function. */
+#undef HAVE_FTRUNCATE
+
+/* Define to 1 if you have the `getaddrinfo' function. */
+#undef HAVE_GETADDRINFO
+
+/* Define to 1 if you have the `getcwd' function. */
+#undef HAVE_GETCWD
+
+/* Define to 1 if you have the `gethostbyaddr' function. */
+#undef HAVE_GETHOSTBYADDR
+
+/* Define to 1 if you have the `gethostbyname' function. */
+#undef HAVE_GETHOSTBYNAME
+
+/* Define to 1 if you have the `gethostbyname2' function. */
+#undef HAVE_GETHOSTBYNAME2
+
+/* Define to 1 if you have the `gethostname' function. */
+#undef HAVE_GETHOSTNAME
+
+/* Define to 1 if you have the `getifaddrs' function. */
+#undef HAVE_GETIFADDRS
+
+/* getloadavg supported */
+#undef HAVE_GETLOADAVG
+
+/* Define to 1 if you have the `getnameinfo' function. */
+#undef HAVE_GETNAMEINFO
+
+/* Define to 1 if you have the `getrusage' function. */
+#undef HAVE_GETRUSAGE
+
+/* Define if the GNU gettext() function is already present or preinstalled. */
+#undef HAVE_GETTEXT
+
+/* Define to 1 if you have the `gettimeofday' function. */
+#undef HAVE_GETTIMEOFDAY
+
+/* Define to 1 if you have the `gmtime' function. */
+#undef HAVE_GMTIME
+
+/* Define to 1 if you have the `gmtime_r' function. */
+#undef HAVE_GMTIME_R
+
+/* Define if you have the iconv() function. */
+#undef HAVE_ICONV
+
+/* Define to 1 if you have the <ifaddrs.h> header file. */
+#undef HAVE_IFADDRS_H
+
+/* Define to 1 if you have the `inet_ntoa' function. */
+#undef HAVE_INET_NTOA
+
+/* Define to 1 if you have the `initgroups' function. */
+#undef HAVE_INITGROUPS
+
+/* Define to 1 if you have the <inttypes.h> header file. */
+#undef HAVE_INTTYPES_H
+
+/* Define to 1 if you have the <kstat.h> header file. */
+#undef HAVE_KSTAT_H
+
+/* Define to 1 if you have the <kvm.h> header file. */
+#undef HAVE_KVM_H
+
+/* Define to 1 if you have the <langinfo.h> header file. */
+#undef HAVE_LANGINFO_H
+
+/* Define to 1 if you have a functional curl library. */
+#undef HAVE_LIBCURL
+
+/* Define if you have the libdl library or equivalent. */
+#undef HAVE_LIBDL
+
+/* Define if libdlloader will be built on this platform */
+#undef HAVE_LIBDLLOADER
+
+/* Define to 1 if you have the <libesmtp.h> header file. */
+#undef HAVE_LIBESMTP_H
+
+/* Define to 1 if you have the `intl' library (-lintl). */
+#undef HAVE_LIBINTL
+
+/* Define to 1 if you have the <libintl.h> header file. */
+#undef HAVE_LIBINTL_H
+
+/* Define to 1 if you have the `kstat' library (-lkstat). */
+#undef HAVE_LIBKSTAT
+
+/* Define to 1 if you have the `kvm' library (-lkvm). */
+#undef HAVE_LIBKVM
+
+/* Define to 1 if you have the `m' library (-lm). */
+#undef HAVE_LIBM
+
+/* Define to 1 if you have the `resolv' library (-lresolv). */
+#undef HAVE_LIBRESOLV
+
+/* Define to 1 if you have the `rt' library (-lrt). */
+#undef HAVE_LIBRT
+
+/* Define to 1 if you have the `socket' library (-lsocket). */
+#undef HAVE_LIBSOCKET
+
+/* Define to 1 if you have the `z' library (-lz). */
+#undef HAVE_LIBZ
+
+/* Define to 1 if you have the <limits.h> header file. */
+#undef HAVE_LIMITS_H
+
+/* Define to 1 if you have the <locale.h> header file. */
+#undef HAVE_LOCALE_H
+
+/* Define to 1 if you have the `localtime_r' function. */
+#undef HAVE_LOCALTIME_R
+
+/* Define this if a modern libltdl is already installed */
+#undef HAVE_LTDL
+
+/* Define to 1 if you have the <mach/mach.h> header file. */
+#undef HAVE_MACH_MACH_H
+
+/* Define to 1 if you have the <mach-o/dyld.h> header file. */
+#undef HAVE_MACH_O_DYLD_H
+
+/* Compile malicious code */
+#undef HAVE_MALICIOUS
+
+/* Define to 1 if you have the <math.h> header file. */
+#undef HAVE_MATH_H
+
+/* Define to 1 if you have the `memmove' function. */
+#undef HAVE_MEMMOVE
+
+/* Define to 1 if you have the <memory.h> header file. */
+#undef HAVE_MEMORY_H
+
+/* Define to 1 if you have the `memset' function. */
+#undef HAVE_MEMSET
+
+/* We have libmicrohttpd */
+#undef HAVE_MHD
+
+/* Define to 1 if you have the <microhttpd.h> header file. */
+#undef HAVE_MICROHTTPD_H
+
+/* Define to 1 if you have the `mkdir' function. */
+#undef HAVE_MKDIR
+
+/* Define to 1 if you have the `mkfifo' function. */
+#undef HAVE_MKFIFO
+
+/* Define to 1 if you have the `mktime' function. */
+#undef HAVE_MKTIME
+
+/* Define to 1 if you have the `mmap' function. */
+#undef HAVE_MMAP
+
+/* Define to 1 if you have the `mremap' function. */
+#undef HAVE_MREMAP
+
+/* Define to 1 if you have the <mysql/mysql.h> header file. */
+#undef HAVE_MYSQL_MYSQL_H
+
+/* Define to 1 if you have the <ndir.h> header file, and it defines `DIR'. */
+#undef HAVE_NDIR_H
+
+/* Define to 1 if you have the <netdb.h> header file. */
+#undef HAVE_NETDB_H
+
+/* Define to 1 if you have the <netinet/in.h> header file. */
+#undef HAVE_NETINET_IN_H
+
+/* Define to 1 if you have the <netinet/in_systm.h> header file. */
+#undef HAVE_NETINET_IN_SYSTM_H
+
+/* Define to 1 if you have the `nl_langinfo' function. */
+#undef HAVE_NL_LANGINFO
+
+/* Define to 1 if the system has the type `off_t'. */
+#undef HAVE_OFF_T
+
+/* Define to 1 if you have the `opendir' function. */
+#undef HAVE_OPENDIR
+
+/* We have openssl */
+#undef HAVE_OPENSSL
+
+/* Define to 1 if you have the <openssl/ssl.h> header file. */
+#undef HAVE_OPENSSL_SSL_H
+
+/* Define to 1 if you have the <pcap.h> header file. */
+#undef HAVE_PCAP_H
+
+/* Define to 1 if you have the <postgresql/libpq-fe.h> header file. */
+#undef HAVE_POSTGRESQL_LIBPQ_FE_H
+
+/* Define if libtool can extract symbol lists from object files. */
+#undef HAVE_PRELOADED_SYMBOLS
+
+/* Define to 1 if you have the `putenv' function. */
+#undef HAVE_PUTENV
+
+/* Define to 1 if you have the `rand' function. */
+#undef HAVE_RAND
+
+/* Define to 1 if you have the `readdir' function. */
+#undef HAVE_READDIR
+
+/* Define to 1 if you have the `realpath' function. */
+#undef HAVE_REALPATH
+
+/* Define to 1 if you have the `rmdir' function. */
+#undef HAVE_RMDIR
+
+/* Define to 1 if you have the `sbrk' function. */
+#undef HAVE_SBRK
+
+/* Define to 1 if you have the `select' function. */
+#undef HAVE_SELECT
+
+/* Define to 1 if you have the `setlocale' function. */
+#undef HAVE_SETLOCALE
+
+/* Define to 1 if you have the `setrlimit' function. */
+#undef HAVE_SETRLIMIT
+
+/* Define if you have the shl_load function. */
+#undef HAVE_SHL_LOAD
+
+/* Define to 1 if you have the <signal.h> header file. */
+#undef HAVE_SIGNAL_H
+
+/* Define to 1 if the system has the type `sigset_t'. */
+#undef HAVE_SIGSET_T
+
+/* Define to 1 if the system has the type `size_t'. */
+#undef HAVE_SIZE_T
+
+/* Do we have sockaddr_in.sin_len? */
+#undef HAVE_SOCKADDR_IN_SIN_LEN
+
+/* Define to 1 if you have the `socket' function. */
+#undef HAVE_SOCKET
+
+/* Define to 1 if you have the <sockLib.h> header file. */
+#undef HAVE_SOCKLIB_H
+
+/* Define to 1 if you have the <sqlite3.h> header file. */
+#undef HAVE_SQLITE3_H
+
+/* Define to 1 if you have the `stat64' function. */
+#undef HAVE_STAT64
+
+/* Define to 1 if `stat' has the bug that it succeeds when given the
+   zero-length file name argument. */
+#undef HAVE_STAT_EMPTY_STRING_BUG
+
+/* Define to 1 if you have the <stdarg.h> header file. */
+#undef HAVE_STDARG_H
+
+/* Define to 1 if stdbool.h conforms to C99. */
+#undef HAVE_STDBOOL_H
+
+/* Define to 1 if you have the <stddef.h> header file. */
+#undef HAVE_STDDEF_H
+
+/* Define to 1 if you have the <stdint.h> header file. */
+#undef HAVE_STDINT_H
+
+/* Define to 1 if you have the <stdio.h> header file. */
+#undef HAVE_STDIO_H
+
+/* Define to 1 if you have the <stdlib.h> header file. */
+#undef HAVE_STDLIB_H
+
+/* Define to 1 if you have the `strcasecmp' function. */
+#undef HAVE_STRCASECMP
+
+/* Define to 1 if you have the `strchr' function. */
+#undef HAVE_STRCHR
+
+/* Define to 1 if you have the `strdup' function. */
+#undef HAVE_STRDUP
+
+/* Define to 1 if you have the `strerror' function. */
+#undef HAVE_STRERROR
+
+/* Define to 1 if you have the `strftime' function. */
+#undef HAVE_STRFTIME
+
+/* Define to 1 if you have the <strings.h> header file. */
+#undef HAVE_STRINGS_H
+
+/* Define to 1 if you have the <string.h> header file. */
+#undef HAVE_STRING_H
+
+/* Define to 1 if you have the `strlcat' function. */
+#undef HAVE_STRLCAT
+
+/* Define to 1 if you have the `strlcpy' function. */
+#undef HAVE_STRLCPY
+
+/* Define to 1 if you have the `strncasecmp' function. */
+#undef HAVE_STRNCASECMP
+
+/* Define to 1 if you have the `strndup' function. */
+#undef HAVE_STRNDUP
+
+/* Define to 1 if you have the `strrchr' function. */
+#undef HAVE_STRRCHR
+
+/* Define to 1 if you have the `strstr' function. */
+#undef HAVE_STRSTR
+
+/* Define to 1 if you have the `strtol' function. */
+#undef HAVE_STRTOL
+
+/* Define to 1 if you have the `sysconf' function. */
+#undef HAVE_SYSCONF
+
+/* Define to 1 if you have the <sys/dir.h> header file, and it defines `DIR'.
+   */
+#undef HAVE_SYS_DIR_H
+
+/* Define to 1 if you have the <sys/dl.h> header file. */
+#undef HAVE_SYS_DL_H
+
+/* Define to 1 if you have the <sys/file.h> header file. */
+#undef HAVE_SYS_FILE_H
+
+/* Define to 1 if you have the <sys/ioctl.h> header file. */
+#undef HAVE_SYS_IOCTL_H
+
+/* Define to 1 if you have the <sys/mman.h> header file. */
+#undef HAVE_SYS_MMAN_H
+
+/* Define to 1 if you have the <sys/mount.h> header file. */
+#undef HAVE_SYS_MOUNT_H
+
+/* Define to 1 if you have the <sys/msg.h> header file. */
+#undef HAVE_SYS_MSG_H
+
+/* Define to 1 if you have the <sys/ndir.h> header file, and it defines `DIR'.
+   */
+#undef HAVE_SYS_NDIR_H
+
+/* Define to 1 if you have the <sys/param.h> header file. */
+#undef HAVE_SYS_PARAM_H
+
+/* Define to 1 if you have the <sys/resource.h> header file. */
+#undef HAVE_SYS_RESOURCE_H
+
+/* Define to 1 if you have the <sys/select.h> header file. */
+#undef HAVE_SYS_SELECT_H
+
+/* Define to 1 if you have the <sys/socket.h> header file. */
+#undef HAVE_SYS_SOCKET_H
+
+/* Define to 1 if you have the <sys/statvfs.h> header file. */
+#undef HAVE_SYS_STATVFS_H
+
+/* Define to 1 if you have the <sys/stat.h> header file. */
+#undef HAVE_SYS_STAT_H
+
+/* Define to 1 if you have the <sys/sysinfo.h> header file. */
+#undef HAVE_SYS_SYSINFO_H
+
+/* Define to 1 if you have the <sys/timeb.h> header file. */
+#undef HAVE_SYS_TIMEB_H
+
+/* Define to 1 if you have the <sys/time.h> header file. */
+#undef HAVE_SYS_TIME_H
+
+/* Define to 1 if you have the <sys/types.h> header file. */
+#undef HAVE_SYS_TYPES_H
+
+/* Define to 1 if you have the <sys/vfs.h> header file. */
+#undef HAVE_SYS_VFS_H
+
+/* Define to 1 if you have <sys/wait.h> that is POSIX.1 compatible. */
+#undef HAVE_SYS_WAIT_H
+
+/* Define to 1 if you have the <terminos.h> header file. */
+#undef HAVE_TERMINOS_H
+
+/* We can access-64 bit values that are only 32-bit aligned */
+#undef HAVE_UNALIGNED_64_ACCESS
+
+/* Define to 1 if you have the `uname' function. */
+#undef HAVE_UNAME
+
+/* Define to 1 if you have the <unistd.h> header file. */
+#undef HAVE_UNISTD_H
+
+/* Define to 1 if you have the `vfork' function. */
+#undef HAVE_VFORK
+
+/* Define to 1 if you have the <vfork.h> header file. */
+#undef HAVE_VFORK_H
+
+/* Define to 1 if you have the `vprintf' function. */
+#undef HAVE_VPRINTF
+
+/* This value is set to 1 to indicate that the system argz facility works */
+#undef HAVE_WORKING_ARGZ
+
+/* Define to 1 if `fork' works. */
+#undef HAVE_WORKING_FORK
+
+/* Define to 1 if `vfork' works. */
+#undef HAVE_WORKING_VFORK
+
+/* Define to 1 if the system has the type `_Bool'. */
+#undef HAVE__BOOL
+
+/* Define as const if the declaration of iconv() needs const. */
+#undef ICONV_CONST
+
+/* Defined if libcurl supports AsynchDNS */
+#undef LIBCURL_FEATURE_ASYNCHDNS
+
+/* Defined if libcurl supports IDN */
+#undef LIBCURL_FEATURE_IDN
+
+/* Defined if libcurl supports IPv6 */
+#undef LIBCURL_FEATURE_IPV6
+
+/* Defined if libcurl supports KRB4 */
+#undef LIBCURL_FEATURE_KRB4
+
+/* Defined if libcurl supports libz */
+#undef LIBCURL_FEATURE_LIBZ
+
+/* Defined if libcurl supports NTLM */
+#undef LIBCURL_FEATURE_NTLM
+
+/* Defined if libcurl supports SSL */
+#undef LIBCURL_FEATURE_SSL
+
+/* Defined if libcurl supports SSPI */
+#undef LIBCURL_FEATURE_SSPI
+
+/* Defined if libcurl supports DICT */
+#undef LIBCURL_PROTOCOL_DICT
+
+/* Defined if libcurl supports FILE */
+#undef LIBCURL_PROTOCOL_FILE
+
+/* Defined if libcurl supports FTP */
+#undef LIBCURL_PROTOCOL_FTP
+
+/* Defined if libcurl supports FTPS */
+#undef LIBCURL_PROTOCOL_FTPS
+
+/* Defined if libcurl supports HTTP */
+#undef LIBCURL_PROTOCOL_HTTP
+
+/* Defined if libcurl supports HTTPS */
+#undef LIBCURL_PROTOCOL_HTTPS
+
+/* Defined if libcurl supports LDAP */
+#undef LIBCURL_PROTOCOL_LDAP
+
+/* Defined if libcurl supports TELNET */
+#undef LIBCURL_PROTOCOL_TELNET
+
+/* Defined if libcurl supports TFTP */
+#undef LIBCURL_PROTOCOL_TFTP
+
+/* This is a Linux system */
+#undef LINUX
+
+/* Define to 1 if `lstat' dereferences a symlink specified with a trailing
+   slash. */
+#undef LSTAT_FOLLOWS_SLASHED_SYMLINK
+
+/* Define if the OS needs help to load dependent libraries for dlopen(). */
+#undef LTDL_DLOPEN_DEPLIBS
+
+/* Define to the system default library search path. */
+#undef LT_DLSEARCH_PATH
+
+/* The archive extension */
+#undef LT_LIBEXT
+
+/* Define to the extension used for runtime loadable modules, say, ".so". */
+#undef LT_MODULE_EXT
+
+/* Define to the name of the environment variable that determines the run-time
+   module search path. */
+#undef LT_MODULE_PATH_VAR
+
+/* Define to the sub-directory in which libtool stores uninstalled libraries.
+   */
+#undef LT_OBJDIR
+
+/* This is a MinGW system */
+#undef MINGW
+
+/* Define if dlsym() requires a leading underscore in symbol names. */
+#undef NEED_USCORE
+
+/* This is a NetBSD system */
+#undef NETBSD
+
+/* Define to 1 if your C compiler doesn't accept -c and -o together. */
+#undef NO_MINUS_C_MINUS_O
+
+/* This is an OpenBSD system */
+#undef OPENBSD
+
+/* Some strange OS */
+#undef OTHEROS
+
+/* Name of package */
+#undef PACKAGE
+
+/* Define to the address where bug reports for this package should be sent. */
+#undef PACKAGE_BUGREPORT
+
+/* Define to the full name of this package. */
+#undef PACKAGE_NAME
+
+/* Define to the full name and version of this package. */
+#undef PACKAGE_STRING
+
+/* Define to the one symbol short name of this package. */
+#undef PACKAGE_TARNAME
+
+/* Define to the home page for this package. */
+#undef PACKAGE_URL
+
+/* Define to the version of this package. */
+#undef PACKAGE_VERSION
+
+/* Define as the return type of signal handlers (`int' or `void'). */
+#undef RETSIGTYPE
+
+/* Define to the type of arg 1 for `select'. */
+#undef SELECT_TYPE_ARG1
+
+/* Define to the type of args 2, 3 and 4 for `select'. */
+#undef SELECT_TYPE_ARG234
+
+/* Define to the type of arg 5 for `select'. */
+#undef SELECT_TYPE_ARG5
+
+/* This is a Solaris system */
+#undef SOLARIS
+
+/* This is a BSD system */
+#undef SOMEBSD
+
+/* Define to 1 if the `S_IS*' macros in <sys/stat.h> do not work properly. */
+#undef STAT_MACROS_BROKEN
+
+/* Define to 1 if you have the ANSI C header files. */
+#undef STDC_HEADERS
+
+/* Define to 1 if you can safely include both <sys/time.h> and <time.h>. */
+#undef TIME_WITH_SYS_TIME
+
+/* Define to 1 if your <sys/time.h> declares `struct tm'. */
+#undef TM_IN_SYS_TIME
+
+/* Version number of package */
+#undef VERSION
+
+/* This is a Windows system */
+#undef WINDOWS
+
+/* Define to 1 if the X Window System is missing or not being used. */
+#undef X_DISPLAY_MISSING
+
+/* Number of bits in a file offset, on hosts where this is settable. */
+#undef _FILE_OFFSET_BITS
+
+/* Define to 1 to make fseeko visible on some hosts (e.g. glibc 2.2). */
+#undef _LARGEFILE_SOURCE
+
+/* Define for large files, on AIX-style hosts. */
+#undef _LARGE_FILES
+
+/* Need with solaris or errno doesnt work */
+#undef _REENTRANT
+
+/* This is a Windows system */
+#undef _WIN32
+
+/* Define so that glibc/gnulib argp.h does not typedef error_t. */
+#undef __error_t_defined
+
+/* Define curl_free() as free() if our version of curl lacks curl_free. */
+#undef curl_free
+
+/* Define to a type to use for `error_t' if it is not otherwise available. */
+#undef error_t
+
+/* Define to `int' if <sys/types.h> doesn't define. */
+#undef gid_t
+
+/* Define to `int' if <sys/types.h> does not define. */
+#undef mode_t
+
+/* Define to `long int' if <sys/types.h> does not define. */
+#undef off_t
+
+/* Define to `int' if <sys/types.h> does not define. */
+#undef pid_t
+
+/* Define to `unsigned int' if <sys/types.h> does not define. */
+#undef size_t
+
+/* Define to `int' if <sys/types.h> doesn't define. */
+#undef uid_t
+
+/* Define as `fork' if `vfork' does not work. */
+#undef vfork
diff --git a/po/.gitignore b/po/.gitignore
new file mode 100644
index 0000000000000000000000000000000000000000..0a6b78acb36b916dd49fefe0c1872bc281347ffd
--- /dev/null
+++ b/po/.gitignore
@@ -0,0 +1,3 @@
+POTFILES
+gnunet.pot
+remove-potcdate.sed
diff --git a/po/Makevars.template b/po/Makevars.template
new file mode 100644
index 0000000000000000000000000000000000000000..32692ab4b98405fcbf6a46497fba1a6c773d1b90
--- /dev/null
+++ b/po/Makevars.template
@@ -0,0 +1,41 @@
+# Makefile variables for PO directory in any package using GNU gettext.
+
+# Usually the message domain is the same as the package name.
+DOMAIN = $(PACKAGE)
+
+# These two variables depend on the location of this directory.
+subdir = po
+top_builddir = ..
+
+# These options get passed to xgettext.
+XGETTEXT_OPTIONS = --keyword=_ --keyword=N_
+
+# This is the copyright holder that gets inserted into the header of the
+# $(DOMAIN).pot file.  Set this to the copyright holder of the surrounding
+# package.  (Note that the msgstr strings, extracted from the package's
+# sources, belong to the copyright holder of the package.)  Translators are
+# expected to transfer the copyright for their translations to this person
+# or entity, or to disclaim their copyright.  The empty string stands for
+# the public domain; in this case the translators are expected to disclaim
+# their copyright.
+COPYRIGHT_HOLDER = Free Software Foundation, Inc.
+
+# This is the email address or URL to which the translators shall report
+# bugs in the untranslated strings:
+# - Strings which are not entire sentences, see the maintainer guidelines
+#   in the GNU gettext documentation, section 'Preparing Strings'.
+# - Strings which use unclear terms or require additional context to be
+#   understood.
+# - Strings which make invalid assumptions about notation of date, time or
+#   money.
+# - Pluralisation problems.
+# - Incorrect English spelling.
+# - Incorrect formatting.
+# It can be your email address, or a mailing list address where translators
+# can write to without being subscribed, or the URL of a web page through
+# which the translators can contact you.
+MSGID_BUGS_ADDRESS =
+
+# This is the list of locale categories, beyond LC_MESSAGES, for which the
+# message catalogs shall be used.  It is usually empty.
+EXTRA_LOCALE_CATEGORIES =
diff --git a/po/POTFILES.in b/po/POTFILES.in
index 9ad5b4862acfe6d81f7fc5b6f426af09d5e05a5e..36d948d931ae7d65c5e3e13923d66f9483132969 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -272,13 +272,13 @@ src/reclaim/gnunet-service-reclaim_tickets.c
 src/reclaim/json_reclaim.c
 src/reclaim/oidc_helper.c
 src/reclaim/plugin_gnsrecord_reclaim.c
-src/reclaim/plugin_reclaim_attestation_jwt.c
 src/reclaim/plugin_reclaim_attribute_basic.c
+src/reclaim/plugin_reclaim_credential_jwt.c
 src/reclaim/plugin_rest_openid_connect.c
 src/reclaim/plugin_rest_reclaim.c
 src/reclaim/reclaim_api.c
-src/reclaim/reclaim_attestation.c
 src/reclaim/reclaim_attribute.c
+src/reclaim/reclaim_credential.c
 src/regex/gnunet-daemon-regexprofiler.c
 src/regex/gnunet-regex-profiler.c
 src/regex/gnunet-regex-simulation-profiler.c
@@ -331,8 +331,20 @@ src/set/gnunet-set-ibf-profiler.c
 src/set/gnunet-set-profiler.c
 src/set/ibf.c
 src/set/ibf_sim.c
+src/seti/gnunet-service-seti.c
+src/seti/gnunet-seti-profiler.c
+src/seti/plugin_block_seti_test.c
+src/seti/seti_api.c
 src/set/plugin_block_set_test.c
 src/set/set_api.c
+src/setu/gnunet-service-setu.c
+src/setu/gnunet-service-setu_strata_estimator.c
+src/setu/gnunet-setu-ibf-profiler.c
+src/setu/gnunet-setu-profiler.c
+src/setu/ibf.c
+src/setu/ibf_sim.c
+src/setu/plugin_block_setu_test.c
+src/setu/setu_api.c
 src/sq/sq.c
 src/sq/sq_exec.c
 src/sq/sq_prepare.c
@@ -503,6 +515,7 @@ src/util/speedup.c
 src/util/strings.c
 src/util/time.c
 src/util/tun.c
+src/util/uri.c
 src/vpn/gnunet-helper-vpn.c
 src/vpn/gnunet-service-vpn.c
 src/vpn/gnunet-vpn.c
diff --git a/po/de.po b/po/de.po
index ee2287cf630d2c41fb3b6105ed27e758230775ba..b352a977ee29c41b8fd0af1f146b0ecd61be6671 100644
--- a/po/de.po
+++ b/po/de.po
@@ -10,7 +10,7 @@ msgid ""
 msgstr ""
 "Project-Id-Version: gnunet 0.10.1\n"
 "Report-Msgid-Bugs-To: gnunet-developers@mail.gnu.org\n"
-"POT-Creation-Date: 2020-07-12 17:55+0200\n"
+"POT-Creation-Date: 2020-09-06 10:07+0200\n"
 "PO-Revision-Date: 2015-03-08 16:16+0100\n"
 "Last-Translator: Mario Blättermann <mario.blaettermann@gmail.com>\n"
 "Language-Team: German <translation-team-de@lists.sourceforge.net>\n"
@@ -21,12 +21,12 @@ msgstr ""
 "Plural-Forms: nplurals=2; plural=(n != 1);\n"
 "X-Generator: Poedit 1.7.4\n"
 
-#: src/abd/gnunet-abd.c:397 src/namestore/gnunet-namestore.c:1302
+#: src/abd/gnunet-abd.c:397 src/namestore/gnunet-namestore.c:1303
 #, fuzzy, c-format
 msgid "Ego `%s' not known to identity service\n"
 msgstr "`%s': unbekannter Dienst: %s\n"
 
-#: src/abd/gnunet-abd.c:413 src/abd/gnunet-abd.c:896
+#: src/abd/gnunet-abd.c:413 src/abd/gnunet-abd.c:901
 #, c-format
 msgid "Issuer public key `%s' is not well-formed\n"
 msgstr ""
@@ -38,107 +38,107 @@ msgstr ""
 msgid "Failed to connect to namestore\n"
 msgstr "Es konnte keine Verbindung mit gnunetd hergestellt werden.\n"
 
-#: src/abd/gnunet-abd.c:835 src/abd/gnunet-abd.c:886
+#: src/abd/gnunet-abd.c:840 src/abd/gnunet-abd.c:891
 #, fuzzy, c-format
 msgid "Issuer public key not well-formed\n"
 msgstr "Ungültiger Parameter: `%s'\n"
 
-#: src/abd/gnunet-abd.c:844 src/abd/gnunet-abd.c:905
+#: src/abd/gnunet-abd.c:849 src/abd/gnunet-abd.c:910
 #, fuzzy, c-format
 msgid "Failed to connect to ABD\n"
 msgstr "Es konnte keine Verbindung mit gnunetd hergestellt werden.\n"
 
-#: src/abd/gnunet-abd.c:850
+#: src/abd/gnunet-abd.c:855
 #, c-format
 msgid "You must provide issuer the attribute\n"
 msgstr ""
 
-#: src/abd/gnunet-abd.c:857
+#: src/abd/gnunet-abd.c:862
 #, fuzzy, c-format
 msgid "ego required\n"
 msgstr "Gültiger Typ ist erforderlich\n"
 
-#: src/abd/gnunet-abd.c:867
+#: src/abd/gnunet-abd.c:872
 #, c-format
 msgid "Subject public key needed\n"
 msgstr ""
 
-#: src/abd/gnunet-abd.c:876
+#: src/abd/gnunet-abd.c:881
 #, c-format
 msgid "Subject public key `%s' is not well-formed\n"
 msgstr ""
 
-#: src/abd/gnunet-abd.c:911
+#: src/abd/gnunet-abd.c:916
 #, c-format
 msgid "You must provide issuer and subject attributes\n"
 msgstr ""
 
-#: src/abd/gnunet-abd.c:970
+#: src/abd/gnunet-abd.c:975
 #, c-format
 msgid "Please specify name to lookup, subject key and issuer key!\n"
 msgstr ""
 
-#: src/abd/gnunet-abd.c:991
+#: src/abd/gnunet-abd.c:996
 msgid "verify credential against attribute"
 msgstr ""
 
-#: src/abd/gnunet-abd.c:998
+#: src/abd/gnunet-abd.c:1003
 #, fuzzy
 msgid ""
 "The public key of the subject to lookup thecredential for, or for issuer "
 "side storage: subject and its attributes"
 msgstr "Die Priorität des Inhalts angeben"
 
-#: src/abd/gnunet-abd.c:1005
+#: src/abd/gnunet-abd.c:1010
 msgid "The private, signed delegate presented by the subject"
 msgstr ""
 
-#: src/abd/gnunet-abd.c:1012
+#: src/abd/gnunet-abd.c:1017
 msgid "The public key of the authority to verify the credential against"
 msgstr ""
 
-#: src/abd/gnunet-abd.c:1017
+#: src/abd/gnunet-abd.c:1022
 msgid "The ego/zone name to use"
 msgstr ""
 
-#: src/abd/gnunet-abd.c:1023
+#: src/abd/gnunet-abd.c:1028
 msgid "The issuer attribute to verify against or to issue"
 msgstr ""
 
-#: src/abd/gnunet-abd.c:1029
+#: src/abd/gnunet-abd.c:1034
 msgid ""
 "The time to live for the credential.e.g. 5m, 6h, \"1990-12-30 12:00:00\""
 msgstr ""
 
-#: src/abd/gnunet-abd.c:1034
+#: src/abd/gnunet-abd.c:1039
 msgid "collect credentials"
 msgstr ""
 
-#: src/abd/gnunet-abd.c:1039
+#: src/abd/gnunet-abd.c:1044
 msgid "Create and issue a credential issuer side."
 msgstr ""
 
-#: src/abd/gnunet-abd.c:1044
+#: src/abd/gnunet-abd.c:1049
 msgid "Issue a credential subject side."
 msgstr ""
 
-#: src/abd/gnunet-abd.c:1049
+#: src/abd/gnunet-abd.c:1054
 msgid "Create, sign and return a credential subject side."
 msgstr ""
 
-#: src/abd/gnunet-abd.c:1056
+#: src/abd/gnunet-abd.c:1061
 msgid "Import signed credentials that should be issued to a zone/ego"
 msgstr ""
 
-#: src/abd/gnunet-abd.c:1060
+#: src/abd/gnunet-abd.c:1065
 msgid "Create private record entry."
 msgstr ""
 
-#: src/abd/gnunet-abd.c:1066 src/abd/gnunet-abd.c:1072
+#: src/abd/gnunet-abd.c:1071 src/abd/gnunet-abd.c:1077
 msgid "Indicates that the collect/verify process is done via forward search."
 msgstr ""
 
-#: src/abd/gnunet-abd.c:1085
+#: src/abd/gnunet-abd.c:1090
 #, fuzzy
 msgid "GNUnet abd resolver tool"
 msgstr "GNUnet Netzwerk Topologie tracen."
@@ -433,64 +433,64 @@ msgstr "»%s« konnte nicht aufgelöst werden: %s\n"
 msgid "Failed to find %saddress for `%s'.\n"
 msgstr "Fehler beim Lesen der Freunde-Liste von `%s'\n"
 
-#: src/arm/gnunet-service-arm.c:933
+#: src/arm/gnunet-service-arm.c:951
 #, fuzzy, c-format
 msgid "Failed to start service `%s'\n"
 msgstr "Der Transportdienst auf Port %d konnte nicht gestartet werden.\n"
 
-#: src/arm/gnunet-service-arm.c:944
+#: src/arm/gnunet-service-arm.c:962
 #, fuzzy, c-format
 msgid "Starting service `%s'\n"
 msgstr "Collection `%s' begonnen.\n"
 
-#: src/arm/gnunet-service-arm.c:1044
+#: src/arm/gnunet-service-arm.c:1062
 #, fuzzy, c-format
 msgid "Unable to create socket for service `%s': %s\n"
 msgstr "Fehler beim Anlegen des Benutzerkontos:"
 
-#: src/arm/gnunet-service-arm.c:1075
+#: src/arm/gnunet-service-arm.c:1093
 #, c-format
 msgid "Unable to bind listening socket for service `%s' to address `%s': %s\n"
 msgstr ""
 
-#: src/arm/gnunet-service-arm.c:1106
+#: src/arm/gnunet-service-arm.c:1124
 #, c-format
 msgid "ARM now monitors connections to service `%s' at `%s'\n"
 msgstr ""
 
-#: src/arm/gnunet-service-arm.c:1254
+#: src/arm/gnunet-service-arm.c:1272
 #, fuzzy, c-format
 msgid "Preparing to stop `%s'\n"
 msgstr "Collection `%s' begonnen.\n"
 
-#: src/arm/gnunet-service-arm.c:1586
+#: src/arm/gnunet-service-arm.c:1604
 #, c-format
 msgid "Restarting service `%s'.\n"
 msgstr "Dienst »%s« wird neu gestartet.\n"
 
-#: src/arm/gnunet-service-arm.c:1737
+#: src/arm/gnunet-service-arm.c:1755
 msgid "exit"
 msgstr ""
 
-#: src/arm/gnunet-service-arm.c:1742
+#: src/arm/gnunet-service-arm.c:1760
 msgid "signal"
 msgstr "Signal"
 
-#: src/arm/gnunet-service-arm.c:1747
+#: src/arm/gnunet-service-arm.c:1765
 msgid "unknown"
 msgstr "Unbekannt"
 
-#: src/arm/gnunet-service-arm.c:1753
+#: src/arm/gnunet-service-arm.c:1771
 #, c-format
 msgid "Service `%s' took %s to terminate\n"
 msgstr "Dienst »%s« benötigte %s zum Beenden\n"
 
-#: src/arm/gnunet-service-arm.c:1780
+#: src/arm/gnunet-service-arm.c:1798
 #, c-format
 msgid "Service `%s' terminated normally, will restart at any time\n"
 msgstr "Dienst »%s« wurde normal beendet, wird jederzeit neu gestartet\n"
 
-#: src/arm/gnunet-service-arm.c:1797
+#: src/arm/gnunet-service-arm.c:1815
 #, c-format
 msgid "Service `%s' terminated with status %s/%d, will restart in %s\n"
 msgstr ""
@@ -820,7 +820,10 @@ msgstr ""
 
 #: src/consensus/gnunet-consensus-profiler.c:543
 #: src/set/gnunet-set-profiler.c:451 src/set/gnunet-set-profiler.c:457
-#: src/set/gnunet-set-profiler.c:480
+#: src/set/gnunet-set-profiler.c:480 src/seti/gnunet-seti-profiler.c:441
+#: src/seti/gnunet-seti-profiler.c:446 src/seti/gnunet-seti-profiler.c:451
+#: src/setu/gnunet-setu-profiler.c:442 src/setu/gnunet-setu-profiler.c:448
+#: src/setu/gnunet-setu-profiler.c:471
 msgid "number of values"
 msgstr "Anzahl der Werte"
 
@@ -833,7 +836,8 @@ msgid "delay until consensus starts"
 msgstr ""
 
 #: src/consensus/gnunet-consensus-profiler.c:563
-#: src/set/gnunet-set-profiler.c:498
+#: src/set/gnunet-set-profiler.c:498 src/seti/gnunet-seti-profiler.c:467
+#: src/setu/gnunet-setu-profiler.c:489
 msgid "write statistics to file"
 msgstr ""
 
@@ -1373,153 +1377,153 @@ msgstr ""
 msgid "Core service of `%s' ready.\n"
 msgstr "Dienst »%s« wird neu gestartet.\n"
 
-#: src/core/gnunet-service-core_kx.c:625
+#: src/core/gnunet-service-core_kx.c:512
 msgid "# bytes encrypted"
 msgstr "# Bytes verschlüsselt"
 
-#: src/core/gnunet-service-core_kx.c:683
+#: src/core/gnunet-service-core_kx.c:570
 msgid "# bytes decrypted"
 msgstr "# Bytes entschlüsselt"
 
-#: src/core/gnunet-service-core_kx.c:780
+#: src/core/gnunet-service-core_kx.c:667
 msgid "# PAYLOAD dropped (out of order)"
 msgstr ""
 
-#: src/core/gnunet-service-core_kx.c:832
+#: src/core/gnunet-service-core_kx.c:719
 msgid "# key exchanges initiated"
 msgstr ""
 
-#: src/core/gnunet-service-core_kx.c:888
+#: src/core/gnunet-service-core_kx.c:775
 msgid "# key exchanges stopped"
 msgstr ""
 
-#: src/core/gnunet-service-core_kx.c:920
+#: src/core/gnunet-service-core_kx.c:807
 #, fuzzy
 msgid "# PING messages transmitted"
 msgstr "# PING Nachrichten erstellt"
 
-#: src/core/gnunet-service-core_kx.c:979
+#: src/core/gnunet-service-core_kx.c:866
 msgid "# old ephemeral keys ignored"
 msgstr ""
 
-#: src/core/gnunet-service-core_kx.c:993
+#: src/core/gnunet-service-core_kx.c:880
 #, fuzzy
 msgid "# duplicate ephemeral keys ignored"
 msgstr "# verschlüsselter PONG Nachrichten empfangen"
 
-#: src/core/gnunet-service-core_kx.c:1028
+#: src/core/gnunet-service-core_kx.c:915
 #, fuzzy
 msgid "# EPHEMERAL_KEYs rejected (bad signature)"
 msgstr "# verschlüsselter PONG Nachrichten empfangen"
 
-#: src/core/gnunet-service-core_kx.c:1046
+#: src/core/gnunet-service-core_kx.c:933
 #, c-format
 msgid ""
 "EPHEMERAL_KEY from peer `%s' rejected as its validity range does not match "
 "our system time (%llu not in [%llu,%llu]).\n"
 msgstr ""
 
-#: src/core/gnunet-service-core_kx.c:1053
+#: src/core/gnunet-service-core_kx.c:940
 #, fuzzy
 msgid "# EPHEMERAL_KEY messages rejected due to time"
 msgstr "# verschlüsselter PONG Nachrichten empfangen"
 
-#: src/core/gnunet-service-core_kx.c:1071
+#: src/core/gnunet-service-core_kx.c:958
 #, fuzzy
 msgid "# valid ephemeral keys received"
 msgstr "# verschlüsselter PONG Nachrichten empfangen"
 
-#: src/core/gnunet-service-core_kx.c:1180
+#: src/core/gnunet-service-core_kx.c:1067
 #: src/transport/gnunet-service-transport_validation.c:1133
 #, fuzzy
 msgid "# PING messages received"
 msgstr "# PING Nachrichten erstellt"
 
-#: src/core/gnunet-service-core_kx.c:1190
+#: src/core/gnunet-service-core_kx.c:1077
 #, fuzzy
 msgid "# PING messages dropped (out of order)"
 msgstr "# PING Nachrichten erstellt"
 
-#: src/core/gnunet-service-core_kx.c:1239
+#: src/core/gnunet-service-core_kx.c:1126
 #, fuzzy
 msgid "# PONG messages created"
 msgstr "# PING Nachrichten erstellt"
 
-#: src/core/gnunet-service-core_kx.c:1264
+#: src/core/gnunet-service-core_kx.c:1151
 msgid "# sessions terminated by timeout"
 msgstr ""
 
-#: src/core/gnunet-service-core_kx.c:1277
+#: src/core/gnunet-service-core_kx.c:1164
 #, fuzzy
 msgid "# keepalive messages sent"
 msgstr "# Klartext PING Nachrichten gesendet"
 
-#: src/core/gnunet-service-core_kx.c:1334
+#: src/core/gnunet-service-core_kx.c:1221
 #: src/transport/gnunet-service-transport_validation.c:1476
 #, fuzzy
 msgid "# PONG messages received"
 msgstr "# verschlüsselter PONG Nachrichten empfangen"
 
-#: src/core/gnunet-service-core_kx.c:1342
+#: src/core/gnunet-service-core_kx.c:1229
 msgid "# PONG messages dropped (connection down)"
 msgstr ""
 
-#: src/core/gnunet-service-core_kx.c:1350
+#: src/core/gnunet-service-core_kx.c:1237
 #, fuzzy
 msgid "# PONG messages dropped (out of order)"
 msgstr "# PING Nachrichten erstellt"
 
-#: src/core/gnunet-service-core_kx.c:1389
+#: src/core/gnunet-service-core_kx.c:1276
 #, fuzzy
 msgid "# PONG messages decrypted"
 msgstr "# PING Nachrichten erstellt"
 
-#: src/core/gnunet-service-core_kx.c:1429
+#: src/core/gnunet-service-core_kx.c:1316
 #, fuzzy
 msgid "# session keys confirmed via PONG"
 msgstr "# Knotenankündigungen empfangen"
 
-#: src/core/gnunet-service-core_kx.c:1441
+#: src/core/gnunet-service-core_kx.c:1328
 #, fuzzy
 msgid "# timeouts prevented via PONG"
 msgstr "# Bytes empfangen über TCP"
 
-#: src/core/gnunet-service-core_kx.c:1450
+#: src/core/gnunet-service-core_kx.c:1337
 #, fuzzy
 msgid "# rekey operations confirmed via PONG"
 msgstr "# Knotenankündigungen empfangen"
 
-#: src/core/gnunet-service-core_kx.c:1626
+#: src/core/gnunet-service-core_kx.c:1513
 msgid "# DATA message dropped (out of order)"
 msgstr ""
 
-#: src/core/gnunet-service-core_kx.c:1637
+#: src/core/gnunet-service-core_kx.c:1524
 #, c-format
 msgid ""
 "Session to peer `%s' went down due to key expiration (should not happen)\n"
 msgstr ""
 
-#: src/core/gnunet-service-core_kx.c:1641
+#: src/core/gnunet-service-core_kx.c:1528
 msgid "# sessions terminated by key expiration"
 msgstr ""
 
-#: src/core/gnunet-service-core_kx.c:1719
-#: src/core/gnunet-service-core_kx.c:1746
+#: src/core/gnunet-service-core_kx.c:1606
+#: src/core/gnunet-service-core_kx.c:1633
 #, fuzzy
 msgid "# bytes dropped (duplicates)"
 msgstr "# Bytes verworfen von TCP (ausgehend)"
 
-#: src/core/gnunet-service-core_kx.c:1732
+#: src/core/gnunet-service-core_kx.c:1619
 #, fuzzy
 msgid "# bytes dropped (out of sequence)"
 msgstr "# Bytes verworfen von TCP (ausgehend)"
 
-#: src/core/gnunet-service-core_kx.c:1777
+#: src/core/gnunet-service-core_kx.c:1664
 #, fuzzy
 msgid "# bytes dropped (ancient message)"
 msgstr "# Bytes verworfen von TCP (ausgehend)"
 
-#: src/core/gnunet-service-core_kx.c:1786
+#: src/core/gnunet-service-core_kx.c:1673
 #, fuzzy
 msgid "# bytes of payload decrypted"
 msgstr "# Bytes entschlüsselt"
@@ -3134,18 +3138,18 @@ msgstr ""
 msgid "Failed to load state: %s\n"
 msgstr "Es konnte keine Verbindung mit gnunetd hergestellt werden.\n"
 
-#: src/fs/gnunet-auto-share.c:286 src/fs/gnunet-auto-share.c:295
-#: src/fs/gnunet-auto-share.c:303
+#: src/fs/gnunet-auto-share.c:287 src/fs/gnunet-auto-share.c:296
+#: src/fs/gnunet-auto-share.c:304
 #, fuzzy, c-format
 msgid "Failed to save state to file %s\n"
 msgstr "Fehler beim Aktualisieren der Daten des Moduls `%s'\n"
 
-#: src/fs/gnunet-auto-share.c:400
+#: src/fs/gnunet-auto-share.c:401
 #, c-format
 msgid "Publication of `%s' done\n"
 msgstr ""
 
-#: src/fs/gnunet-auto-share.c:479
+#: src/fs/gnunet-auto-share.c:480
 #, c-format
 msgid "Publishing `%s'\n"
 msgstr ""
@@ -3990,39 +3994,39 @@ msgstr ""
 msgid "GNUnet HTTP server to create business cards"
 msgstr ""
 
-#: src/gns/gnunet-dns2gns.c:239
+#: src/gns/gnunet-dns2gns.c:241
 msgid "Failed to pack DNS response into UDP packet!\n"
 msgstr ""
 
-#: src/gns/gnunet-dns2gns.c:442
+#: src/gns/gnunet-dns2gns.c:444
 #, c-format
 msgid "Cannot parse DNS request from %s\n"
 msgstr ""
 
-#: src/gns/gnunet-dns2gns.c:458
+#: src/gns/gnunet-dns2gns.c:460
 #, fuzzy, c-format
 msgid "Received malformed DNS request from %s\n"
 msgstr "Beschädigte Antwort auf `%s' von Knoten `%s' empfangen.\n"
 
-#: src/gns/gnunet-dns2gns.c:466
+#: src/gns/gnunet-dns2gns.c:468
 #, fuzzy, c-format
 msgid "Received unsupported DNS request from %s\n"
 msgstr "Unbekannte Anfrageart %d empfangen bei %s:%d\n"
 
-#: src/gns/gnunet-dns2gns.c:627
+#: src/gns/gnunet-dns2gns.c:629
 #, fuzzy
 msgid "No DNS server specified!\n"
 msgstr "Keine Schlüsselwörter angegeben!\n"
 
-#: src/gns/gnunet-dns2gns.c:776
+#: src/gns/gnunet-dns2gns.c:778
 msgid "IP of recursive DNS resolver to use (required)"
 msgstr ""
 
-#: src/gns/gnunet-dns2gns.c:782
+#: src/gns/gnunet-dns2gns.c:784
 msgid "UDP port to listen on for inbound DNS requests; default: 2853"
 msgstr ""
 
-#: src/gns/gnunet-dns2gns.c:799
+#: src/gns/gnunet-dns2gns.c:801
 msgid "GNUnet DNS-to-GNS proxy (a DNS server)"
 msgstr ""
 
@@ -4163,7 +4167,7 @@ msgstr "SQLite Datenbank konnte nicht initialisiert werden: %s.\n"
 msgid "Failed to start HTTPS server for `%s'\n"
 msgstr "Der Transportdienst auf Port %d konnte nicht gestartet werden.\n"
 
-#: src/gns/gnunet-gns-proxy.c:2922 src/rest/gnunet-rest-server.c:713
+#: src/gns/gnunet-gns-proxy.c:2922 src/rest/gnunet-rest-server.c:917
 #, fuzzy
 msgid "Failed to pass client to MHD\n"
 msgstr "Fehler beim Starten der Collection.\n"
@@ -4320,7 +4324,7 @@ msgstr "Fehler beim Speichern der Konfigurationsdatei `%s':"
 msgid "Unable to parse BOX record string `%s'\n"
 msgstr "Fehler beim Speichern der Konfigurationsdatei `%s':"
 
-#: src/gns/plugin_rest_gns.c:445
+#: src/gns/plugin_rest_gns.c:447
 #, fuzzy
 msgid "Gns REST API initialized\n"
 msgstr " Verbindung fehlgeschlagen\n"
@@ -4519,7 +4523,7 @@ msgid "# valid HELLOs downloaded from hostlist servers"
 msgstr "# Hellos per HTTP heruntergeladen"
 
 #: src/hostlist/gnunet-daemon-hostlist_client.c:677
-#: src/hostlist/gnunet-daemon-hostlist_client.c:1459
+#: src/hostlist/gnunet-daemon-hostlist_client.c:1460
 msgid "# advertised hostlist URIs"
 msgstr ""
 
@@ -4570,7 +4574,7 @@ msgid "# hostlist downloads initiated"
 msgstr ""
 
 #: src/hostlist/gnunet-daemon-hostlist_client.c:1144
-#: src/hostlist/gnunet-daemon-hostlist_client.c:1726
+#: src/hostlist/gnunet-daemon-hostlist_client.c:1728
 msgid "# milliseconds between hostlist downloads"
 msgstr ""
 
@@ -4601,51 +4605,51 @@ msgid "Could not open file `%s' for reading to load hostlists: %s\n"
 msgstr ""
 "`%s' konnte nicht aufgelöst werden, um unsere IP-Adresse zu ermitteln: %s\n"
 
-#: src/hostlist/gnunet-daemon-hostlist_client.c:1452
+#: src/hostlist/gnunet-daemon-hostlist_client.c:1453
 #, c-format
 msgid "%u hostlist URIs loaded from file\n"
 msgstr ""
 
-#: src/hostlist/gnunet-daemon-hostlist_client.c:1455
+#: src/hostlist/gnunet-daemon-hostlist_client.c:1456
 msgid "# hostlist URIs read from file"
 msgstr ""
 
-#: src/hostlist/gnunet-daemon-hostlist_client.c:1506
+#: src/hostlist/gnunet-daemon-hostlist_client.c:1507
 #, fuzzy, c-format
 msgid "Could not open file `%s' for writing to save hostlists: %s\n"
 msgstr ""
 "Datei `%s' konnte nicht zu `%s' umbenannt werden: Datei existiert bereits\n"
 
-#: src/hostlist/gnunet-daemon-hostlist_client.c:1513
+#: src/hostlist/gnunet-daemon-hostlist_client.c:1514
 #, fuzzy, c-format
 msgid "Writing %u hostlist URIs to `%s'\n"
 msgstr "Fehler beim Lesen der Freunde-Liste von `%s'\n"
 
-#: src/hostlist/gnunet-daemon-hostlist_client.c:1545
-#: src/hostlist/gnunet-daemon-hostlist_client.c:1564
+#: src/hostlist/gnunet-daemon-hostlist_client.c:1547
+#: src/hostlist/gnunet-daemon-hostlist_client.c:1566
 #, c-format
 msgid "Error writing hostlist URIs to file `%s'\n"
 msgstr ""
 
-#: src/hostlist/gnunet-daemon-hostlist_client.c:1558
+#: src/hostlist/gnunet-daemon-hostlist_client.c:1560
 msgid "# hostlist URIs written to file"
 msgstr ""
 
-#: src/hostlist/gnunet-daemon-hostlist_client.c:1655
+#: src/hostlist/gnunet-daemon-hostlist_client.c:1657
 #: src/transport/plugin_transport_http_client.c:2301
 #, c-format
 msgid "Invalid proxy type: `%s', disabling proxy! Check configuration!\n"
 msgstr ""
 
-#: src/hostlist/gnunet-daemon-hostlist_client.c:1684
+#: src/hostlist/gnunet-daemon-hostlist_client.c:1686
 msgid "Learning is enabled on this peer\n"
 msgstr ""
 
-#: src/hostlist/gnunet-daemon-hostlist_client.c:1697
+#: src/hostlist/gnunet-daemon-hostlist_client.c:1699
 msgid "Learning is not enabled on this peer\n"
 msgstr ""
 
-#: src/hostlist/gnunet-daemon-hostlist_client.c:1711
+#: src/hostlist/gnunet-daemon-hostlist_client.c:1713
 #, c-format
 msgid ""
 "Since learning is not enabled on this peer, hostlist file `%s' was removed\n"
@@ -4771,48 +4775,48 @@ msgstr "Es konnte keine Verbindung mit gnunetd hergestellt werden.\n"
 msgid "Failed to set default ego: %s\n"
 msgstr "Fehler beim Parsen der Gerätedaten von `%s' bei %s:%d.\n"
 
-#: src/identity/gnunet-identity.c:445
+#: src/identity/gnunet-identity.c:446
 msgid "create ego NAME"
 msgstr ""
 
-#: src/identity/gnunet-identity.c:450
+#: src/identity/gnunet-identity.c:451
 msgid "delete ego NAME "
 msgstr ""
 
-#: src/identity/gnunet-identity.c:455
+#: src/identity/gnunet-identity.c:457
 msgid ""
 "set the private key for the identity to PRIVATE_KEY (use together with -C)"
 msgstr ""
 
-#: src/identity/gnunet-identity.c:459
+#: src/identity/gnunet-identity.c:461
 msgid "display all egos"
 msgstr ""
 
-#: src/identity/gnunet-identity.c:463
+#: src/identity/gnunet-identity.c:465
 #, fuzzy
 msgid "reduce output"
 msgstr "Ausführliche Ausgabe"
 
-#: src/identity/gnunet-identity.c:470
+#: src/identity/gnunet-identity.c:472
 msgid ""
 "set default identity to NAME for a subsystem SUBSYSTEM (use together with -"
 "s) or restrict results to NAME (use together with -d)"
 msgstr ""
 
-#: src/identity/gnunet-identity.c:474
+#: src/identity/gnunet-identity.c:476
 msgid "run in monitor mode egos"
 msgstr ""
 
-#: src/identity/gnunet-identity.c:478
+#: src/identity/gnunet-identity.c:480
 msgid "display private keys as well"
 msgstr ""
 
-#: src/identity/gnunet-identity.c:485
+#: src/identity/gnunet-identity.c:487
 msgid ""
 "set default identity to EGO for a subsystem SUBSYSTEM (use together with -e)"
 msgstr ""
 
-#: src/identity/gnunet-identity.c:500
+#: src/identity/gnunet-identity.c:502
 msgid "Maintain egos"
 msgstr ""
 
@@ -4863,7 +4867,7 @@ msgstr "Fehler beim Speichern der Konfigurationsdatei `%s':"
 msgid "Failed to create directory `%s' for storing egos\n"
 msgstr "Dateiformat fehlerhaft (kein GNUnet Verzeichnis?)\n"
 
-#: src/identity/plugin_rest_identity.c:1406
+#: src/identity/plugin_rest_identity.c:1384
 msgid "Identity REST API initialized\n"
 msgstr ""
 
@@ -4912,7 +4916,7 @@ msgstr "Ungültiger Parameter: `%s'\n"
 msgid "You must specify a name\n"
 msgstr "Sie müssen einen Empfänger angeben!\n"
 
-#: src/namecache/gnunet-namecache.c:214 src/namestore/gnunet-namestore.c:1639
+#: src/namecache/gnunet-namecache.c:214 src/namestore/gnunet-namestore.c:1640
 msgid "name of the record to add/delete/display"
 msgstr ""
 
@@ -4921,7 +4925,7 @@ msgstr ""
 msgid "specifies the public key of the zone to look in"
 msgstr "Die Priorität des Inhalts angeben"
 
-#: src/namecache/gnunet-namecache.c:233 src/namestore/gnunet-namestore.c:1700
+#: src/namecache/gnunet-namecache.c:233 src/namestore/gnunet-namestore.c:1701
 #, fuzzy
 msgid "GNUnet zone manipulation tool"
 msgstr "GNUnet Konfiguration"
@@ -5030,10 +5034,10 @@ msgstr "Dateiformat fehlerhaft (kein GNUnet Verzeichnis?)\n"
 msgid "No options given\n"
 msgstr ""
 
-#: src/namestore/gnunet-namestore.c:1014 src/namestore/gnunet-namestore.c:1065
-#: src/namestore/gnunet-namestore.c:1075 src/namestore/gnunet-namestore.c:1104
-#: src/namestore/gnunet-namestore.c:1125 src/namestore/gnunet-namestore.c:1152
-#: src/namestore/gnunet-namestore.c:1228
+#: src/namestore/gnunet-namestore.c:1014 src/namestore/gnunet-namestore.c:1066
+#: src/namestore/gnunet-namestore.c:1076 src/namestore/gnunet-namestore.c:1105
+#: src/namestore/gnunet-namestore.c:1126 src/namestore/gnunet-namestore.c:1153
+#: src/namestore/gnunet-namestore.c:1229
 #, fuzzy, c-format
 msgid "Missing option `%s' for operation `%s'\n"
 msgstr "Unbekannte Operation `%s'\n"
@@ -5047,53 +5051,53 @@ msgstr ""
 msgid "Invalid nick `%s'\n"
 msgstr "Ungültiger Parameter: `%s'\n"
 
-#: src/namestore/gnunet-namestore.c:1067 src/namestore/gnunet-namestore.c:1077
-#: src/namestore/gnunet-namestore.c:1106 src/namestore/gnunet-namestore.c:1127
-#: src/namestore/gnunet-namestore.c:1230
+#: src/namestore/gnunet-namestore.c:1068 src/namestore/gnunet-namestore.c:1078
+#: src/namestore/gnunet-namestore.c:1107 src/namestore/gnunet-namestore.c:1128
+#: src/namestore/gnunet-namestore.c:1231
 msgid "add"
 msgstr ""
 
-#: src/namestore/gnunet-namestore.c:1085
+#: src/namestore/gnunet-namestore.c:1086
 #, fuzzy, c-format
 msgid "Unsupported type `%s'\n"
 msgstr "Kommando `%s' wird nicht unterstützt. Vorgang wird abgebrochen.\n"
 
-#: src/namestore/gnunet-namestore.c:1095
+#: src/namestore/gnunet-namestore.c:1096
 #, c-format
 msgid "For DNS record types `SRV', `TLSA' and `OPENPGPKEY'"
 msgstr ""
 
-#: src/namestore/gnunet-namestore.c:1115
+#: src/namestore/gnunet-namestore.c:1116
 #, fuzzy, c-format
 msgid "Value `%s' invalid for record type `%s'\n"
 msgstr "%s: Symbolwert `%s' ist ungültig für %s\n"
 
-#: src/namestore/gnunet-namestore.c:1134 src/namestore/gnunet-namestore.c:1237
+#: src/namestore/gnunet-namestore.c:1135 src/namestore/gnunet-namestore.c:1238
 #, fuzzy, c-format
 msgid "Invalid time format `%s'\n"
 msgstr "Ungültiger Parameter: `%s'\n"
 
-#: src/namestore/gnunet-namestore.c:1154
+#: src/namestore/gnunet-namestore.c:1155
 msgid "del"
 msgstr ""
 
-#: src/namestore/gnunet-namestore.c:1197
+#: src/namestore/gnunet-namestore.c:1198
 #, c-format
 msgid "Invalid public key for reverse lookup `%s'\n"
 msgstr ""
 
-#: src/namestore/gnunet-namestore.c:1220
+#: src/namestore/gnunet-namestore.c:1221
 #: src/peerinfo-tool/gnunet-peerinfo.c:736
 #, fuzzy, c-format
 msgid "Invalid URI `%s'\n"
 msgstr "Ungültiger Parameter: `%s'\n"
 
-#: src/namestore/gnunet-namestore.c:1290
+#: src/namestore/gnunet-namestore.c:1291
 #, c-format
 msgid "Label `%s' contains `.' which is not allowed\n"
 msgstr ""
 
-#: src/namestore/gnunet-namestore.c:1340
+#: src/namestore/gnunet-namestore.c:1341
 #, c-format
 msgid ""
 "No default identity configured for `namestore' subsystem\n"
@@ -5101,99 +5105,99 @@ msgid ""
 "Run gnunet-identity -d to get a list of choices for $NAME\n"
 msgstr ""
 
-#: src/namestore/gnunet-namestore.c:1405
+#: src/namestore/gnunet-namestore.c:1406
 #, c-format
 msgid "Superfluous command line arguments (starting with `%s') ignored\n"
 msgstr ""
 
-#: src/namestore/gnunet-namestore.c:1434
+#: src/namestore/gnunet-namestore.c:1435
 #, fuzzy, c-format
 msgid "Cannot connect to identity service\n"
 msgstr "Verbindung zu %u.%u.%u.%u:%u fehlgeschlagen: %s\n"
 
-#: src/namestore/gnunet-namestore.c:1481
+#: src/namestore/gnunet-namestore.c:1482
 msgid "Empty record line argument is not allowed.\n"
 msgstr ""
 
-#: src/namestore/gnunet-namestore.c:1493
+#: src/namestore/gnunet-namestore.c:1494
 #, c-format
 msgid "Invalid expiration time `%s' (must be without unit)\n"
 msgstr ""
 
-#: src/namestore/gnunet-namestore.c:1505 src/namestore/gnunet-namestore.c:1521
-#: src/namestore/gnunet-namestore.c:1538
+#: src/namestore/gnunet-namestore.c:1506 src/namestore/gnunet-namestore.c:1522
+#: src/namestore/gnunet-namestore.c:1539
 #, fuzzy, c-format
 msgid "Missing entries in record line `%s'.\n"
 msgstr "Anwendung `%s' konnte nicht initialisiert werden.\n"
 
-#: src/namestore/gnunet-namestore.c:1513
+#: src/namestore/gnunet-namestore.c:1514
 #, fuzzy, c-format
 msgid "Unknown record type `%s'\n"
 msgstr "Unbekannter Befehl »%s«\n"
 
-#: src/namestore/gnunet-namestore.c:1551
+#: src/namestore/gnunet-namestore.c:1552
 #, fuzzy, c-format
 msgid "Invalid record data for type %s: `%s'.\n"
 msgstr "Ungültiges Format für IP: »%s«\n"
 
-#: src/namestore/gnunet-namestore.c:1608
+#: src/namestore/gnunet-namestore.c:1609
 msgid "add record"
 msgstr ""
 
-#: src/namestore/gnunet-namestore.c:1611
+#: src/namestore/gnunet-namestore.c:1612
 msgid "delete record"
 msgstr ""
 
-#: src/namestore/gnunet-namestore.c:1615
+#: src/namestore/gnunet-namestore.c:1616
 msgid "display records"
 msgstr ""
 
-#: src/namestore/gnunet-namestore.c:1622
+#: src/namestore/gnunet-namestore.c:1623
 msgid ""
 "expiration time for record to use (for adding only), \"never\" is possible"
 msgstr ""
 
-#: src/namestore/gnunet-namestore.c:1628
+#: src/namestore/gnunet-namestore.c:1629
 msgid "set the desired nick name for the zone"
 msgstr ""
 
-#: src/namestore/gnunet-namestore.c:1633
+#: src/namestore/gnunet-namestore.c:1634
 msgid "monitor changes in the namestore"
 msgstr ""
 
-#: src/namestore/gnunet-namestore.c:1645
+#: src/namestore/gnunet-namestore.c:1646
 msgid "determine our name for the given PKEY"
 msgstr ""
 
-#: src/namestore/gnunet-namestore.c:1652
+#: src/namestore/gnunet-namestore.c:1653
 msgid ""
 "set record set to values given by (possibly multiple) RECORDLINES; can be "
 "specified multiple times"
 msgstr ""
 
-#: src/namestore/gnunet-namestore.c:1658
+#: src/namestore/gnunet-namestore.c:1659
 msgid "type of the record to add/delete/display"
 msgstr ""
 
-#: src/namestore/gnunet-namestore.c:1663
+#: src/namestore/gnunet-namestore.c:1664
 msgid "URI to import into our zone"
 msgstr ""
 
-#: src/namestore/gnunet-namestore.c:1669
+#: src/namestore/gnunet-namestore.c:1670
 msgid "value of the record to add/delete"
 msgstr ""
 
-#: src/namestore/gnunet-namestore.c:1673
+#: src/namestore/gnunet-namestore.c:1674
 msgid "create or list public record"
 msgstr ""
 
-#: src/namestore/gnunet-namestore.c:1679
+#: src/namestore/gnunet-namestore.c:1680
 msgid ""
 "create shadow record (only valid if all other records of the same type have "
 "expired"
 msgstr ""
 
-#: src/namestore/gnunet-namestore.c:1685
+#: src/namestore/gnunet-namestore.c:1686
 msgid "name of the ego controlling the zone"
 msgstr ""
 
@@ -5293,7 +5297,7 @@ msgstr ""
 msgid "Flat file database running\n"
 msgstr "Sqlite-Datenbank läuft\n"
 
-#: src/namestore/plugin_rest_namestore.c:1093
+#: src/namestore/plugin_rest_namestore.c:1103
 #, fuzzy
 msgid "Namestore REST API initialized\n"
 msgstr " Verbindung fehlgeschlagen\n"
@@ -5568,7 +5572,7 @@ msgstr ""
 msgid "gnunet-helper-nat-server generated malformed address `%s'\n"
 msgstr ""
 
-#: src/nat/gnunet-service-nat_helper.c:250
+#: src/nat/gnunet-service-nat_helper.c:249
 #, fuzzy, c-format
 msgid "Failed to start %s\n"
 msgstr "Fehler beim Starten der Collection.\n"
@@ -5578,7 +5582,7 @@ msgstr "Fehler beim Starten der Collection.\n"
 msgid "`external-ip' command not found\n"
 msgstr "Kommando `%s' wurde nicht gefunden!\n"
 
-#: src/nat/gnunet-service-nat_mini.c:608
+#: src/nat/gnunet-service-nat_mini.c:607
 #, fuzzy
 msgid "`upnpc' command not found\n"
 msgstr "Kommando `%s' wurde nicht gefunden!\n"
@@ -5611,8 +5615,8 @@ msgstr ""
 msgid "Measure quality and performance of the NSE service."
 msgstr ""
 
-#: src/nse/gnunet-service-nse.c:1438
-#: src/revocation/gnunet-service-revocation.c:842 src/util/gnunet-scrypt.c:250
+#: src/nse/gnunet-service-nse.c:1443
+#: src/revocation/gnunet-service-revocation.c:834 src/util/gnunet-scrypt.c:257
 msgid "Value is too large.\n"
 msgstr ""
 
@@ -5684,7 +5688,7 @@ msgid "\tExpires: %s \t %s\n"
 msgstr ""
 
 #: src/peerinfo-tool/gnunet-peerinfo.c:292
-#: src/peerinfo-tool/plugin_rest_peerinfo.c:501
+#: src/peerinfo-tool/plugin_rest_peerinfo.c:523
 #, fuzzy, c-format
 msgid "Failure: Cannot convert address to string for peer `%s'\n"
 msgstr "Adresse des Knotens `%s' konnte nicht ermittelt werden.\n"
@@ -5764,7 +5768,7 @@ msgstr "Teste Transport(e) %s\n"
 msgid "Failed to load transport plugin for `%s'\n"
 msgstr "Anwendung `%s' konnte nicht initialisiert werden.\n"
 
-#: src/peerinfo-tool/plugin_rest_peerinfo.c:797
+#: src/peerinfo-tool/plugin_rest_peerinfo.c:809
 #, fuzzy
 msgid "Peerinfo REST API initialized\n"
 msgstr " Verbindung fehlgeschlagen\n"
@@ -5878,96 +5882,100 @@ msgstr ""
 msgid "Daemon to run to perform IP protocol translation to GNUnet"
 msgstr ""
 
-#: src/reclaim/gnunet-reclaim.c:799
+#: src/reclaim/gnunet-reclaim.c:801
 #, fuzzy, c-format
 msgid "Ego is required\n"
 msgstr "Option `%s' macht keinen Sinn ohne die Option `%s'.\n"
 
-#: src/reclaim/gnunet-reclaim.c:806
+#: src/reclaim/gnunet-reclaim.c:808
 #, c-format
 msgid "Attribute value missing!\n"
 msgstr ""
 
-#: src/reclaim/gnunet-reclaim.c:813
+#: src/reclaim/gnunet-reclaim.c:815
 #, fuzzy, c-format
 msgid "Requesting party key is required!\n"
 msgstr "Option `%s' macht keinen Sinn ohne die Option `%s'.\n"
 
-#: src/reclaim/gnunet-reclaim.c:831
+#: src/reclaim/gnunet-reclaim.c:833
 msgid "Add an attribute NAME"
 msgstr ""
 
-#: src/reclaim/gnunet-reclaim.c:836
+#: src/reclaim/gnunet-reclaim.c:838
 msgid "Delete the attribute with ID"
 msgstr ""
 
-#: src/reclaim/gnunet-reclaim.c:841
+#: src/reclaim/gnunet-reclaim.c:843
 msgid "The attribute VALUE"
 msgstr ""
 
-#: src/reclaim/gnunet-reclaim.c:846
+#: src/reclaim/gnunet-reclaim.c:848
 msgid "The EGO to use"
 msgstr ""
 
-#: src/reclaim/gnunet-reclaim.c:852
+#: src/reclaim/gnunet-reclaim.c:854
 msgid "Specify the relying party for issue"
 msgstr ""
 
-#: src/reclaim/gnunet-reclaim.c:856
+#: src/reclaim/gnunet-reclaim.c:858
 msgid "List attributes for EGO"
 msgstr ""
 
-#: src/reclaim/gnunet-reclaim.c:860
-msgid "List attestations for EGO"
+#: src/reclaim/gnunet-reclaim.c:862
+msgid "List credentials for EGO"
 msgstr ""
 
-#: src/reclaim/gnunet-reclaim.c:866
-msgid "Attestation to use for attribute"
+#: src/reclaim/gnunet-reclaim.c:868
+msgid "Credential to use for attribute"
 msgstr ""
 
-#: src/reclaim/gnunet-reclaim.c:871
-msgid "Attestation name"
+#: src/reclaim/gnunet-reclaim.c:873
+msgid "Credential name"
 msgstr ""
 
-#: src/reclaim/gnunet-reclaim.c:877
+#: src/reclaim/gnunet-reclaim.c:879
 msgid "Issue a ticket for a set of attributes separated by comma"
 msgstr ""
 
-#: src/reclaim/gnunet-reclaim.c:882
+#: src/reclaim/gnunet-reclaim.c:884
 msgid "Consume a ticket"
 msgstr ""
 
-#: src/reclaim/gnunet-reclaim.c:887
+#: src/reclaim/gnunet-reclaim.c:889
 msgid "Revoke a ticket"
 msgstr ""
 
-#: src/reclaim/gnunet-reclaim.c:892
+#: src/reclaim/gnunet-reclaim.c:894
 msgid "Type of attribute"
 msgstr ""
 
-#: src/reclaim/gnunet-reclaim.c:896
+#: src/reclaim/gnunet-reclaim.c:899
+msgid "Type of credential"
+msgstr ""
+
+#: src/reclaim/gnunet-reclaim.c:903
 msgid "List tickets of ego"
 msgstr ""
 
-#: src/reclaim/gnunet-reclaim.c:902
+#: src/reclaim/gnunet-reclaim.c:909
 msgid "Expiration interval of the attribute"
 msgstr ""
 
-#: src/reclaim/gnunet-reclaim.c:910
+#: src/reclaim/gnunet-reclaim.c:917
 msgid "re:claimID command line tool"
 msgstr ""
 
-#: src/reclaim/plugin_rest_openid_connect.c:2481
+#: src/reclaim/plugin_rest_openid_connect.c:2618
 #, fuzzy
 msgid "OpenID Connect REST API initialized\n"
 msgstr " Verbindung fehlgeschlagen\n"
 
-#: src/reclaim/plugin_rest_reclaim.c:1476
+#: src/reclaim/plugin_rest_reclaim.c:1502
 #, fuzzy
 msgid "Identity Provider REST API initialized\n"
 msgstr " Verbindung fehlgeschlagen\n"
 
-#: src/reclaim/reclaim_api.c:540
+#: src/reclaim/reclaim_api.c:545
 #, fuzzy
 msgid "failed to store record\n"
 msgstr "Zustellung der Nachricht `%s' fehlgeschlagen.\n"
@@ -6056,17 +6064,17 @@ msgstr ""
 msgid "Search string `%s' is too long!\n"
 msgstr "Dienst »%s« läuft nicht\n"
 
-#: src/rest/gnunet-rest-server.c:1051
+#: src/rest/gnunet-rest-server.c:1266
 #, fuzzy
 msgid "GNUnet REST server"
 msgstr "GNUnet Netzwerk Topologie tracen."
 
-#: src/rest/plugin_rest_config.c:402
+#: src/rest/plugin_rest_config.c:427
 #, fuzzy
 msgid "CONFIG REST API initialized\n"
 msgstr " Verbindung fehlgeschlagen\n"
 
-#: src/rest/plugin_rest_copying.c:209
+#: src/rest/plugin_rest_copying.c:211
 #, fuzzy
 msgid "COPYING REST API initialized\n"
 msgstr " Verbindung fehlgeschlagen\n"
@@ -6199,26 +6207,26 @@ msgstr ""
 msgid "# revocation messages received via set union"
 msgstr "# verschlüsselter PING Nachrichten empfangen"
 
-#: src/revocation/gnunet-service-revocation.c:470
+#: src/revocation/gnunet-service-revocation.c:469
 #, c-format
 msgid "Error computing revocation set union with %s\n"
 msgstr ""
 
-#: src/revocation/gnunet-service-revocation.c:474
+#: src/revocation/gnunet-service-revocation.c:473
 #, fuzzy
 msgid "# revocation set unions failed"
 msgstr " Verbindung fehlgeschlagen\n"
 
-#: src/revocation/gnunet-service-revocation.c:486
+#: src/revocation/gnunet-service-revocation.c:481
 #, fuzzy
 msgid "# revocation set unions completed"
 msgstr "# Klartext PONG Nachrichten empfangen"
 
-#: src/revocation/gnunet-service-revocation.c:526
+#: src/revocation/gnunet-service-revocation.c:519
 msgid "SET service crashed, terminating revocation service\n"
 msgstr ""
 
-#: src/revocation/gnunet-service-revocation.c:881
+#: src/revocation/gnunet-service-revocation.c:871
 #, fuzzy
 msgid "Could not open revocation database file!"
 msgstr "Knoten `%s' konnte nicht in der Routing Tabelle gefunden werden!\n"
@@ -6307,10 +6315,10 @@ msgstr ""
 msgid "Calculate the Vectorproduct with a GNUnet peer."
 msgstr ""
 
-#: src/scalarproduct/gnunet-service-scalarproduct_alice.c:1363
-#: src/scalarproduct/gnunet-service-scalarproduct_bob.c:1366
-#: src/scalarproduct/gnunet-service-scalarproduct-ecc_alice.c:1127
-#: src/scalarproduct/gnunet-service-scalarproduct-ecc_bob.c:1073
+#: src/scalarproduct/gnunet-service-scalarproduct_alice.c:1358
+#: src/scalarproduct/gnunet-service-scalarproduct_bob.c:1355
+#: src/scalarproduct/gnunet-service-scalarproduct-ecc_alice.c:1118
+#: src/scalarproduct/gnunet-service-scalarproduct-ecc_bob.c:1063
 #, fuzzy
 msgid "Connect to CADET failed\n"
 msgstr " Verbindung fehlgeschlagen\n"
@@ -6335,53 +6343,64 @@ msgstr ""
 msgid "also profile decryption"
 msgstr ""
 
-#: src/set/gnunet-service-set.c:1916
+#: src/set/gnunet-service-set.c:1916 src/seti/gnunet-service-seti.c:2467
+#: src/setu/gnunet-service-setu.c:3635
 #, fuzzy
 msgid "Could not connect to CADET service\n"
 msgstr "Verbindung zum %s-Dienst ist fehlgeschlagen!\n"
 
 #: src/set/gnunet-set-ibf-profiler.c:268
+#: src/setu/gnunet-setu-ibf-profiler.c:268
 #, fuzzy
 msgid "number of element in set A-B"
 msgstr "Anzahl an Durchläufen"
 
 #: src/set/gnunet-set-ibf-profiler.c:274
+#: src/setu/gnunet-setu-ibf-profiler.c:274
 #, fuzzy
 msgid "number of element in set B-A"
 msgstr "Anzahl an Durchläufen"
 
 #: src/set/gnunet-set-ibf-profiler.c:281
+#: src/setu/gnunet-setu-ibf-profiler.c:281
 msgid "number of common elements in A and B"
 msgstr ""
 
 #: src/set/gnunet-set-ibf-profiler.c:287
+#: src/setu/gnunet-setu-ibf-profiler.c:287
 msgid "hash num"
 msgstr ""
 
 #: src/set/gnunet-set-ibf-profiler.c:293
+#: src/setu/gnunet-setu-ibf-profiler.c:293
 msgid "ibf size"
 msgstr ""
 
-#: src/set/gnunet-set-profiler.c:462
+#: src/set/gnunet-set-profiler.c:462 src/setu/gnunet-setu-profiler.c:453
 msgid "use byzantine mode"
 msgstr ""
 
-#: src/set/gnunet-set-profiler.c:468
+#: src/set/gnunet-set-profiler.c:468 src/setu/gnunet-setu-profiler.c:459
 msgid "force sending full set"
 msgstr ""
 
-#: src/set/gnunet-set-profiler.c:474
+#: src/set/gnunet-set-profiler.c:474 src/setu/gnunet-setu-profiler.c:465
 msgid "number delta operation"
 msgstr ""
 
-#: src/set/gnunet-set-profiler.c:486
+#: src/set/gnunet-set-profiler.c:486 src/setu/gnunet-setu-profiler.c:477
 msgid "operation to execute"
 msgstr ""
 
-#: src/set/gnunet-set-profiler.c:492
+#: src/set/gnunet-set-profiler.c:492 src/seti/gnunet-seti-profiler.c:462
+#: src/setu/gnunet-setu-profiler.c:483
 msgid "element size"
 msgstr ""
 
+#: src/seti/gnunet-seti-profiler.c:457
+msgid "return intersection instead of delta"
+msgstr ""
+
 #: src/sq/sq.c:54
 #, c-format
 msgid "Failure to bind %u-th SQL parameter\n"
@@ -6397,12 +6416,12 @@ msgid "Failed to reset sqlite statement with error: %s\n"
 msgstr ""
 "`%s' konnte die Methode '%s%s' nicht auflösen. Ort: %s:%d. Fehler: %s\n"
 
-#: src/statistics/gnunet-service-statistics.c:318
+#: src/statistics/gnunet-service-statistics.c:319
 #, fuzzy, c-format
 msgid "Wrote %llu bytes of statistics to `%s'\n"
 msgstr "Dateien aus dem GNUnet herunterladen."
 
-#: src/statistics/gnunet-service-statistics.c:983
+#: src/statistics/gnunet-service-statistics.c:984
 #, fuzzy, c-format
 msgid "Loading %llu bytes of statistics from `%s'\n"
 msgstr "Dateien aus dem GNUnet herunterladen."
@@ -6584,7 +6603,7 @@ msgid ""
 msgstr ""
 
 #: src/testbed/gnunet-daemon-testbed-underlay.c:234 src/testing/list-keys.c:47
-#: src/testing/testing.c:284 src/util/gnunet-ecc.c:318
+#: src/testing/testing.c:278 src/util/gnunet-ecc.c:318
 #, c-format
 msgid "Incorrect hostkey file format: %s\n"
 msgstr ""
@@ -6843,57 +6862,57 @@ msgstr ""
 msgid "list COUNT number of keys"
 msgstr ""
 
-#: src/testing/testing.c:267
+#: src/testing/testing.c:261
 #, c-format
 msgid "Hostkeys file not found: %s\n"
 msgstr ""
 
-#: src/testing/testing.c:721
+#: src/testing/testing.c:714
 #, c-format
 msgid "Key number %u does not exist\n"
 msgstr ""
 
-#: src/testing/testing.c:1195
+#: src/testing/testing.c:1188
 #, c-format
 msgid ""
 "You attempted to create a testbed with more than %u hosts.  Please "
 "precompute more hostkeys first.\n"
 msgstr ""
 
-#: src/testing/testing.c:1204
+#: src/testing/testing.c:1197
 #, fuzzy, c-format
 msgid "Failed to initialize hostkey for peer %u\n"
 msgstr "SQLite Datenbank konnte nicht initialisiert werden.\n"
 
-#: src/testing/testing.c:1214
+#: src/testing/testing.c:1207
 msgid "PRIVATE_KEY option in PEER section missing in configuration\n"
 msgstr ""
 
-#: src/testing/testing.c:1227
+#: src/testing/testing.c:1220
 msgid "Failed to create configuration for peer (not enough free ports?)\n"
 msgstr ""
 
-#: src/testing/testing.c:1243
+#: src/testing/testing.c:1236
 #, fuzzy, c-format
 msgid "Cannot open hostkey file `%s': %s\n"
 msgstr "Konfigurationsdatei `%s' konnte nicht geöffnet werden.\n"
 
-#: src/testing/testing.c:1257
+#: src/testing/testing.c:1250
 #, fuzzy, c-format
 msgid "Failed to write hostkey file for peer %u: %s\n"
 msgstr "Datei wurde als `%s' gespeichert.\n"
 
-#: src/testing/testing.c:1285
+#: src/testing/testing.c:1278
 #, fuzzy, c-format
 msgid "Failed to write configuration file `%s' for peer %u: %s\n"
 msgstr "Fehler beim Speichern der Konfigurationsdatei `%s':"
 
-#: src/testing/testing.c:1392
+#: src/testing/testing.c:1384
 #, c-format
 msgid "Failed to start `%s': %s\n"
 msgstr "»%s« konnte nicht gestartet werden: %s\n"
 
-#: src/testing/testing.c:1691
+#: src/testing/testing.c:1683
 #, c-format
 msgid "Failed to load configuration from %s\n"
 msgstr "Konfiguration konnte nicht aus %s geladen werden\n"
@@ -6969,39 +6988,39 @@ msgstr "# HELLO-Meldungen empfangen"
 msgid "GNUnet topology control"
 msgstr ""
 
-#: src/transport/gnunet-communicator-tcp.c:2458
-#: src/transport/gnunet-communicator-udp.c:2825
-#: src/transport/gnunet-service-tng.c:10027
+#: src/transport/gnunet-communicator-tcp.c:3189
+#: src/transport/gnunet-communicator-udp.c:2826
+#: src/transport/gnunet-service-tng.c:10014
 #: src/transport/gnunet-service-transport.c:2624
 msgid "Transport service is lacking key configuration settings. Exiting.\n"
 msgstr ""
 
-#: src/transport/gnunet-communicator-tcp.c:2754
+#: src/transport/gnunet-communicator-tcp.c:3494
 msgid "GNUnet TCP communicator"
 msgstr ""
 
-#: src/transport/gnunet-communicator-udp.c:2897
+#: src/transport/gnunet-communicator-udp.c:2898
 msgid "GNUnet UDP communicator"
 msgstr ""
 
-#: src/transport/gnunet-communicator-unix.c:788
+#: src/transport/gnunet-communicator-unix.c:789
 #, fuzzy
 msgid ""
 "Maximum number of UNIX connections exceeded, dropping incoming message\n"
 msgstr "Maximale Anzahl der Verbindungen ist %u\n"
 
-#: src/transport/gnunet-communicator-unix.c:1015
+#: src/transport/gnunet-communicator-unix.c:1016
 #, fuzzy
 msgid "UNIX communicator is lacking key configuration settings. Exiting.\n"
 msgstr "GNUnet Konfiguration"
 
-#: src/transport/gnunet-communicator-unix.c:1060
+#: src/transport/gnunet-communicator-unix.c:1061
 #: src/transport/plugin_transport_unix.c:1383
 #, c-format
 msgid "Cannot create path to `%s'\n"
 msgstr "Pfad zu »%s« kann nicht erstellt werden\n"
 
-#: src/transport/gnunet-communicator-unix.c:1138
+#: src/transport/gnunet-communicator-unix.c:1139
 msgid "GNUnet UNIX domain socket communicator"
 msgstr ""
 
@@ -8066,7 +8085,7 @@ msgid "do daemonize (detach from terminal)"
 msgstr ""
 
 #: src/transport/tcp_service_legacy.c:1397
-#: src/transport/transport-testing2.c:1061 src/util/service.c:2072
+#: src/transport/transport-testing2.c:1116 src/util/service.c:2072
 #: src/util/service.c:2084
 #, fuzzy, c-format
 msgid "Malformed configuration file `%s', exit ...\n"
@@ -8109,7 +8128,7 @@ msgstr ""
 msgid "Invalid handle type while reading `%s'"
 msgstr "Ungültiges Befehlszeilenargument »%s«\n"
 
-#: src/util/bio.c:335 src/util/bio.c:838
+#: src/util/bio.c:335 src/util/bio.c:839
 msgid "string length"
 msgstr ""
 
@@ -8128,7 +8147,7 @@ msgstr ""
 msgid "String `%s' longer than allowed (%u > %u)"
 msgstr ""
 
-#: src/util/bio.c:398 src/util/bio.c:863 src/util/bio.c:880
+#: src/util/bio.c:398 src/util/bio.c:864 src/util/bio.c:881
 msgid "metadata length"
 msgstr ""
 
@@ -8142,25 +8161,25 @@ msgstr ""
 msgid "Failed to deserialize metadata `%s'"
 msgstr "Fehler beim Lesen der Freunde-Liste von `%s'\n"
 
-#: src/util/bio.c:667
+#: src/util/bio.c:668
 msgid "Unable to flush buffer to file"
 msgstr ""
 
-#: src/util/bio.c:729 src/util/bio.c:750
+#: src/util/bio.c:730 src/util/bio.c:751
 #, fuzzy, c-format
 msgid "Error while writing `%s' to file: %s"
 msgstr "Konfigurationsdatei `%s' konnte nicht geöffnet werden.\n"
 
-#: src/util/bio.c:731
+#: src/util/bio.c:732
 msgid "No associated file"
 msgstr ""
 
-#: src/util/bio.c:815
+#: src/util/bio.c:816
 #, fuzzy, c-format
 msgid "Invalid handle type while writing `%s'"
 msgstr "Ungültiger Parameter: `%s'\n"
 
-#: src/util/bio.c:875
+#: src/util/bio.c:876
 #, fuzzy, c-format
 msgid "Failed to serialize metadata `%s'"
 msgstr "Fehler beim Lesen der Freunde-Liste von `%s'\n"
@@ -8654,15 +8673,15 @@ msgstr ""
 msgid "No handler known for subsystem `%s'\n"
 msgstr ""
 
-#: src/util/gnunet-qr.c:358
+#: src/util/gnunet-qr.c:357
 msgid "use video-device DEVICE (default: /dev/video0"
 msgstr ""
 
-#: src/util/gnunet-qr.c:363
+#: src/util/gnunet-qr.c:362
 msgid "do not show preview windows"
 msgstr ""
 
-#: src/util/gnunet-qr.c:373
+#: src/util/gnunet-qr.c:372
 msgid "Scan a QR code using a video device and import the uri read"
 msgstr ""
 
@@ -8674,28 +8693,28 @@ msgstr ""
 msgid "Use build-in GNUnet stub resolver"
 msgstr ""
 
-#: src/util/gnunet-scrypt.c:222
+#: src/util/gnunet-scrypt.c:229
 #, fuzzy, c-format
 msgid "Loading hostkey from `%s' failed.\n"
 msgstr "Das Parsen des Hello von `%s' schlug fehl.\n"
 
-#: src/util/gnunet-scrypt.c:288
+#: src/util/gnunet-scrypt.c:295
 msgid "number of bits to require for the proof of work"
 msgstr ""
 
-#: src/util/gnunet-scrypt.c:294
+#: src/util/gnunet-scrypt.c:301
 msgid "file with private key, otherwise default is used"
 msgstr ""
 
-#: src/util/gnunet-scrypt.c:300
+#: src/util/gnunet-scrypt.c:307
 msgid "file with proof of work, otherwise default is used"
 msgstr ""
 
-#: src/util/gnunet-scrypt.c:306
+#: src/util/gnunet-scrypt.c:313
 msgid "time to wait between calculations"
 msgstr ""
 
-#: src/util/gnunet-scrypt.c:319
+#: src/util/gnunet-scrypt.c:326
 msgid "Manipulate GNUnet proof of work files"
 msgstr ""
 
@@ -8708,7 +8727,7 @@ msgstr ""
 msgid "No URI specified on command line\n"
 msgstr ""
 
-#: src/util/gnunet-uri.c:179
+#: src/util/gnunet-uri.c:178
 msgid "Perform default-actions for GNUnet URIs"
 msgstr ""
 
@@ -8722,7 +8741,7 @@ msgstr "Fehler beim Lesen von »%s«: %s\n"
 msgid "Failed to parse inbound message from helper `%s'\n"
 msgstr "Fehler beim Parsen der Gerätedaten von `%s' bei %s:%d.\n"
 
-#: src/util/helper.c:600
+#: src/util/helper.c:602
 #, fuzzy, c-format
 msgid "Error writing to `%s': %s\n"
 msgstr "Verbindung zu %u.%u.%u.%u:%u fehlgeschlagen: %s\n"
@@ -8854,116 +8873,116 @@ msgstr ""
 msgid "Attempting to proxy service `%s' to invalid port %d or hostname.\n"
 msgstr ""
 
-#: src/util/strings.c:178
+#: src/util/strings.c:179
 msgid "b"
 msgstr "b"
 
-#: src/util/strings.c:502
+#: src/util/strings.c:503
 #, c-format
 msgid "Character sets requested were `%s'->`%s'\n"
 msgstr ""
 
-#: src/util/strings.c:636
+#: src/util/strings.c:637
 msgid "Failed to expand `$HOME': environment variable `HOME' not set"
 msgstr ""
 
-#: src/util/strings.c:705
+#: src/util/strings.c:706
 msgid "µs"
 msgstr "µs"
 
-#: src/util/strings.c:709
+#: src/util/strings.c:710
 msgid "forever"
 msgstr ""
 
-#: src/util/strings.c:711
+#: src/util/strings.c:712
 msgid "0 ms"
 msgstr "0 ms"
 
-#: src/util/strings.c:715
+#: src/util/strings.c:716
 msgid "ms"
 msgstr "ms"
 
-#: src/util/strings.c:719
+#: src/util/strings.c:720
 msgid "s"
 msgstr "s"
 
-#: src/util/strings.c:723
+#: src/util/strings.c:724
 msgid "m"
 msgstr "m"
 
-#: src/util/strings.c:727
+#: src/util/strings.c:728
 msgid "h"
 msgstr "h"
 
-#: src/util/strings.c:733
+#: src/util/strings.c:734
 msgid "day"
 msgstr "Tag"
 
-#: src/util/strings.c:735
+#: src/util/strings.c:736
 msgid "days"
 msgstr "Tage"
 
-#: src/util/strings.c:763
+#: src/util/strings.c:764
 msgid "end of time"
 msgstr ""
 
-#: src/util/strings.c:1239
+#: src/util/strings.c:1240
 msgid "IPv6 address did not start with `['\n"
 msgstr "IPv6-Adresse beginnt nicht mit »[«\n"
 
-#: src/util/strings.c:1247
+#: src/util/strings.c:1248
 msgid "IPv6 address did contain ':' to separate port number\n"
 msgstr "IPv6-Adresse enthält kein »:« zur Abtrennung der Portnummer\n"
 
-#: src/util/strings.c:1254
+#: src/util/strings.c:1255
 msgid "IPv6 address did contain ']' before ':' to separate port number\n"
 msgstr "IPv6-Adresse enthält kein »]« vor »:« zur Abtrennung der Portnummer\n"
 
-#: src/util/strings.c:1262
+#: src/util/strings.c:1263
 msgid "IPv6 address did contain a valid port number after the last ':'\n"
 msgstr "IPv6-Adresse enthält keine gültige Portnummer nach dem letzten »:«\n"
 
-#: src/util/strings.c:1271
+#: src/util/strings.c:1272
 #, fuzzy, c-format
 msgid "Invalid IPv6 address `%s': %s\n"
 msgstr "Ungültige Antwort auf `%s' von `%s'\n"
 
-#: src/util/strings.c:1498 src/util/strings.c:1509
+#: src/util/strings.c:1499 src/util/strings.c:1510
 msgid "Port not in range\n"
 msgstr "Port außerhalb des Bereichs\n"
 
-#: src/util/strings.c:1518
+#: src/util/strings.c:1519
 #, c-format
 msgid "Malformed port policy `%s'\n"
 msgstr ""
 
-#: src/util/strings.c:1601 src/util/strings.c:1630 src/util/strings.c:1677
-#: src/util/strings.c:1697
+#: src/util/strings.c:1602 src/util/strings.c:1631 src/util/strings.c:1678
+#: src/util/strings.c:1698
 #, c-format
 msgid "Invalid format for IP: `%s'\n"
 msgstr "Ungültiges Format für IP: »%s«\n"
 
-#: src/util/strings.c:1655
+#: src/util/strings.c:1656
 #, c-format
 msgid "Invalid network notation ('/%d' is not legal in IPv4 CIDR)."
 msgstr "Ungültige Netzwerk-Notation ('/%d ist nicht gültig in IPv4 CIDR)."
 
-#: src/util/strings.c:1706
+#: src/util/strings.c:1707
 #, fuzzy, c-format
 msgid "Invalid format: `%s'\n"
 msgstr "Ungültiges Format für IP: `%s'\n"
 
-#: src/util/strings.c:1759
+#: src/util/strings.c:1760
 #, c-format
 msgid "Invalid network notation (does not end with ';': `%s')\n"
 msgstr "Ungültige Netzwerk-Notation (endet nicht mit »;«: »%s«)\n"
 
-#: src/util/strings.c:1809
+#: src/util/strings.c:1810
 #, fuzzy, c-format
 msgid "Wrong format `%s' for netmask\n"
 msgstr "Falsches Format `%s' für Netzmaske: %s\n"
 
-#: src/util/strings.c:1840
+#: src/util/strings.c:1841
 #, fuzzy, c-format
 msgid "Wrong format `%s' for network\n"
 msgstr "Falsches Format `%s' für Netzwerk: %s\n"
diff --git a/po/es.po b/po/es.po
index a566af4f025704a857dc0e14fb6db86e8161ce35..646ae9c81ecc56080cd92f6f5d6535c287e0de9c 100644
--- a/po/es.po
+++ b/po/es.po
@@ -8,7 +8,7 @@ msgid ""
 msgstr ""
 "Project-Id-Version: gnunet 0.9.5a\n"
 "Report-Msgid-Bugs-To: gnunet-developers@mail.gnu.org\n"
-"POT-Creation-Date: 2020-07-12 17:55+0200\n"
+"POT-Creation-Date: 2020-09-06 10:07+0200\n"
 "PO-Revision-Date: 2013-02-23 17:50+0100\n"
 "Last-Translator: Miguel Ángel Arruga Vivas <rosen644835@gmail.com>\n"
 "Language-Team: Spanish <es@li.org>\n"
@@ -18,12 +18,12 @@ msgstr ""
 "Content-Transfer-Encoding: 8bit\n"
 "Plural-Forms: nplurals=2; plural=(n != 1);\n"
 
-#: src/abd/gnunet-abd.c:397 src/namestore/gnunet-namestore.c:1302
+#: src/abd/gnunet-abd.c:397 src/namestore/gnunet-namestore.c:1303
 #, fuzzy, c-format
 msgid "Ego `%s' not known to identity service\n"
 msgstr "'%s': servicio desconocido: %s\n"
 
-#: src/abd/gnunet-abd.c:413 src/abd/gnunet-abd.c:896
+#: src/abd/gnunet-abd.c:413 src/abd/gnunet-abd.c:901
 #, fuzzy, c-format
 msgid "Issuer public key `%s' is not well-formed\n"
 msgstr "El bloque del tipo %u está mal formado\n"
@@ -35,109 +35,109 @@ msgstr "El bloque del tipo %u está mal formado\n"
 msgid "Failed to connect to namestore\n"
 msgstr "Se produjo un fallo al conectar con el almacén de nombres\n"
 
-#: src/abd/gnunet-abd.c:835 src/abd/gnunet-abd.c:886
+#: src/abd/gnunet-abd.c:840 src/abd/gnunet-abd.c:891
 #, fuzzy, c-format
 msgid "Issuer public key not well-formed\n"
 msgstr "El bloque del tipo %u está mal formado\n"
 
-#: src/abd/gnunet-abd.c:844 src/abd/gnunet-abd.c:905
+#: src/abd/gnunet-abd.c:849 src/abd/gnunet-abd.c:910
 #, fuzzy, c-format
 msgid "Failed to connect to ABD\n"
 msgstr "Se produjo un fallo al conectar con GNS\n"
 
-#: src/abd/gnunet-abd.c:850
+#: src/abd/gnunet-abd.c:855
 #, c-format
 msgid "You must provide issuer the attribute\n"
 msgstr ""
 
-#: src/abd/gnunet-abd.c:857
+#: src/abd/gnunet-abd.c:862
 #, fuzzy, c-format
 msgid "ego required\n"
 msgstr "Tipo requerido\n"
 
-#: src/abd/gnunet-abd.c:867
+#: src/abd/gnunet-abd.c:872
 #, c-format
 msgid "Subject public key needed\n"
 msgstr ""
 
-#: src/abd/gnunet-abd.c:876
+#: src/abd/gnunet-abd.c:881
 #, fuzzy, c-format
 msgid "Subject public key `%s' is not well-formed\n"
 msgstr "El bloque del tipo %u está mal formado\n"
 
-#: src/abd/gnunet-abd.c:911
+#: src/abd/gnunet-abd.c:916
 #, c-format
 msgid "You must provide issuer and subject attributes\n"
 msgstr ""
 
-#: src/abd/gnunet-abd.c:970
+#: src/abd/gnunet-abd.c:975
 #, c-format
 msgid "Please specify name to lookup, subject key and issuer key!\n"
 msgstr ""
 
-#: src/abd/gnunet-abd.c:991
+#: src/abd/gnunet-abd.c:996
 msgid "verify credential against attribute"
 msgstr ""
 
-#: src/abd/gnunet-abd.c:998
+#: src/abd/gnunet-abd.c:1003
 #, fuzzy
 msgid ""
 "The public key of the subject to lookup thecredential for, or for issuer "
 "side storage: subject and its attributes"
 msgstr "Especificar el tipo del registro a buscar"
 
-#: src/abd/gnunet-abd.c:1005
+#: src/abd/gnunet-abd.c:1010
 msgid "The private, signed delegate presented by the subject"
 msgstr ""
 
-#: src/abd/gnunet-abd.c:1012
+#: src/abd/gnunet-abd.c:1017
 #, fuzzy
 msgid "The public key of the authority to verify the credential against"
 msgstr "Especificar el tipo del registro a buscar"
 
-#: src/abd/gnunet-abd.c:1017
+#: src/abd/gnunet-abd.c:1022
 #, fuzzy
 msgid "The ego/zone name to use"
 msgstr "tamaño del mensaje"
 
-#: src/abd/gnunet-abd.c:1023
+#: src/abd/gnunet-abd.c:1028
 msgid "The issuer attribute to verify against or to issue"
 msgstr ""
 
-#: src/abd/gnunet-abd.c:1029
+#: src/abd/gnunet-abd.c:1034
 msgid ""
 "The time to live for the credential.e.g. 5m, 6h, \"1990-12-30 12:00:00\""
 msgstr ""
 
-#: src/abd/gnunet-abd.c:1034
+#: src/abd/gnunet-abd.c:1039
 msgid "collect credentials"
 msgstr ""
 
-#: src/abd/gnunet-abd.c:1039
+#: src/abd/gnunet-abd.c:1044
 msgid "Create and issue a credential issuer side."
 msgstr ""
 
-#: src/abd/gnunet-abd.c:1044
+#: src/abd/gnunet-abd.c:1049
 msgid "Issue a credential subject side."
 msgstr ""
 
-#: src/abd/gnunet-abd.c:1049
+#: src/abd/gnunet-abd.c:1054
 msgid "Create, sign and return a credential subject side."
 msgstr ""
 
-#: src/abd/gnunet-abd.c:1056
+#: src/abd/gnunet-abd.c:1061
 msgid "Import signed credentials that should be issued to a zone/ego"
 msgstr ""
 
-#: src/abd/gnunet-abd.c:1060
+#: src/abd/gnunet-abd.c:1065
 msgid "Create private record entry."
 msgstr ""
 
-#: src/abd/gnunet-abd.c:1066 src/abd/gnunet-abd.c:1072
+#: src/abd/gnunet-abd.c:1071 src/abd/gnunet-abd.c:1077
 msgid "Indicates that the collect/verify process is done via forward search."
 msgstr ""
 
-#: src/abd/gnunet-abd.c:1085
+#: src/abd/gnunet-abd.c:1090
 #, fuzzy
 msgid "GNUnet abd resolver tool"
 msgstr "Herramienta de acceso GNUnet GNS"
@@ -452,23 +452,23 @@ msgstr "Se produjo un fallo al resolver «%s»: %s\n"
 msgid "Failed to find %saddress for `%s'.\n"
 msgstr "No se encontró la dirección %s para «%s».\n"
 
-#: src/arm/gnunet-service-arm.c:933
+#: src/arm/gnunet-service-arm.c:951
 #, c-format
 msgid "Failed to start service `%s'\n"
 msgstr "Se produjo un fallo al iniciar el servicio «%s»\n"
 
-#: src/arm/gnunet-service-arm.c:944
+#: src/arm/gnunet-service-arm.c:962
 #, c-format
 msgid "Starting service `%s'\n"
 msgstr "Iniciando el servicio «%s»\n"
 
 # Miguel: ¿Alguna idea para "socket"?
-#: src/arm/gnunet-service-arm.c:1044
+#: src/arm/gnunet-service-arm.c:1062
 #, c-format
 msgid "Unable to create socket for service `%s': %s\n"
 msgstr "Imposible crear un «socket» para el servicio «%s»: %s\n"
 
-#: src/arm/gnunet-service-arm.c:1075
+#: src/arm/gnunet-service-arm.c:1093
 #, c-format
 msgid "Unable to bind listening socket for service `%s' to address `%s': %s\n"
 msgstr ""
@@ -479,44 +479,44 @@ msgstr ""
 # no es exactamente lo mismo que el texto en inglés, pero
 # es fiel a la realidad puesto que el ARM reinicia
 # las conexiones cuando se caen.
-#: src/arm/gnunet-service-arm.c:1106
+#: src/arm/gnunet-service-arm.c:1124
 #, c-format
 msgid "ARM now monitors connections to service `%s' at `%s'\n"
 msgstr "El ARM ahora gestiona las conexiones del servicio «%s» en «%s»\n"
 
-#: src/arm/gnunet-service-arm.c:1254
+#: src/arm/gnunet-service-arm.c:1272
 #, c-format
 msgid "Preparing to stop `%s'\n"
 msgstr "Preparando para parar «%s»\n"
 
-#: src/arm/gnunet-service-arm.c:1586
+#: src/arm/gnunet-service-arm.c:1604
 #, c-format
 msgid "Restarting service `%s'.\n"
 msgstr "Reiniciando el servicio «%s»\n"
 
-#: src/arm/gnunet-service-arm.c:1737
+#: src/arm/gnunet-service-arm.c:1755
 msgid "exit"
 msgstr "salida"
 
-#: src/arm/gnunet-service-arm.c:1742
+#: src/arm/gnunet-service-arm.c:1760
 msgid "signal"
 msgstr "señal"
 
-#: src/arm/gnunet-service-arm.c:1747
+#: src/arm/gnunet-service-arm.c:1765
 msgid "unknown"
 msgstr "desconocido"
 
-#: src/arm/gnunet-service-arm.c:1753
+#: src/arm/gnunet-service-arm.c:1771
 #, c-format
 msgid "Service `%s' took %s to terminate\n"
 msgstr "El servicio «%s» tardó %s en finalizar\n"
 
-#: src/arm/gnunet-service-arm.c:1780
+#: src/arm/gnunet-service-arm.c:1798
 #, fuzzy, c-format
 msgid "Service `%s' terminated normally, will restart at any time\n"
 msgstr "El servicio «%s» finalizó con estado %s/%d, se reiniciará en %llu ms\n"
 
-#: src/arm/gnunet-service-arm.c:1797
+#: src/arm/gnunet-service-arm.c:1815
 #, fuzzy, c-format
 msgid "Service `%s' terminated with status %s/%d, will restart in %s\n"
 msgstr "El servicio «%s» finalizó con estado %s/%d, se reiniciará en %llu ms\n"
@@ -877,7 +877,10 @@ msgstr "¿cuántos pares reciben un valor?"
 
 #: src/consensus/gnunet-consensus-profiler.c:543
 #: src/set/gnunet-set-profiler.c:451 src/set/gnunet-set-profiler.c:457
-#: src/set/gnunet-set-profiler.c:480
+#: src/set/gnunet-set-profiler.c:480 src/seti/gnunet-seti-profiler.c:441
+#: src/seti/gnunet-seti-profiler.c:446 src/seti/gnunet-seti-profiler.c:451
+#: src/setu/gnunet-setu-profiler.c:442 src/setu/gnunet-setu-profiler.c:448
+#: src/setu/gnunet-setu-profiler.c:471
 msgid "number of values"
 msgstr "número de valores"
 
@@ -892,7 +895,8 @@ msgid "delay until consensus starts"
 msgstr ""
 
 #: src/consensus/gnunet-consensus-profiler.c:563
-#: src/set/gnunet-set-profiler.c:498
+#: src/set/gnunet-set-profiler.c:498 src/seti/gnunet-seti-profiler.c:467
+#: src/setu/gnunet-setu-profiler.c:489
 #, fuzzy
 msgid "write statistics to file"
 msgstr "imprime el valor de las estadísticas"
@@ -1450,147 +1454,147 @@ msgstr ""
 msgid "Core service of `%s' ready.\n"
 msgstr "El servicio principal de «%4s» está listo.\n"
 
-#: src/core/gnunet-service-core_kx.c:625
+#: src/core/gnunet-service-core_kx.c:512
 msgid "# bytes encrypted"
 msgstr "# bytes cifrados"
 
-#: src/core/gnunet-service-core_kx.c:683
+#: src/core/gnunet-service-core_kx.c:570
 msgid "# bytes decrypted"
 msgstr "# bytes descifrados"
 
-#: src/core/gnunet-service-core_kx.c:780
+#: src/core/gnunet-service-core_kx.c:667
 #, fuzzy
 msgid "# PAYLOAD dropped (out of order)"
 msgstr "# bytes omitidos (fuera de secuencia)"
 
-#: src/core/gnunet-service-core_kx.c:832
+#: src/core/gnunet-service-core_kx.c:719
 msgid "# key exchanges initiated"
 msgstr "# intercambio de claves iniciados"
 
-#: src/core/gnunet-service-core_kx.c:888
+#: src/core/gnunet-service-core_kx.c:775
 msgid "# key exchanges stopped"
 msgstr "# intercambio de claves parados"
 
-#: src/core/gnunet-service-core_kx.c:920
+#: src/core/gnunet-service-core_kx.c:807
 #, fuzzy
 msgid "# PING messages transmitted"
 msgstr "# mensajes PONG creados"
 
-#: src/core/gnunet-service-core_kx.c:979
+#: src/core/gnunet-service-core_kx.c:866
 msgid "# old ephemeral keys ignored"
 msgstr ""
 
-#: src/core/gnunet-service-core_kx.c:993
+#: src/core/gnunet-service-core_kx.c:880
 #, fuzzy
 msgid "# duplicate ephemeral keys ignored"
 msgstr "# mapas de tipos recibidos"
 
-#: src/core/gnunet-service-core_kx.c:1028
+#: src/core/gnunet-service-core_kx.c:915
 #, fuzzy
 msgid "# EPHEMERAL_KEYs rejected (bad signature)"
 msgstr "# mensajes «SET_KEY» descifrados"
 
-#: src/core/gnunet-service-core_kx.c:1046
+#: src/core/gnunet-service-core_kx.c:933
 #, c-format
 msgid ""
 "EPHEMERAL_KEY from peer `%s' rejected as its validity range does not match "
 "our system time (%llu not in [%llu,%llu]).\n"
 msgstr ""
 
-#: src/core/gnunet-service-core_kx.c:1053
+#: src/core/gnunet-service-core_kx.c:940
 #, fuzzy
 msgid "# EPHEMERAL_KEY messages rejected due to time"
 msgstr "# mensajes «SET_KEY» descifrados"
 
-#: src/core/gnunet-service-core_kx.c:1071
+#: src/core/gnunet-service-core_kx.c:958
 #, fuzzy
 msgid "# valid ephemeral keys received"
 msgstr "# mapas de tipos recibidos"
 
-#: src/core/gnunet-service-core_kx.c:1180
+#: src/core/gnunet-service-core_kx.c:1067
 #: src/transport/gnunet-service-transport_validation.c:1133
 msgid "# PING messages received"
 msgstr "# mensajes PING recibidos"
 
-#: src/core/gnunet-service-core_kx.c:1190
+#: src/core/gnunet-service-core_kx.c:1077
 #, fuzzy
 msgid "# PING messages dropped (out of order)"
 msgstr "# Mensajes P2P omitidos debido a saturación de la cola"
 
-#: src/core/gnunet-service-core_kx.c:1239
+#: src/core/gnunet-service-core_kx.c:1126
 msgid "# PONG messages created"
 msgstr "# mensajes PONG creados"
 
-#: src/core/gnunet-service-core_kx.c:1264
+#: src/core/gnunet-service-core_kx.c:1151
 msgid "# sessions terminated by timeout"
 msgstr "# sesiones terminadas por plazo de expiración"
 
-#: src/core/gnunet-service-core_kx.c:1277
+#: src/core/gnunet-service-core_kx.c:1164
 msgid "# keepalive messages sent"
 msgstr "# mensajes «keepalive» enviados"
 
-#: src/core/gnunet-service-core_kx.c:1334
+#: src/core/gnunet-service-core_kx.c:1221
 #: src/transport/gnunet-service-transport_validation.c:1476
 msgid "# PONG messages received"
 msgstr "# mensajes PONG recibidos"
 
-#: src/core/gnunet-service-core_kx.c:1342
+#: src/core/gnunet-service-core_kx.c:1229
 #, fuzzy
 msgid "# PONG messages dropped (connection down)"
 msgstr "# mensajes PONG recibidos"
 
-#: src/core/gnunet-service-core_kx.c:1350
+#: src/core/gnunet-service-core_kx.c:1237
 #, fuzzy
 msgid "# PONG messages dropped (out of order)"
 msgstr "# Mensajes P2P omitidos debido a saturación de la cola"
 
-#: src/core/gnunet-service-core_kx.c:1389
+#: src/core/gnunet-service-core_kx.c:1276
 msgid "# PONG messages decrypted"
 msgstr "# mensajes PONG descifrados"
 
-#: src/core/gnunet-service-core_kx.c:1429
+#: src/core/gnunet-service-core_kx.c:1316
 msgid "# session keys confirmed via PONG"
 msgstr "# claves de sesión confirmadas vía PONG"
 
-#: src/core/gnunet-service-core_kx.c:1441
+#: src/core/gnunet-service-core_kx.c:1328
 #, fuzzy
 msgid "# timeouts prevented via PONG"
 msgstr "# bytes recibidos vía TCP"
 
-#: src/core/gnunet-service-core_kx.c:1450
+#: src/core/gnunet-service-core_kx.c:1337
 msgid "# rekey operations confirmed via PONG"
 msgstr "# operaciones de cambio de clave confirmadas vía PONG"
 
-#: src/core/gnunet-service-core_kx.c:1626
+#: src/core/gnunet-service-core_kx.c:1513
 #, fuzzy
 msgid "# DATA message dropped (out of order)"
 msgstr "# bytes omitidos (fuera de secuencia)"
 
-#: src/core/gnunet-service-core_kx.c:1637
+#: src/core/gnunet-service-core_kx.c:1524
 #, c-format
 msgid ""
 "Session to peer `%s' went down due to key expiration (should not happen)\n"
 msgstr ""
 
-#: src/core/gnunet-service-core_kx.c:1641
+#: src/core/gnunet-service-core_kx.c:1528
 #, fuzzy
 msgid "# sessions terminated by key expiration"
 msgstr "# sesiones terminadas por plazo de expiración"
 
-#: src/core/gnunet-service-core_kx.c:1719
-#: src/core/gnunet-service-core_kx.c:1746
+#: src/core/gnunet-service-core_kx.c:1606
+#: src/core/gnunet-service-core_kx.c:1633
 msgid "# bytes dropped (duplicates)"
 msgstr "# bytes omitidos (duplicados)"
 
-#: src/core/gnunet-service-core_kx.c:1732
+#: src/core/gnunet-service-core_kx.c:1619
 msgid "# bytes dropped (out of sequence)"
 msgstr "# bytes omitidos (fuera de secuencia)"
 
-#: src/core/gnunet-service-core_kx.c:1777
+#: src/core/gnunet-service-core_kx.c:1664
 msgid "# bytes dropped (ancient message)"
 msgstr "# bytes omitidos (mensaje antiguo)"
 
-#: src/core/gnunet-service-core_kx.c:1786
+#: src/core/gnunet-service-core_kx.c:1673
 msgid "# bytes of payload decrypted"
 msgstr "# bytes de «payload» descifrados"
 
@@ -3254,18 +3258,18 @@ msgstr "¡Número de comillas dobles no balanceado!\n"
 msgid "Failed to load state: %s\n"
 msgstr "Se produjo un fallo al cargar el estado: %s\n"
 
-#: src/fs/gnunet-auto-share.c:286 src/fs/gnunet-auto-share.c:295
-#: src/fs/gnunet-auto-share.c:303
+#: src/fs/gnunet-auto-share.c:287 src/fs/gnunet-auto-share.c:296
+#: src/fs/gnunet-auto-share.c:304
 #, c-format
 msgid "Failed to save state to file %s\n"
 msgstr "Se produjo un fallo al guardar el estado en el fichero %s\n"
 
-#: src/fs/gnunet-auto-share.c:400
+#: src/fs/gnunet-auto-share.c:401
 #, c-format
 msgid "Publication of `%s' done\n"
 msgstr "Publicación de «%s» finalizada\n"
 
-#: src/fs/gnunet-auto-share.c:479
+#: src/fs/gnunet-auto-share.c:480
 #, c-format
 msgid "Publishing `%s'\n"
 msgstr "Publicando «%s»\n"
@@ -4111,43 +4115,43 @@ msgstr ""
 msgid "GNUnet HTTP server to create business cards"
 msgstr ""
 
-#: src/gns/gnunet-dns2gns.c:239
+#: src/gns/gnunet-dns2gns.c:241
 msgid "Failed to pack DNS response into UDP packet!\n"
 msgstr ""
 "¡Se produjo un fallo al empaquetar una respuesta DNS en un paquete UDP!\n"
 
-#: src/gns/gnunet-dns2gns.c:442
+#: src/gns/gnunet-dns2gns.c:444
 #, c-format
 msgid "Cannot parse DNS request from %s\n"
 msgstr "No se puede procesar la petición DNS de %s\n"
 
-#: src/gns/gnunet-dns2gns.c:458
+#: src/gns/gnunet-dns2gns.c:460
 #, c-format
 msgid "Received malformed DNS request from %s\n"
 msgstr "Recibida petición DNS mal formada de %s\n"
 
-#: src/gns/gnunet-dns2gns.c:466
+#: src/gns/gnunet-dns2gns.c:468
 #, c-format
 msgid "Received unsupported DNS request from %s\n"
 msgstr "Recibida petición DNS no soportada de %s\n"
 
-#: src/gns/gnunet-dns2gns.c:627
+#: src/gns/gnunet-dns2gns.c:629
 #, fuzzy
 msgid "No DNS server specified!\n"
 msgstr "¡Ninguna palabra clave especificada!\n"
 
-#: src/gns/gnunet-dns2gns.c:776
+#: src/gns/gnunet-dns2gns.c:778
 msgid "IP of recursive DNS resolver to use (required)"
 msgstr "IP del resolvedor recursivo DNS a usar (requerido)"
 
-#: src/gns/gnunet-dns2gns.c:782
+#: src/gns/gnunet-dns2gns.c:784
 #, fuzzy
 msgid "UDP port to listen on for inbound DNS requests; default: 2853"
 msgstr ""
 "Puerto UDP en el que escuchar para peticiones DNS entrantes; predeterminado: "
 "53"
 
-#: src/gns/gnunet-dns2gns.c:799
+#: src/gns/gnunet-dns2gns.c:801
 msgid "GNUnet DNS-to-GNS proxy (a DNS server)"
 msgstr "Pasarela GNUnet DNS-a-GNS (un servidor DNS)"
 
@@ -4290,7 +4294,7 @@ msgstr "No se pudo importar el certificado %s\n"
 msgid "Failed to start HTTPS server for `%s'\n"
 msgstr "Se produjo un fallo al iniciar el servidor HTTP\n"
 
-#: src/gns/gnunet-gns-proxy.c:2922 src/rest/gnunet-rest-server.c:713
+#: src/gns/gnunet-gns-proxy.c:2922 src/rest/gnunet-rest-server.c:917
 #, fuzzy
 msgid "Failed to pass client to MHD\n"
 msgstr "Se produjo un fallo al conectar con GNS\n"
@@ -4448,7 +4452,7 @@ msgstr "No se pudo procesar la cadena de registro VPN «%s»\n"
 msgid "Unable to parse BOX record string `%s'\n"
 msgstr "No se pudo procesar la cadena de registro VPN «%s»\n"
 
-#: src/gns/plugin_rest_gns.c:445
+#: src/gns/plugin_rest_gns.c:447
 #, fuzzy
 msgid "Gns REST API initialized\n"
 msgstr "Conexión fallida\n"
@@ -4666,7 +4670,7 @@ msgid "# valid HELLOs downloaded from hostlist servers"
 msgstr "# «HELLO» válidos descargados de servidores de listas de máquinas"
 
 #: src/hostlist/gnunet-daemon-hostlist_client.c:677
-#: src/hostlist/gnunet-daemon-hostlist_client.c:1459
+#: src/hostlist/gnunet-daemon-hostlist_client.c:1460
 msgid "# advertised hostlist URIs"
 msgstr "# URI de listas de máquinas anunciadas"
 
@@ -4720,7 +4724,7 @@ msgid "# hostlist downloads initiated"
 msgstr "# descargas de listas de máquinas iniciadas"
 
 #: src/hostlist/gnunet-daemon-hostlist_client.c:1144
-#: src/hostlist/gnunet-daemon-hostlist_client.c:1726
+#: src/hostlist/gnunet-daemon-hostlist_client.c:1728
 msgid "# milliseconds between hostlist downloads"
 msgstr "# milisegundos entre descargas de listas de máquinas"
 
@@ -4752,52 +4756,52 @@ msgstr ""
 "No se pudo abrir el fichero «%s» en modo lectura para cargar las listas de "
 "máquinas: %s\n"
 
-#: src/hostlist/gnunet-daemon-hostlist_client.c:1452
+#: src/hostlist/gnunet-daemon-hostlist_client.c:1453
 #, c-format
 msgid "%u hostlist URIs loaded from file\n"
 msgstr "%u URI de listas de máquinas cargadas del fichero\n"
 
-#: src/hostlist/gnunet-daemon-hostlist_client.c:1455
+#: src/hostlist/gnunet-daemon-hostlist_client.c:1456
 msgid "# hostlist URIs read from file"
 msgstr "# URI de listas de máquinas leídas de fichero"
 
-#: src/hostlist/gnunet-daemon-hostlist_client.c:1506
+#: src/hostlist/gnunet-daemon-hostlist_client.c:1507
 #, c-format
 msgid "Could not open file `%s' for writing to save hostlists: %s\n"
 msgstr ""
 "No se pudo abrir el fichero «%s» en modo escritura para almacenar las listas "
 "de máquinas: %s\n"
 
-#: src/hostlist/gnunet-daemon-hostlist_client.c:1513
+#: src/hostlist/gnunet-daemon-hostlist_client.c:1514
 #, c-format
 msgid "Writing %u hostlist URIs to `%s'\n"
 msgstr "Escribiendo %u URI de listas de máquinas a «%s»\n"
 
-#: src/hostlist/gnunet-daemon-hostlist_client.c:1545
-#: src/hostlist/gnunet-daemon-hostlist_client.c:1564
+#: src/hostlist/gnunet-daemon-hostlist_client.c:1547
+#: src/hostlist/gnunet-daemon-hostlist_client.c:1566
 #, c-format
 msgid "Error writing hostlist URIs to file `%s'\n"
 msgstr "Error escribiendo URI de listas de máquinas al fichero «%s»\n"
 
-#: src/hostlist/gnunet-daemon-hostlist_client.c:1558
+#: src/hostlist/gnunet-daemon-hostlist_client.c:1560
 msgid "# hostlist URIs written to file"
 msgstr "# URI de listas de máquinas escritas a fichero"
 
-#: src/hostlist/gnunet-daemon-hostlist_client.c:1655
+#: src/hostlist/gnunet-daemon-hostlist_client.c:1657
 #: src/transport/plugin_transport_http_client.c:2301
 #, c-format
 msgid "Invalid proxy type: `%s', disabling proxy! Check configuration!\n"
 msgstr ""
 
-#: src/hostlist/gnunet-daemon-hostlist_client.c:1684
+#: src/hostlist/gnunet-daemon-hostlist_client.c:1686
 msgid "Learning is enabled on this peer\n"
 msgstr "El aprendizaje está habilitado en este par\n"
 
-#: src/hostlist/gnunet-daemon-hostlist_client.c:1697
+#: src/hostlist/gnunet-daemon-hostlist_client.c:1699
 msgid "Learning is not enabled on this peer\n"
 msgstr "El aprendizaje no está habilitado en este par\n"
 
-#: src/hostlist/gnunet-daemon-hostlist_client.c:1711
+#: src/hostlist/gnunet-daemon-hostlist_client.c:1713
 #, c-format
 msgid ""
 "Since learning is not enabled on this peer, hostlist file `%s' was removed\n"
@@ -4930,31 +4934,31 @@ msgstr "Se produjo un fallo al crear la página para «%s»\n"
 msgid "Failed to set default ego: %s\n"
 msgstr "Se produjo un fallo al crear la página para «%s»\n"
 
-#: src/identity/gnunet-identity.c:445
+#: src/identity/gnunet-identity.c:446
 msgid "create ego NAME"
 msgstr ""
 
-#: src/identity/gnunet-identity.c:450
+#: src/identity/gnunet-identity.c:451
 #, fuzzy
 msgid "delete ego NAME "
 msgstr "borrar un nombre de espacio de nombres (NAME)"
 
-#: src/identity/gnunet-identity.c:455
+#: src/identity/gnunet-identity.c:457
 msgid ""
 "set the private key for the identity to PRIVATE_KEY (use together with -C)"
 msgstr ""
 
-#: src/identity/gnunet-identity.c:459
+#: src/identity/gnunet-identity.c:461
 #, fuzzy
 msgid "display all egos"
 msgstr "mostrar registros"
 
-#: src/identity/gnunet-identity.c:463
+#: src/identity/gnunet-identity.c:465
 #, fuzzy
 msgid "reduce output"
 msgstr "Sin salida innecesaria"
 
-#: src/identity/gnunet-identity.c:470
+#: src/identity/gnunet-identity.c:472
 msgid ""
 "set default identity to NAME for a subsystem SUBSYSTEM (use together with -"
 "s) or restrict results to NAME (use together with -d)"
@@ -4962,21 +4966,21 @@ msgstr ""
 
 # Miguel: Aquí he dejado monitorización porque esto es
 # del servicio de traducción de direcciones.
-#: src/identity/gnunet-identity.c:474
+#: src/identity/gnunet-identity.c:476
 #, fuzzy
 msgid "run in monitor mode egos"
 msgstr "modo de monitorización"
 
-#: src/identity/gnunet-identity.c:478
+#: src/identity/gnunet-identity.c:480
 msgid "display private keys as well"
 msgstr ""
 
-#: src/identity/gnunet-identity.c:485
+#: src/identity/gnunet-identity.c:487
 msgid ""
 "set default identity to EGO for a subsystem SUBSYSTEM (use together with -e)"
 msgstr ""
 
-#: src/identity/gnunet-identity.c:500
+#: src/identity/gnunet-identity.c:502
 msgid "Maintain egos"
 msgstr ""
 
@@ -5029,7 +5033,7 @@ msgstr "Se produjo un fallo al borrar el fichero de configuración %s\n"
 msgid "Failed to create directory `%s' for storing egos\n"
 msgstr "Se produjo un fallo al leer el directorio «%s»\n"
 
-#: src/identity/plugin_rest_identity.c:1406
+#: src/identity/plugin_rest_identity.c:1384
 #, fuzzy
 msgid "Identity REST API initialized\n"
 msgstr "Conexión fallida\n"
@@ -5079,7 +5083,7 @@ msgstr "Parámetro no válido «%s»\n"
 msgid "You must specify a name\n"
 msgstr "¡Debes especificar un receptor!\n"
 
-#: src/namecache/gnunet-namecache.c:214 src/namestore/gnunet-namestore.c:1639
+#: src/namecache/gnunet-namecache.c:214 src/namestore/gnunet-namestore.c:1640
 msgid "name of the record to add/delete/display"
 msgstr "nombre del registro a añadir/borrar/mostrar"
 
@@ -5088,7 +5092,7 @@ msgstr "nombre del registro a añadir/borrar/mostrar"
 msgid "specifies the public key of the zone to look in"
 msgstr "Especificar el tipo del registro a buscar"
 
-#: src/namecache/gnunet-namecache.c:233 src/namestore/gnunet-namestore.c:1700
+#: src/namecache/gnunet-namecache.c:233 src/namestore/gnunet-namestore.c:1701
 msgid "GNUnet zone manipulation tool"
 msgstr "Herramienta de manipulación de zona de GNUnet"
 
@@ -5198,10 +5202,10 @@ msgstr "Se produjo un fallo al procesar la petición DNS.  Omitiendo.\n"
 msgid "No options given\n"
 msgstr "No se han proporcionado opciones\n"
 
-#: src/namestore/gnunet-namestore.c:1014 src/namestore/gnunet-namestore.c:1065
-#: src/namestore/gnunet-namestore.c:1075 src/namestore/gnunet-namestore.c:1104
-#: src/namestore/gnunet-namestore.c:1125 src/namestore/gnunet-namestore.c:1152
-#: src/namestore/gnunet-namestore.c:1228
+#: src/namestore/gnunet-namestore.c:1014 src/namestore/gnunet-namestore.c:1066
+#: src/namestore/gnunet-namestore.c:1076 src/namestore/gnunet-namestore.c:1105
+#: src/namestore/gnunet-namestore.c:1126 src/namestore/gnunet-namestore.c:1153
+#: src/namestore/gnunet-namestore.c:1229
 #, c-format
 msgid "Missing option `%s' for operation `%s'\n"
 msgstr "Falta la opción «%s» para la operación «%s»\n"
@@ -5215,53 +5219,53 @@ msgstr ""
 msgid "Invalid nick `%s'\n"
 msgstr "URI no válida: «%s»\n"
 
-#: src/namestore/gnunet-namestore.c:1067 src/namestore/gnunet-namestore.c:1077
-#: src/namestore/gnunet-namestore.c:1106 src/namestore/gnunet-namestore.c:1127
-#: src/namestore/gnunet-namestore.c:1230
+#: src/namestore/gnunet-namestore.c:1068 src/namestore/gnunet-namestore.c:1078
+#: src/namestore/gnunet-namestore.c:1107 src/namestore/gnunet-namestore.c:1128
+#: src/namestore/gnunet-namestore.c:1231
 msgid "add"
 msgstr "añadir"
 
-#: src/namestore/gnunet-namestore.c:1085
+#: src/namestore/gnunet-namestore.c:1086
 #, c-format
 msgid "Unsupported type `%s'\n"
 msgstr "Tipo no soportado «%s»\n"
 
-#: src/namestore/gnunet-namestore.c:1095
+#: src/namestore/gnunet-namestore.c:1096
 #, c-format
 msgid "For DNS record types `SRV', `TLSA' and `OPENPGPKEY'"
 msgstr ""
 
-#: src/namestore/gnunet-namestore.c:1115
+#: src/namestore/gnunet-namestore.c:1116
 #, c-format
 msgid "Value `%s' invalid for record type `%s'\n"
 msgstr "Valor «%s» no válido para el tipo de registro «%s»\n"
 
-#: src/namestore/gnunet-namestore.c:1134 src/namestore/gnunet-namestore.c:1237
+#: src/namestore/gnunet-namestore.c:1135 src/namestore/gnunet-namestore.c:1238
 #, c-format
 msgid "Invalid time format `%s'\n"
 msgstr "Formato de tiempo no válido «%s»\n"
 
-#: src/namestore/gnunet-namestore.c:1154
+#: src/namestore/gnunet-namestore.c:1155
 msgid "del"
 msgstr "borrar"
 
-#: src/namestore/gnunet-namestore.c:1197
+#: src/namestore/gnunet-namestore.c:1198
 #, fuzzy, c-format
 msgid "Invalid public key for reverse lookup `%s'\n"
 msgstr "Parámetro no válido «%s»\n"
 
-#: src/namestore/gnunet-namestore.c:1220
+#: src/namestore/gnunet-namestore.c:1221
 #: src/peerinfo-tool/gnunet-peerinfo.c:736
 #, c-format
 msgid "Invalid URI `%s'\n"
 msgstr "URI no válida: «%s»\n"
 
-#: src/namestore/gnunet-namestore.c:1290
+#: src/namestore/gnunet-namestore.c:1291
 #, c-format
 msgid "Label `%s' contains `.' which is not allowed\n"
 msgstr ""
 
-#: src/namestore/gnunet-namestore.c:1340
+#: src/namestore/gnunet-namestore.c:1341
 #, c-format
 msgid ""
 "No default identity configured for `namestore' subsystem\n"
@@ -5269,104 +5273,104 @@ msgid ""
 "Run gnunet-identity -d to get a list of choices for $NAME\n"
 msgstr ""
 
-#: src/namestore/gnunet-namestore.c:1405
+#: src/namestore/gnunet-namestore.c:1406
 #, fuzzy, c-format
 msgid "Superfluous command line arguments (starting with `%s') ignored\n"
 msgstr "Argumentos superfluos (ignorados).\n"
 
-#: src/namestore/gnunet-namestore.c:1434
+#: src/namestore/gnunet-namestore.c:1435
 #, fuzzy, c-format
 msgid "Cannot connect to identity service\n"
 msgstr "¡No se pudo conectar al servicio %s!\n"
 
-#: src/namestore/gnunet-namestore.c:1481
+#: src/namestore/gnunet-namestore.c:1482
 msgid "Empty record line argument is not allowed.\n"
 msgstr ""
 
-#: src/namestore/gnunet-namestore.c:1493
+#: src/namestore/gnunet-namestore.c:1494
 #, c-format
 msgid "Invalid expiration time `%s' (must be without unit)\n"
 msgstr ""
 
-#: src/namestore/gnunet-namestore.c:1505 src/namestore/gnunet-namestore.c:1521
-#: src/namestore/gnunet-namestore.c:1538
+#: src/namestore/gnunet-namestore.c:1506 src/namestore/gnunet-namestore.c:1522
+#: src/namestore/gnunet-namestore.c:1539
 #, fuzzy, c-format
 msgid "Missing entries in record line `%s'.\n"
 msgstr "Se produjo un fallo al cargar el módulo del transporte para «%s»\n"
 
-#: src/namestore/gnunet-namestore.c:1513
+#: src/namestore/gnunet-namestore.c:1514
 #, fuzzy, c-format
 msgid "Unknown record type `%s'\n"
 msgstr "Comando desconocido «%s»\n"
 
-#: src/namestore/gnunet-namestore.c:1551
+#: src/namestore/gnunet-namestore.c:1552
 #, fuzzy, c-format
 msgid "Invalid record data for type %s: `%s'.\n"
 msgstr "Formato no válido para la IP: «%s»\n"
 
-#: src/namestore/gnunet-namestore.c:1608
+#: src/namestore/gnunet-namestore.c:1609
 msgid "add record"
 msgstr "añadir registro"
 
-#: src/namestore/gnunet-namestore.c:1611
+#: src/namestore/gnunet-namestore.c:1612
 msgid "delete record"
 msgstr "borrar registro"
 
-#: src/namestore/gnunet-namestore.c:1615
+#: src/namestore/gnunet-namestore.c:1616
 msgid "display records"
 msgstr "mostrar registros"
 
-#: src/namestore/gnunet-namestore.c:1622
+#: src/namestore/gnunet-namestore.c:1623
 msgid ""
 "expiration time for record to use (for adding only), \"never\" is possible"
 msgstr ""
 "tiempo de expiración del registro a usar (únicamente para añadir), nunca "
 "(\"never\") es posible"
 
-#: src/namestore/gnunet-namestore.c:1628
+#: src/namestore/gnunet-namestore.c:1629
 #, fuzzy
 msgid "set the desired nick name for the zone"
 msgstr "establece el nivel LEVEL deseado de replicación"
 
-#: src/namestore/gnunet-namestore.c:1633
+#: src/namestore/gnunet-namestore.c:1634
 #, fuzzy
 msgid "monitor changes in the namestore"
 msgstr "¡Se produjo un fallo al conectar con el almacén de nombres!\n"
 
-#: src/namestore/gnunet-namestore.c:1645
+#: src/namestore/gnunet-namestore.c:1646
 #, fuzzy
 msgid "determine our name for the given PKEY"
 msgstr "establece las preferencias para el par dado"
 
-#: src/namestore/gnunet-namestore.c:1652
+#: src/namestore/gnunet-namestore.c:1653
 msgid ""
 "set record set to values given by (possibly multiple) RECORDLINES; can be "
 "specified multiple times"
 msgstr ""
 
-#: src/namestore/gnunet-namestore.c:1658
+#: src/namestore/gnunet-namestore.c:1659
 msgid "type of the record to add/delete/display"
 msgstr "tipo del registro a añadir/borrar/mostrar"
 
-#: src/namestore/gnunet-namestore.c:1663
+#: src/namestore/gnunet-namestore.c:1664
 msgid "URI to import into our zone"
 msgstr "URI a importar a nuestra zona"
 
-#: src/namestore/gnunet-namestore.c:1669
+#: src/namestore/gnunet-namestore.c:1670
 msgid "value of the record to add/delete"
 msgstr "valor del registro a añadir/borrar"
 
-#: src/namestore/gnunet-namestore.c:1673
+#: src/namestore/gnunet-namestore.c:1674
 msgid "create or list public record"
 msgstr "crear o listar registros públicos"
 
-#: src/namestore/gnunet-namestore.c:1679
+#: src/namestore/gnunet-namestore.c:1680
 msgid ""
 "create shadow record (only valid if all other records of the same type have "
 "expired"
 msgstr ""
 
-#: src/namestore/gnunet-namestore.c:1685
+#: src/namestore/gnunet-namestore.c:1686
 #, fuzzy
 msgid "name of the ego controlling the zone"
 msgstr "nombre de la sección a la que acceder"
@@ -5469,7 +5473,7 @@ msgstr ""
 msgid "Flat file database running\n"
 msgstr "Base de datos de plantilla ejecutándose\n"
 
-#: src/namestore/plugin_rest_namestore.c:1093
+#: src/namestore/plugin_rest_namestore.c:1103
 #, fuzzy
 msgid "Namestore REST API initialized\n"
 msgstr "Conexión fallida\n"
@@ -5756,7 +5760,7 @@ msgstr ""
 msgid "gnunet-helper-nat-server generated malformed address `%s'\n"
 msgstr "«gnunet-helper-nat-server» generó la dirección mal formada «%s»\n"
 
-#: src/nat/gnunet-service-nat_helper.c:250
+#: src/nat/gnunet-service-nat_helper.c:249
 #, c-format
 msgid "Failed to start %s\n"
 msgstr "Se produjo un fallo al arrancar %s\n"
@@ -5765,7 +5769,7 @@ msgstr "Se produjo un fallo al arrancar %s\n"
 msgid "`external-ip' command not found\n"
 msgstr "comando «external-ip» no encontrado\n"
 
-#: src/nat/gnunet-service-nat_mini.c:608
+#: src/nat/gnunet-service-nat_mini.c:607
 msgid "`upnpc' command not found\n"
 msgstr "comando «upnpc» no encontrado\n"
 
@@ -5799,8 +5803,8 @@ msgstr "retraso entre rondas"
 msgid "Measure quality and performance of the NSE service."
 msgstr "Medir la calidad y rendimiento del servicio NSE."
 
-#: src/nse/gnunet-service-nse.c:1438
-#: src/revocation/gnunet-service-revocation.c:842 src/util/gnunet-scrypt.c:250
+#: src/nse/gnunet-service-nse.c:1443
+#: src/revocation/gnunet-service-revocation.c:834 src/util/gnunet-scrypt.c:257
 msgid "Value is too large.\n"
 msgstr ""
 
@@ -5874,7 +5878,7 @@ msgid "\tExpires: %s \t %s\n"
 msgstr ""
 
 #: src/peerinfo-tool/gnunet-peerinfo.c:292
-#: src/peerinfo-tool/plugin_rest_peerinfo.c:501
+#: src/peerinfo-tool/plugin_rest_peerinfo.c:523
 #, fuzzy, c-format
 msgid "Failure: Cannot convert address to string for peer `%s'\n"
 msgstr "Se produjo un fallo al resolver la dirección para el par «%s»\n"
@@ -5953,7 +5957,7 @@ msgstr "Cargando el módulo de transporte «%s»\n"
 msgid "Failed to load transport plugin for `%s'\n"
 msgstr "Se produjo un fallo al cargar el módulo del transporte para «%s»\n"
 
-#: src/peerinfo-tool/plugin_rest_peerinfo.c:797
+#: src/peerinfo-tool/plugin_rest_peerinfo.c:809
 #, fuzzy
 msgid "Peerinfo REST API initialized\n"
 msgstr "Conexión fallida\n"
@@ -6062,97 +6066,101 @@ msgid "Daemon to run to perform IP protocol translation to GNUnet"
 msgstr ""
 "Demonio a ejecutar para realizar la traducción de protocolo IP a GNUnet"
 
-#: src/reclaim/gnunet-reclaim.c:799
+#: src/reclaim/gnunet-reclaim.c:801
 #, fuzzy, c-format
 msgid "Ego is required\n"
 msgstr "Las opción «%s» o «%s» es necesaria.\n"
 
-#: src/reclaim/gnunet-reclaim.c:806
+#: src/reclaim/gnunet-reclaim.c:808
 #, c-format
 msgid "Attribute value missing!\n"
 msgstr ""
 
-#: src/reclaim/gnunet-reclaim.c:813
+#: src/reclaim/gnunet-reclaim.c:815
 #, fuzzy, c-format
 msgid "Requesting party key is required!\n"
 msgstr "el parámetro --section es necesario\n"
 
-#: src/reclaim/gnunet-reclaim.c:831
+#: src/reclaim/gnunet-reclaim.c:833
 msgid "Add an attribute NAME"
 msgstr ""
 
-#: src/reclaim/gnunet-reclaim.c:836
+#: src/reclaim/gnunet-reclaim.c:838
 msgid "Delete the attribute with ID"
 msgstr ""
 
-#: src/reclaim/gnunet-reclaim.c:841
+#: src/reclaim/gnunet-reclaim.c:843
 msgid "The attribute VALUE"
 msgstr ""
 
-#: src/reclaim/gnunet-reclaim.c:846
+#: src/reclaim/gnunet-reclaim.c:848
 #, fuzzy
 msgid "The EGO to use"
 msgstr "tamaño del mensaje"
 
-#: src/reclaim/gnunet-reclaim.c:852
+#: src/reclaim/gnunet-reclaim.c:854
 msgid "Specify the relying party for issue"
 msgstr ""
 
-#: src/reclaim/gnunet-reclaim.c:856
+#: src/reclaim/gnunet-reclaim.c:858
 msgid "List attributes for EGO"
 msgstr ""
 
-#: src/reclaim/gnunet-reclaim.c:860
-msgid "List attestations for EGO"
+#: src/reclaim/gnunet-reclaim.c:862
+msgid "List credentials for EGO"
 msgstr ""
 
-#: src/reclaim/gnunet-reclaim.c:866
-msgid "Attestation to use for attribute"
+#: src/reclaim/gnunet-reclaim.c:868
+msgid "Credential to use for attribute"
 msgstr ""
 
-#: src/reclaim/gnunet-reclaim.c:871
-msgid "Attestation name"
+#: src/reclaim/gnunet-reclaim.c:873
+msgid "Credential name"
 msgstr ""
 
-#: src/reclaim/gnunet-reclaim.c:877
+#: src/reclaim/gnunet-reclaim.c:879
 msgid "Issue a ticket for a set of attributes separated by comma"
 msgstr ""
 
-#: src/reclaim/gnunet-reclaim.c:882
+#: src/reclaim/gnunet-reclaim.c:884
 msgid "Consume a ticket"
 msgstr ""
 
-#: src/reclaim/gnunet-reclaim.c:887
+#: src/reclaim/gnunet-reclaim.c:889
 msgid "Revoke a ticket"
 msgstr ""
 
-#: src/reclaim/gnunet-reclaim.c:892
+#: src/reclaim/gnunet-reclaim.c:894
 msgid "Type of attribute"
 msgstr ""
 
-#: src/reclaim/gnunet-reclaim.c:896
+#: src/reclaim/gnunet-reclaim.c:899
+msgid "Type of credential"
+msgstr ""
+
+#: src/reclaim/gnunet-reclaim.c:903
 msgid "List tickets of ego"
 msgstr ""
 
-#: src/reclaim/gnunet-reclaim.c:902
+#: src/reclaim/gnunet-reclaim.c:909
 msgid "Expiration interval of the attribute"
 msgstr ""
 
-#: src/reclaim/gnunet-reclaim.c:910
+#: src/reclaim/gnunet-reclaim.c:917
 msgid "re:claimID command line tool"
 msgstr ""
 
-#: src/reclaim/plugin_rest_openid_connect.c:2481
+#: src/reclaim/plugin_rest_openid_connect.c:2618
 #, fuzzy
 msgid "OpenID Connect REST API initialized\n"
 msgstr "Conexión fallida\n"
 
-#: src/reclaim/plugin_rest_reclaim.c:1476
+#: src/reclaim/plugin_rest_reclaim.c:1502
 #, fuzzy
 msgid "Identity Provider REST API initialized\n"
 msgstr "Conexión fallida\n"
 
-#: src/reclaim/reclaim_api.c:540
+#: src/reclaim/reclaim_api.c:545
 #, fuzzy
 msgid "failed to store record\n"
 msgstr "El almacén de nombres no pudo añadir el registro\n"
@@ -6252,17 +6260,17 @@ msgstr "El servicio «%s» no está ejecutandose\n"
 msgid "Search string `%s' is too long!\n"
 msgstr "El servicio «%s» no está ejecutandose\n"
 
-#: src/rest/gnunet-rest-server.c:1051
+#: src/rest/gnunet-rest-server.c:1266
 #, fuzzy
 msgid "GNUnet REST server"
 msgstr "Herramienta de acceso GNUnet GNS"
 
-#: src/rest/plugin_rest_config.c:402
+#: src/rest/plugin_rest_config.c:427
 #, fuzzy
 msgid "CONFIG REST API initialized\n"
 msgstr "Conexión fallida\n"
 
-#: src/rest/plugin_rest_copying.c:209
+#: src/rest/plugin_rest_copying.c:211
 #, fuzzy
 msgid "COPYING REST API initialized\n"
 msgstr "Conexión fallida\n"
@@ -6401,26 +6409,26 @@ msgstr "Opciones de paquete IPv4 recibidas.  Ignoradas.\n"
 msgid "# revocation messages received via set union"
 msgstr "# mensajes «DATA» recibidos vía WLAN"
 
-#: src/revocation/gnunet-service-revocation.c:470
+#: src/revocation/gnunet-service-revocation.c:469
 #, c-format
 msgid "Error computing revocation set union with %s\n"
 msgstr ""
 
-#: src/revocation/gnunet-service-revocation.c:474
+#: src/revocation/gnunet-service-revocation.c:473
 #, fuzzy
 msgid "# revocation set unions failed"
 msgstr "# sesiones wlan creadas"
 
-#: src/revocation/gnunet-service-revocation.c:486
+#: src/revocation/gnunet-service-revocation.c:481
 #, fuzzy
 msgid "# revocation set unions completed"
 msgstr "# transmisiones de fragmentos completadas"
 
-#: src/revocation/gnunet-service-revocation.c:526
+#: src/revocation/gnunet-service-revocation.c:519
 msgid "SET service crashed, terminating revocation service\n"
 msgstr ""
 
-#: src/revocation/gnunet-service-revocation.c:881
+#: src/revocation/gnunet-service-revocation.c:871
 #, fuzzy
 msgid "Could not open revocation database file!"
 msgstr "No se pudo conectar con el almacén de datos."
@@ -6513,10 +6521,10 @@ msgstr ""
 msgid "Calculate the Vectorproduct with a GNUnet peer."
 msgstr ""
 
-#: src/scalarproduct/gnunet-service-scalarproduct_alice.c:1363
-#: src/scalarproduct/gnunet-service-scalarproduct_bob.c:1366
-#: src/scalarproduct/gnunet-service-scalarproduct-ecc_alice.c:1127
-#: src/scalarproduct/gnunet-service-scalarproduct-ecc_bob.c:1073
+#: src/scalarproduct/gnunet-service-scalarproduct_alice.c:1358
+#: src/scalarproduct/gnunet-service-scalarproduct_bob.c:1355
+#: src/scalarproduct/gnunet-service-scalarproduct-ecc_alice.c:1118
+#: src/scalarproduct/gnunet-service-scalarproduct-ecc_bob.c:1063
 #, fuzzy
 msgid "Connect to CADET failed\n"
 msgstr "Conexión fallida (¿bug?)\n"
@@ -6541,54 +6549,65 @@ msgstr ""
 msgid "also profile decryption"
 msgstr ""
 
-#: src/set/gnunet-service-set.c:1916
+#: src/set/gnunet-service-set.c:1916 src/seti/gnunet-service-seti.c:2467
+#: src/setu/gnunet-service-setu.c:3635
 #, fuzzy
 msgid "Could not connect to CADET service\n"
 msgstr "¡No se pudo conectar al servicio %s!\n"
 
 # Miguel: Conjunto resta.
 #: src/set/gnunet-set-ibf-profiler.c:268
+#: src/setu/gnunet-setu-ibf-profiler.c:268
 msgid "number of element in set A-B"
 msgstr "número de elementos en el conjunto A-B"
 
 #: src/set/gnunet-set-ibf-profiler.c:274
+#: src/setu/gnunet-setu-ibf-profiler.c:274
 msgid "number of element in set B-A"
 msgstr "número de elementos en el conjunto B-A"
 
 # Miguel: Conjunto unión.
 #: src/set/gnunet-set-ibf-profiler.c:281
+#: src/setu/gnunet-setu-ibf-profiler.c:281
 msgid "number of common elements in A and B"
 msgstr "número de elementos comunes en A y B"
 
 # Miguel: "hash" me tiene un poco frito. ¿Existe alguna traducción buena?
 #: src/set/gnunet-set-ibf-profiler.c:287
+#: src/setu/gnunet-setu-ibf-profiler.c:287
 msgid "hash num"
 msgstr "número de hash"
 
 #: src/set/gnunet-set-ibf-profiler.c:293
+#: src/setu/gnunet-setu-ibf-profiler.c:293
 msgid "ibf size"
 msgstr "tamaño ibf"
 
-#: src/set/gnunet-set-profiler.c:462
+#: src/set/gnunet-set-profiler.c:462 src/setu/gnunet-setu-profiler.c:453
 msgid "use byzantine mode"
 msgstr ""
 
-#: src/set/gnunet-set-profiler.c:468
+#: src/set/gnunet-set-profiler.c:468 src/setu/gnunet-setu-profiler.c:459
 msgid "force sending full set"
 msgstr ""
 
-#: src/set/gnunet-set-profiler.c:474
+#: src/set/gnunet-set-profiler.c:474 src/setu/gnunet-setu-profiler.c:465
 msgid "number delta operation"
 msgstr ""
 
-#: src/set/gnunet-set-profiler.c:486
+#: src/set/gnunet-set-profiler.c:486 src/setu/gnunet-setu-profiler.c:477
 msgid "operation to execute"
 msgstr ""
 
-#: src/set/gnunet-set-profiler.c:492
+#: src/set/gnunet-set-profiler.c:492 src/seti/gnunet-seti-profiler.c:462
+#: src/setu/gnunet-setu-profiler.c:483
 msgid "element size"
 msgstr ""
 
+#: src/seti/gnunet-seti-profiler.c:457
+msgid "return intersection instead of delta"
+msgstr ""
+
 #: src/sq/sq.c:54
 #, c-format
 msgid "Failure to bind %u-th SQL parameter\n"
@@ -6603,12 +6622,12 @@ msgstr ""
 msgid "Failed to reset sqlite statement with error: %s\n"
 msgstr "«%s» falló al resolver el método «%s» con error: %s\n"
 
-#: src/statistics/gnunet-service-statistics.c:318
+#: src/statistics/gnunet-service-statistics.c:319
 #, c-format
 msgid "Wrote %llu bytes of statistics to `%s'\n"
 msgstr "Escritos %llu bytes de estadísticas a «%s»\n"
 
-#: src/statistics/gnunet-service-statistics.c:983
+#: src/statistics/gnunet-service-statistics.c:984
 #, c-format
 msgid "Loading %llu bytes of statistics from `%s'\n"
 msgstr "Cargando %llu bytes de estadísticas de «%s»\n"
@@ -6791,7 +6810,7 @@ msgid ""
 msgstr ""
 
 #: src/testbed/gnunet-daemon-testbed-underlay.c:234 src/testing/list-keys.c:47
-#: src/testing/testing.c:284 src/util/gnunet-ecc.c:318
+#: src/testing/testing.c:278 src/util/gnunet-ecc.c:318
 #, c-format
 msgid "Incorrect hostkey file format: %s\n"
 msgstr "El fichero de máquinas no tiene el formato correcto: %s\n"
@@ -7061,19 +7080,19 @@ msgstr ""
 msgid "list COUNT number of keys"
 msgstr "crea «COUNT» número de pares"
 
-#: src/testing/testing.c:267
+#: src/testing/testing.c:261
 #, c-format
 msgid "Hostkeys file not found: %s\n"
 msgstr "El fichero de máquinas no fue encontrado: %s\n"
 
-#: src/testing/testing.c:721
+#: src/testing/testing.c:714
 #, c-format
 msgid "Key number %u does not exist\n"
 msgstr "El número de clave %u no existe\n"
 
 # Miguel: "testbed" lo he traducido como batería de pruebas, pero
 # no es una traducción muy literal.
-#: src/testing/testing.c:1195
+#: src/testing/testing.c:1188
 #, c-format
 msgid ""
 "You attempted to create a testbed with more than %u hosts.  Please "
@@ -7082,47 +7101,47 @@ msgstr ""
 "Se ha intentado crear una batería de pruebas con más de %u máquinas.  Por "
 "favor, pre-compute más claves de máquinas primero.\n"
 
-#: src/testing/testing.c:1204
+#: src/testing/testing.c:1197
 #, c-format
 msgid "Failed to initialize hostkey for peer %u\n"
 msgstr ""
 "Se produjo un fallo al inicializar la clave de la máquina desde el par %u\n"
 
-#: src/testing/testing.c:1214
+#: src/testing/testing.c:1207
 #, fuzzy
 msgid "PRIVATE_KEY option in PEER section missing in configuration\n"
 msgstr "¡Falta la opción «%s» en la sección «%s» de la configuración!\n"
 
-#: src/testing/testing.c:1227
+#: src/testing/testing.c:1220
 msgid "Failed to create configuration for peer (not enough free ports?)\n"
 msgstr ""
 "Se produjo un fallo al crear la configuración para el par (¿no hay "
 "suficientes puertos libres?)\n"
 
-#: src/testing/testing.c:1243
+#: src/testing/testing.c:1236
 #, fuzzy, c-format
 msgid "Cannot open hostkey file `%s': %s\n"
 msgstr "No se pudo abrir el fichero de claves de máquina: %s\n"
 
-#: src/testing/testing.c:1257
+#: src/testing/testing.c:1250
 #, c-format
 msgid "Failed to write hostkey file for peer %u: %s\n"
 msgstr ""
 "Se produjo un fallo al escribir la clave de la máquina para el par %u: %s\n"
 
-#: src/testing/testing.c:1285
+#: src/testing/testing.c:1278
 #, c-format
 msgid "Failed to write configuration file `%s' for peer %u: %s\n"
 msgstr ""
 "Se produjo un fallo al escribir el fichero de configuración «%s» para el par "
 "%u: %s\n"
 
-#: src/testing/testing.c:1392
+#: src/testing/testing.c:1384
 #, c-format
 msgid "Failed to start `%s': %s\n"
 msgstr "Se produjo un fallo al arrancar «%s»: %s\n"
 
-#: src/testing/testing.c:1691
+#: src/testing/testing.c:1683
 #, c-format
 msgid "Failed to load configuration from %s\n"
 msgstr "Se produjo un fallo al cargar la configuración de %s\n"
@@ -7206,9 +7225,9 @@ msgstr "# mensajes «HELLO» recibidos"
 msgid "GNUnet topology control"
 msgstr ""
 
-#: src/transport/gnunet-communicator-tcp.c:2458
-#: src/transport/gnunet-communicator-udp.c:2825
-#: src/transport/gnunet-service-tng.c:10027
+#: src/transport/gnunet-communicator-tcp.c:3189
+#: src/transport/gnunet-communicator-udp.c:2826
+#: src/transport/gnunet-service-tng.c:10014
 #: src/transport/gnunet-service-transport.c:2624
 #, fuzzy
 msgid "Transport service is lacking key configuration settings. Exiting.\n"
@@ -7216,35 +7235,35 @@ msgstr ""
 "El servicio de transporte carece de opciones de configuración de clave.  "
 "Saliendo.\n"
 
-#: src/transport/gnunet-communicator-tcp.c:2754
+#: src/transport/gnunet-communicator-tcp.c:3494
 #, fuzzy
 msgid "GNUnet TCP communicator"
 msgstr "Configurador Gtk de GNUnet"
 
-#: src/transport/gnunet-communicator-udp.c:2897
+#: src/transport/gnunet-communicator-udp.c:2898
 #, fuzzy
 msgid "GNUnet UDP communicator"
 msgstr "Configurador Gtk de GNUnet"
 
-#: src/transport/gnunet-communicator-unix.c:788
+#: src/transport/gnunet-communicator-unix.c:789
 #, fuzzy
 msgid ""
 "Maximum number of UNIX connections exceeded, dropping incoming message\n"
 msgstr "El número máximo de conexiones es %u\n"
 
-#: src/transport/gnunet-communicator-unix.c:1015
+#: src/transport/gnunet-communicator-unix.c:1016
 #, fuzzy
 msgid "UNIX communicator is lacking key configuration settings. Exiting.\n"
 msgstr ""
 "El servicio NSE carece de opciones de configuración de clave.  Saliendo.\n"
 
-#: src/transport/gnunet-communicator-unix.c:1060
+#: src/transport/gnunet-communicator-unix.c:1061
 #: src/transport/plugin_transport_unix.c:1383
 #, fuzzy, c-format
 msgid "Cannot create path to `%s'\n"
 msgstr "Se produjo un fallo al crear la página para «%s»\n"
 
-#: src/transport/gnunet-communicator-unix.c:1138
+#: src/transport/gnunet-communicator-unix.c:1139
 msgid "GNUnet UNIX domain socket communicator"
 msgstr ""
 
@@ -8371,7 +8390,7 @@ msgid "do daemonize (detach from terminal)"
 msgstr "demonizar (desasociar del terminal)"
 
 #: src/transport/tcp_service_legacy.c:1397
-#: src/transport/transport-testing2.c:1061 src/util/service.c:2072
+#: src/transport/transport-testing2.c:1116 src/util/service.c:2072
 #: src/util/service.c:2084
 #, fuzzy, c-format
 msgid "Malformed configuration file `%s', exit ...\n"
@@ -8414,7 +8433,7 @@ msgstr ""
 msgid "Invalid handle type while reading `%s'"
 msgstr "Parámetro no válido «%s» en la línea de comandos\n"
 
-#: src/util/bio.c:335 src/util/bio.c:838
+#: src/util/bio.c:335 src/util/bio.c:839
 msgid "string length"
 msgstr ""
 
@@ -8433,7 +8452,7 @@ msgstr "Se produjo un error leyendo la cadena «%s»"
 msgid "String `%s' longer than allowed (%u > %u)"
 msgstr "La cadena «%s» es mayor de lo permitido (%u > %u)"
 
-#: src/util/bio.c:398 src/util/bio.c:863 src/util/bio.c:880
+#: src/util/bio.c:398 src/util/bio.c:864 src/util/bio.c:881
 msgid "metadata length"
 msgstr ""
 
@@ -8447,25 +8466,25 @@ msgstr "Los metadatos serializados «%s» son mayores de lo permitido (%u>%u)"
 msgid "Failed to deserialize metadata `%s'"
 msgstr "Se produjo un fallo al serializar metadatos"
 
-#: src/util/bio.c:667
+#: src/util/bio.c:668
 msgid "Unable to flush buffer to file"
 msgstr ""
 
-#: src/util/bio.c:729 src/util/bio.c:750
+#: src/util/bio.c:730 src/util/bio.c:751
 #, fuzzy, c-format
 msgid "Error while writing `%s' to file: %s"
 msgstr "Error decodificando clave %u\n"
 
-#: src/util/bio.c:731
+#: src/util/bio.c:732
 msgid "No associated file"
 msgstr ""
 
-#: src/util/bio.c:815
+#: src/util/bio.c:816
 #, fuzzy, c-format
 msgid "Invalid handle type while writing `%s'"
 msgstr "Formato de tiempo no válido «%s»\n"
 
-#: src/util/bio.c:875
+#: src/util/bio.c:876
 #, fuzzy, c-format
 msgid "Failed to serialize metadata `%s'"
 msgstr "Se produjo un fallo al serializar metadatos"
@@ -8964,15 +8983,15 @@ msgstr "URI no válida: falla al especificar el subsistema\n"
 msgid "No handler known for subsystem `%s'\n"
 msgstr "No hay un manejador conocido para el subsistema «%s»\n"
 
-#: src/util/gnunet-qr.c:358
+#: src/util/gnunet-qr.c:357
 msgid "use video-device DEVICE (default: /dev/video0"
 msgstr ""
 
-#: src/util/gnunet-qr.c:363
+#: src/util/gnunet-qr.c:362
 msgid "do not show preview windows"
 msgstr ""
 
-#: src/util/gnunet-qr.c:373
+#: src/util/gnunet-qr.c:372
 msgid "Scan a QR code using a video device and import the uri read"
 msgstr ""
 
@@ -8984,28 +9003,28 @@ msgstr "realizar una búsqueda inversa"
 msgid "Use build-in GNUnet stub resolver"
 msgstr "Utilizar el resolvedor interno para pruebas de GNUnet"
 
-#: src/util/gnunet-scrypt.c:222
+#: src/util/gnunet-scrypt.c:229
 #, c-format
 msgid "Loading hostkey from `%s' failed.\n"
 msgstr "La carga de la clave de la máquina desde «%s» ha fallado.\n"
 
-#: src/util/gnunet-scrypt.c:288
+#: src/util/gnunet-scrypt.c:295
 msgid "number of bits to require for the proof of work"
 msgstr ""
 
-#: src/util/gnunet-scrypt.c:294
+#: src/util/gnunet-scrypt.c:301
 msgid "file with private key, otherwise default is used"
 msgstr ""
 
-#: src/util/gnunet-scrypt.c:300
+#: src/util/gnunet-scrypt.c:307
 msgid "file with proof of work, otherwise default is used"
 msgstr ""
 
-#: src/util/gnunet-scrypt.c:306
+#: src/util/gnunet-scrypt.c:313
 msgid "time to wait between calculations"
 msgstr ""
 
-#: src/util/gnunet-scrypt.c:319
+#: src/util/gnunet-scrypt.c:326
 #, fuzzy
 msgid "Manipulate GNUnet proof of work files"
 msgstr "Manipular los ficheros de clave privada ECC de GNUnet"
@@ -9019,7 +9038,7 @@ msgstr ""
 msgid "No URI specified on command line\n"
 msgstr "No se ha especificado una URI en la línea de comandos. Saliendo.\n"
 
-#: src/util/gnunet-uri.c:179
+#: src/util/gnunet-uri.c:178
 msgid "Perform default-actions for GNUnet URIs"
 msgstr "Realizar las acciones predeterminadas para URI de GNUnet"
 
@@ -9035,7 +9054,7 @@ msgstr ""
 "Se produjo un fallo al procesar el mensaje interno del programa auxiliar "
 "«%s»\n"
 
-#: src/util/helper.c:600
+#: src/util/helper.c:602
 #, c-format
 msgid "Error writing to `%s': %s\n"
 msgstr "Error escribiendo a «%s»: %s\n"
@@ -9175,122 +9194,122 @@ msgstr ""
 msgid "Attempting to proxy service `%s' to invalid port %d or hostname.\n"
 msgstr ""
 
-#: src/util/strings.c:178
+#: src/util/strings.c:179
 msgid "b"
 msgstr "b"
 
-#: src/util/strings.c:502
+#: src/util/strings.c:503
 #, c-format
 msgid "Character sets requested were `%s'->`%s'\n"
 msgstr "Los conjuntos de caracteres pedidos fueron «%s»->«%s»\n"
 
-#: src/util/strings.c:636
+#: src/util/strings.c:637
 msgid "Failed to expand `$HOME': environment variable `HOME' not set"
 msgstr ""
 "Se produjo un fallo al expandir «$HOME»: variable de entorno «HOME» no "
 "establecida"
 
-#: src/util/strings.c:705
+#: src/util/strings.c:706
 msgid "µs"
 msgstr ""
 
-#: src/util/strings.c:709
+#: src/util/strings.c:710
 msgid "forever"
 msgstr "para siempre"
 
-#: src/util/strings.c:711
+#: src/util/strings.c:712
 msgid "0 ms"
 msgstr "0 ms"
 
-#: src/util/strings.c:715
+#: src/util/strings.c:716
 msgid "ms"
 msgstr "ms"
 
-#: src/util/strings.c:719
+#: src/util/strings.c:720
 msgid "s"
 msgstr "s"
 
-#: src/util/strings.c:723
+#: src/util/strings.c:724
 msgid "m"
 msgstr "m"
 
-#: src/util/strings.c:727
+#: src/util/strings.c:728
 msgid "h"
 msgstr "h"
 
-#: src/util/strings.c:733
+#: src/util/strings.c:734
 msgid "day"
 msgstr "día"
 
-#: src/util/strings.c:735
+#: src/util/strings.c:736
 msgid "days"
 msgstr "días"
 
-#: src/util/strings.c:763
+#: src/util/strings.c:764
 msgid "end of time"
 msgstr "fin del plazo"
 
-#: src/util/strings.c:1239
+#: src/util/strings.c:1240
 msgid "IPv6 address did not start with `['\n"
 msgstr "La dirección IPv6 no empezaba con «[»\n"
 
-#: src/util/strings.c:1247
+#: src/util/strings.c:1248
 msgid "IPv6 address did contain ':' to separate port number\n"
 msgstr "La dirección IPv6 contenía «:» para separar el número de puerto\n"
 
-#: src/util/strings.c:1254
+#: src/util/strings.c:1255
 msgid "IPv6 address did contain ']' before ':' to separate port number\n"
 msgstr ""
 "La dirección IPv6 contenía «]» antes de «:» para separar el número de "
 "puerto\n"
 
-#: src/util/strings.c:1262
+#: src/util/strings.c:1263
 msgid "IPv6 address did contain a valid port number after the last ':'\n"
 msgstr ""
 "La dirección IPv6 contenía un número de puerto válido después del último "
 "«:»\n"
 
-#: src/util/strings.c:1271
+#: src/util/strings.c:1272
 #, c-format
 msgid "Invalid IPv6 address `%s': %s\n"
 msgstr "Dirección IPv6 «%s» no válida: %s\n"
 
-#: src/util/strings.c:1498 src/util/strings.c:1509
+#: src/util/strings.c:1499 src/util/strings.c:1510
 msgid "Port not in range\n"
 msgstr ""
 
-#: src/util/strings.c:1518
+#: src/util/strings.c:1519
 #, fuzzy, c-format
 msgid "Malformed port policy `%s'\n"
 msgstr "Se produjo un fallo al iniciar el servicio «%s»\n"
 
-#: src/util/strings.c:1601 src/util/strings.c:1630 src/util/strings.c:1677
-#: src/util/strings.c:1697
+#: src/util/strings.c:1602 src/util/strings.c:1631 src/util/strings.c:1678
+#: src/util/strings.c:1698
 #, c-format
 msgid "Invalid format for IP: `%s'\n"
 msgstr "Formato no válido para la IP: «%s»\n"
 
-#: src/util/strings.c:1655
+#: src/util/strings.c:1656
 #, c-format
 msgid "Invalid network notation ('/%d' is not legal in IPv4 CIDR)."
 msgstr "Notación de red no válida («/%d» no es válido en IPv4 CIDR)."
 
-#: src/util/strings.c:1706
+#: src/util/strings.c:1707
 #, fuzzy, c-format
 msgid "Invalid format: `%s'\n"
 msgstr "Formato de tiempo no válido «%s»\n"
 
-#: src/util/strings.c:1759
+#: src/util/strings.c:1760
 #, c-format
 msgid "Invalid network notation (does not end with ';': `%s')\n"
 msgstr "Notación de red no válida (no termina con «;»: «%s»)\n"
 
-#: src/util/strings.c:1809
+#: src/util/strings.c:1810
 #, c-format
 msgid "Wrong format `%s' for netmask\n"
 msgstr "Formato «%s» erroneo para máscara de red\n"
 
-#: src/util/strings.c:1840
+#: src/util/strings.c:1841
 #, c-format
 msgid "Wrong format `%s' for network\n"
 msgstr "Formato «%s» erroneo para red\n"
diff --git a/po/fr.po b/po/fr.po
index 521bc8d78eed6278ae7c5f2314da83ff2bf12239..1ffa44998be9ec91304fea29c7c30d1f443322e9 100644
--- a/po/fr.po
+++ b/po/fr.po
@@ -7,7 +7,7 @@ msgid ""
 msgstr ""
 "Project-Id-Version: gnunet 0.10.1\n"
 "Report-Msgid-Bugs-To: gnunet-developers@mail.gnu.org\n"
-"POT-Creation-Date: 2020-07-12 17:55+0200\n"
+"POT-Creation-Date: 2020-09-06 10:07+0200\n"
 "PO-Revision-Date: 2015-12-24 01:20+0100\n"
 "Last-Translator: Stéphane  Aulery <lkppo@free.fr>\n"
 "Language-Team: French <traduc@traduc.org>\n"
@@ -16,12 +16,12 @@ msgstr ""
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
 
-#: src/abd/gnunet-abd.c:397 src/namestore/gnunet-namestore.c:1302
+#: src/abd/gnunet-abd.c:397 src/namestore/gnunet-namestore.c:1303
 #, c-format
 msgid "Ego `%s' not known to identity service\n"
 msgstr ""
 
-#: src/abd/gnunet-abd.c:413 src/abd/gnunet-abd.c:896
+#: src/abd/gnunet-abd.c:413 src/abd/gnunet-abd.c:901
 #, c-format
 msgid "Issuer public key `%s' is not well-formed\n"
 msgstr ""
@@ -33,106 +33,106 @@ msgstr ""
 msgid "Failed to connect to namestore\n"
 msgstr ""
 
-#: src/abd/gnunet-abd.c:835 src/abd/gnunet-abd.c:886
+#: src/abd/gnunet-abd.c:840 src/abd/gnunet-abd.c:891
 #, c-format
 msgid "Issuer public key not well-formed\n"
 msgstr ""
 
-#: src/abd/gnunet-abd.c:844 src/abd/gnunet-abd.c:905
+#: src/abd/gnunet-abd.c:849 src/abd/gnunet-abd.c:910
 #, fuzzy, c-format
 msgid "Failed to connect to ABD\n"
 msgstr "Impossible d’ouvrir « %s ».\n"
 
-#: src/abd/gnunet-abd.c:850
+#: src/abd/gnunet-abd.c:855
 #, c-format
 msgid "You must provide issuer the attribute\n"
 msgstr ""
 
-#: src/abd/gnunet-abd.c:857
+#: src/abd/gnunet-abd.c:862
 #, c-format
 msgid "ego required\n"
 msgstr ""
 
-#: src/abd/gnunet-abd.c:867
+#: src/abd/gnunet-abd.c:872
 #, c-format
 msgid "Subject public key needed\n"
 msgstr ""
 
-#: src/abd/gnunet-abd.c:876
+#: src/abd/gnunet-abd.c:881
 #, c-format
 msgid "Subject public key `%s' is not well-formed\n"
 msgstr ""
 
-#: src/abd/gnunet-abd.c:911
+#: src/abd/gnunet-abd.c:916
 #, c-format
 msgid "You must provide issuer and subject attributes\n"
 msgstr ""
 
-#: src/abd/gnunet-abd.c:970
+#: src/abd/gnunet-abd.c:975
 #, c-format
 msgid "Please specify name to lookup, subject key and issuer key!\n"
 msgstr ""
 
-#: src/abd/gnunet-abd.c:991
+#: src/abd/gnunet-abd.c:996
 msgid "verify credential against attribute"
 msgstr ""
 
-#: src/abd/gnunet-abd.c:998
+#: src/abd/gnunet-abd.c:1003
 msgid ""
 "The public key of the subject to lookup thecredential for, or for issuer "
 "side storage: subject and its attributes"
 msgstr ""
 
-#: src/abd/gnunet-abd.c:1005
+#: src/abd/gnunet-abd.c:1010
 msgid "The private, signed delegate presented by the subject"
 msgstr ""
 
-#: src/abd/gnunet-abd.c:1012
+#: src/abd/gnunet-abd.c:1017
 msgid "The public key of the authority to verify the credential against"
 msgstr ""
 
-#: src/abd/gnunet-abd.c:1017
+#: src/abd/gnunet-abd.c:1022
 msgid "The ego/zone name to use"
 msgstr ""
 
-#: src/abd/gnunet-abd.c:1023
+#: src/abd/gnunet-abd.c:1028
 msgid "The issuer attribute to verify against or to issue"
 msgstr ""
 
-#: src/abd/gnunet-abd.c:1029
+#: src/abd/gnunet-abd.c:1034
 msgid ""
 "The time to live for the credential.e.g. 5m, 6h, \"1990-12-30 12:00:00\""
 msgstr ""
 
-#: src/abd/gnunet-abd.c:1034
+#: src/abd/gnunet-abd.c:1039
 msgid "collect credentials"
 msgstr ""
 
-#: src/abd/gnunet-abd.c:1039
+#: src/abd/gnunet-abd.c:1044
 msgid "Create and issue a credential issuer side."
 msgstr ""
 
-#: src/abd/gnunet-abd.c:1044
+#: src/abd/gnunet-abd.c:1049
 msgid "Issue a credential subject side."
 msgstr ""
 
-#: src/abd/gnunet-abd.c:1049
+#: src/abd/gnunet-abd.c:1054
 msgid "Create, sign and return a credential subject side."
 msgstr ""
 
-#: src/abd/gnunet-abd.c:1056
+#: src/abd/gnunet-abd.c:1061
 msgid "Import signed credentials that should be issued to a zone/ego"
 msgstr ""
 
-#: src/abd/gnunet-abd.c:1060
+#: src/abd/gnunet-abd.c:1065
 msgid "Create private record entry."
 msgstr ""
 
-#: src/abd/gnunet-abd.c:1066 src/abd/gnunet-abd.c:1072
+#: src/abd/gnunet-abd.c:1071 src/abd/gnunet-abd.c:1077
 msgid "Indicates that the collect/verify process is done via forward search."
 msgstr ""
 
-#: src/abd/gnunet-abd.c:1085
+#: src/abd/gnunet-abd.c:1090
 msgid "GNUnet abd resolver tool"
 msgstr ""
 
@@ -425,64 +425,64 @@ msgstr "Résolution de « %s » échouée : %s\n"
 msgid "Failed to find %saddress for `%s'.\n"
 msgstr ""
 
-#: src/arm/gnunet-service-arm.c:933
+#: src/arm/gnunet-service-arm.c:951
 #, c-format
 msgid "Failed to start service `%s'\n"
 msgstr ""
 
-#: src/arm/gnunet-service-arm.c:944
+#: src/arm/gnunet-service-arm.c:962
 #, c-format
 msgid "Starting service `%s'\n"
 msgstr ""
 
-#: src/arm/gnunet-service-arm.c:1044
+#: src/arm/gnunet-service-arm.c:1062
 #, c-format
 msgid "Unable to create socket for service `%s': %s\n"
 msgstr ""
 
-#: src/arm/gnunet-service-arm.c:1075
+#: src/arm/gnunet-service-arm.c:1093
 #, c-format
 msgid "Unable to bind listening socket for service `%s' to address `%s': %s\n"
 msgstr ""
 
-#: src/arm/gnunet-service-arm.c:1106
+#: src/arm/gnunet-service-arm.c:1124
 #, c-format
 msgid "ARM now monitors connections to service `%s' at `%s'\n"
 msgstr ""
 
-#: src/arm/gnunet-service-arm.c:1254
+#: src/arm/gnunet-service-arm.c:1272
 #, c-format
 msgid "Preparing to stop `%s'\n"
 msgstr ""
 
-#: src/arm/gnunet-service-arm.c:1586
+#: src/arm/gnunet-service-arm.c:1604
 #, c-format
 msgid "Restarting service `%s'.\n"
 msgstr ""
 
-#: src/arm/gnunet-service-arm.c:1737
+#: src/arm/gnunet-service-arm.c:1755
 msgid "exit"
 msgstr "exit"
 
-#: src/arm/gnunet-service-arm.c:1742
+#: src/arm/gnunet-service-arm.c:1760
 msgid "signal"
 msgstr "signal"
 
-#: src/arm/gnunet-service-arm.c:1747
+#: src/arm/gnunet-service-arm.c:1765
 msgid "unknown"
 msgstr "inconnu"
 
-#: src/arm/gnunet-service-arm.c:1753
+#: src/arm/gnunet-service-arm.c:1771
 #, c-format
 msgid "Service `%s' took %s to terminate\n"
 msgstr ""
 
-#: src/arm/gnunet-service-arm.c:1780
+#: src/arm/gnunet-service-arm.c:1798
 #, c-format
 msgid "Service `%s' terminated normally, will restart at any time\n"
 msgstr ""
 
-#: src/arm/gnunet-service-arm.c:1797
+#: src/arm/gnunet-service-arm.c:1815
 #, c-format
 msgid "Service `%s' terminated with status %s/%d, will restart in %s\n"
 msgstr ""
@@ -804,7 +804,10 @@ msgstr ""
 
 #: src/consensus/gnunet-consensus-profiler.c:543
 #: src/set/gnunet-set-profiler.c:451 src/set/gnunet-set-profiler.c:457
-#: src/set/gnunet-set-profiler.c:480
+#: src/set/gnunet-set-profiler.c:480 src/seti/gnunet-seti-profiler.c:441
+#: src/seti/gnunet-seti-profiler.c:446 src/seti/gnunet-seti-profiler.c:451
+#: src/setu/gnunet-setu-profiler.c:442 src/setu/gnunet-setu-profiler.c:448
+#: src/setu/gnunet-setu-profiler.c:471
 msgid "number of values"
 msgstr "nombre de valeurs"
 
@@ -817,7 +820,8 @@ msgid "delay until consensus starts"
 msgstr ""
 
 #: src/consensus/gnunet-consensus-profiler.c:563
-#: src/set/gnunet-set-profiler.c:498
+#: src/set/gnunet-set-profiler.c:498 src/seti/gnunet-seti-profiler.c:467
+#: src/setu/gnunet-setu-profiler.c:489
 msgid "write statistics to file"
 msgstr ""
 
@@ -1348,135 +1352,135 @@ msgstr ""
 msgid "Core service of `%s' ready.\n"
 msgstr ""
 
-#: src/core/gnunet-service-core_kx.c:625
+#: src/core/gnunet-service-core_kx.c:512
 msgid "# bytes encrypted"
 msgstr ""
 
-#: src/core/gnunet-service-core_kx.c:683
+#: src/core/gnunet-service-core_kx.c:570
 msgid "# bytes decrypted"
 msgstr ""
 
-#: src/core/gnunet-service-core_kx.c:780
+#: src/core/gnunet-service-core_kx.c:667
 msgid "# PAYLOAD dropped (out of order)"
 msgstr ""
 
-#: src/core/gnunet-service-core_kx.c:832
+#: src/core/gnunet-service-core_kx.c:719
 msgid "# key exchanges initiated"
 msgstr ""
 
-#: src/core/gnunet-service-core_kx.c:888
+#: src/core/gnunet-service-core_kx.c:775
 msgid "# key exchanges stopped"
 msgstr ""
 
-#: src/core/gnunet-service-core_kx.c:920
+#: src/core/gnunet-service-core_kx.c:807
 msgid "# PING messages transmitted"
 msgstr ""
 
-#: src/core/gnunet-service-core_kx.c:979
+#: src/core/gnunet-service-core_kx.c:866
 msgid "# old ephemeral keys ignored"
 msgstr ""
 
-#: src/core/gnunet-service-core_kx.c:993
+#: src/core/gnunet-service-core_kx.c:880
 msgid "# duplicate ephemeral keys ignored"
 msgstr ""
 
-#: src/core/gnunet-service-core_kx.c:1028
+#: src/core/gnunet-service-core_kx.c:915
 msgid "# EPHEMERAL_KEYs rejected (bad signature)"
 msgstr ""
 
-#: src/core/gnunet-service-core_kx.c:1046
+#: src/core/gnunet-service-core_kx.c:933
 #, c-format
 msgid ""
 "EPHEMERAL_KEY from peer `%s' rejected as its validity range does not match "
 "our system time (%llu not in [%llu,%llu]).\n"
 msgstr ""
 
-#: src/core/gnunet-service-core_kx.c:1053
+#: src/core/gnunet-service-core_kx.c:940
 msgid "# EPHEMERAL_KEY messages rejected due to time"
 msgstr ""
 
-#: src/core/gnunet-service-core_kx.c:1071
+#: src/core/gnunet-service-core_kx.c:958
 msgid "# valid ephemeral keys received"
 msgstr ""
 
-#: src/core/gnunet-service-core_kx.c:1180
+#: src/core/gnunet-service-core_kx.c:1067
 #: src/transport/gnunet-service-transport_validation.c:1133
 msgid "# PING messages received"
 msgstr ""
 
-#: src/core/gnunet-service-core_kx.c:1190
+#: src/core/gnunet-service-core_kx.c:1077
 msgid "# PING messages dropped (out of order)"
 msgstr ""
 
-#: src/core/gnunet-service-core_kx.c:1239
+#: src/core/gnunet-service-core_kx.c:1126
 msgid "# PONG messages created"
 msgstr ""
 
-#: src/core/gnunet-service-core_kx.c:1264
+#: src/core/gnunet-service-core_kx.c:1151
 msgid "# sessions terminated by timeout"
 msgstr ""
 
-#: src/core/gnunet-service-core_kx.c:1277
+#: src/core/gnunet-service-core_kx.c:1164
 msgid "# keepalive messages sent"
 msgstr ""
 
-#: src/core/gnunet-service-core_kx.c:1334
+#: src/core/gnunet-service-core_kx.c:1221
 #: src/transport/gnunet-service-transport_validation.c:1476
 msgid "# PONG messages received"
 msgstr ""
 
-#: src/core/gnunet-service-core_kx.c:1342
+#: src/core/gnunet-service-core_kx.c:1229
 msgid "# PONG messages dropped (connection down)"
 msgstr ""
 
-#: src/core/gnunet-service-core_kx.c:1350
+#: src/core/gnunet-service-core_kx.c:1237
 msgid "# PONG messages dropped (out of order)"
 msgstr ""
 
-#: src/core/gnunet-service-core_kx.c:1389
+#: src/core/gnunet-service-core_kx.c:1276
 msgid "# PONG messages decrypted"
 msgstr ""
 
-#: src/core/gnunet-service-core_kx.c:1429
+#: src/core/gnunet-service-core_kx.c:1316
 msgid "# session keys confirmed via PONG"
 msgstr ""
 
-#: src/core/gnunet-service-core_kx.c:1441
+#: src/core/gnunet-service-core_kx.c:1328
 msgid "# timeouts prevented via PONG"
 msgstr ""
 
-#: src/core/gnunet-service-core_kx.c:1450
+#: src/core/gnunet-service-core_kx.c:1337
 msgid "# rekey operations confirmed via PONG"
 msgstr ""
 
-#: src/core/gnunet-service-core_kx.c:1626
+#: src/core/gnunet-service-core_kx.c:1513
 msgid "# DATA message dropped (out of order)"
 msgstr ""
 
-#: src/core/gnunet-service-core_kx.c:1637
+#: src/core/gnunet-service-core_kx.c:1524
 #, c-format
 msgid ""
 "Session to peer `%s' went down due to key expiration (should not happen)\n"
 msgstr ""
 
-#: src/core/gnunet-service-core_kx.c:1641
+#: src/core/gnunet-service-core_kx.c:1528
 msgid "# sessions terminated by key expiration"
 msgstr ""
 
-#: src/core/gnunet-service-core_kx.c:1719
-#: src/core/gnunet-service-core_kx.c:1746
+#: src/core/gnunet-service-core_kx.c:1606
+#: src/core/gnunet-service-core_kx.c:1633
 msgid "# bytes dropped (duplicates)"
 msgstr ""
 
-#: src/core/gnunet-service-core_kx.c:1732
+#: src/core/gnunet-service-core_kx.c:1619
 msgid "# bytes dropped (out of sequence)"
 msgstr ""
 
-#: src/core/gnunet-service-core_kx.c:1777
+#: src/core/gnunet-service-core_kx.c:1664
 msgid "# bytes dropped (ancient message)"
 msgstr ""
 
-#: src/core/gnunet-service-core_kx.c:1786
+#: src/core/gnunet-service-core_kx.c:1673
 msgid "# bytes of payload decrypted"
 msgstr ""
 
@@ -3010,18 +3014,18 @@ msgstr ""
 msgid "Failed to load state: %s\n"
 msgstr ""
 
-#: src/fs/gnunet-auto-share.c:286 src/fs/gnunet-auto-share.c:295
-#: src/fs/gnunet-auto-share.c:303
+#: src/fs/gnunet-auto-share.c:287 src/fs/gnunet-auto-share.c:296
+#: src/fs/gnunet-auto-share.c:304
 #, c-format
 msgid "Failed to save state to file %s\n"
 msgstr ""
 
-#: src/fs/gnunet-auto-share.c:400
+#: src/fs/gnunet-auto-share.c:401
 #, c-format
 msgid "Publication of `%s' done\n"
 msgstr "Publication de « %s » terminée\n"
 
-#: src/fs/gnunet-auto-share.c:479
+#: src/fs/gnunet-auto-share.c:480
 #, c-format
 msgid "Publishing `%s'\n"
 msgstr "Publication de « %s »\n"
@@ -3809,38 +3813,38 @@ msgstr ""
 msgid "GNUnet HTTP server to create business cards"
 msgstr ""
 
-#: src/gns/gnunet-dns2gns.c:239
+#: src/gns/gnunet-dns2gns.c:241
 msgid "Failed to pack DNS response into UDP packet!\n"
 msgstr ""
 
-#: src/gns/gnunet-dns2gns.c:442
+#: src/gns/gnunet-dns2gns.c:444
 #, c-format
 msgid "Cannot parse DNS request from %s\n"
 msgstr ""
 
-#: src/gns/gnunet-dns2gns.c:458
+#: src/gns/gnunet-dns2gns.c:460
 #, c-format
 msgid "Received malformed DNS request from %s\n"
 msgstr ""
 
-#: src/gns/gnunet-dns2gns.c:466
+#: src/gns/gnunet-dns2gns.c:468
 #, c-format
 msgid "Received unsupported DNS request from %s\n"
 msgstr ""
 
-#: src/gns/gnunet-dns2gns.c:627
+#: src/gns/gnunet-dns2gns.c:629
 msgid "No DNS server specified!\n"
 msgstr ""
 
-#: src/gns/gnunet-dns2gns.c:776
+#: src/gns/gnunet-dns2gns.c:778
 msgid "IP of recursive DNS resolver to use (required)"
 msgstr ""
 
-#: src/gns/gnunet-dns2gns.c:782
+#: src/gns/gnunet-dns2gns.c:784
 msgid "UDP port to listen on for inbound DNS requests; default: 2853"
 msgstr ""
 
-#: src/gns/gnunet-dns2gns.c:799
+#: src/gns/gnunet-dns2gns.c:801
 msgid "GNUnet DNS-to-GNS proxy (a DNS server)"
 msgstr ""
 
@@ -3978,7 +3982,7 @@ msgstr ""
 msgid "Failed to start HTTPS server for `%s'\n"
 msgstr ""
 
-#: src/gns/gnunet-gns-proxy.c:2922 src/rest/gnunet-rest-server.c:713
+#: src/gns/gnunet-gns-proxy.c:2922 src/rest/gnunet-rest-server.c:917
 msgid "Failed to pass client to MHD\n"
 msgstr ""
 
@@ -4128,7 +4132,7 @@ msgstr ""
 msgid "Unable to parse BOX record string `%s'\n"
 msgstr ""
 
-#: src/gns/plugin_rest_gns.c:445
+#: src/gns/plugin_rest_gns.c:447
 msgid "Gns REST API initialized\n"
 msgstr ""
 
@@ -4321,7 +4325,7 @@ msgid "# valid HELLOs downloaded from hostlist servers"
 msgstr ""
 
 #: src/hostlist/gnunet-daemon-hostlist_client.c:677
-#: src/hostlist/gnunet-daemon-hostlist_client.c:1459
+#: src/hostlist/gnunet-daemon-hostlist_client.c:1460
 msgid "# advertised hostlist URIs"
 msgstr ""
 
@@ -4372,7 +4376,7 @@ msgid "# hostlist downloads initiated"
 msgstr ""
 
 #: src/hostlist/gnunet-daemon-hostlist_client.c:1144
-#: src/hostlist/gnunet-daemon-hostlist_client.c:1726
+#: src/hostlist/gnunet-daemon-hostlist_client.c:1728
 msgid "# milliseconds between hostlist downloads"
 msgstr ""
 
@@ -4401,50 +4405,50 @@ msgstr ""
 msgid "Could not open file `%s' for reading to load hostlists: %s\n"
 msgstr ""
 
-#: src/hostlist/gnunet-daemon-hostlist_client.c:1452
+#: src/hostlist/gnunet-daemon-hostlist_client.c:1453
 #, c-format
 msgid "%u hostlist URIs loaded from file\n"
 msgstr ""
 
-#: src/hostlist/gnunet-daemon-hostlist_client.c:1455
+#: src/hostlist/gnunet-daemon-hostlist_client.c:1456
 msgid "# hostlist URIs read from file"
 msgstr ""
 
-#: src/hostlist/gnunet-daemon-hostlist_client.c:1506
+#: src/hostlist/gnunet-daemon-hostlist_client.c:1507
 #, c-format
 msgid "Could not open file `%s' for writing to save hostlists: %s\n"
 msgstr ""
 
-#: src/hostlist/gnunet-daemon-hostlist_client.c:1513
+#: src/hostlist/gnunet-daemon-hostlist_client.c:1514
 #, c-format
 msgid "Writing %u hostlist URIs to `%s'\n"
 msgstr ""
 
-#: src/hostlist/gnunet-daemon-hostlist_client.c:1545
-#: src/hostlist/gnunet-daemon-hostlist_client.c:1564
+#: src/hostlist/gnunet-daemon-hostlist_client.c:1547
+#: src/hostlist/gnunet-daemon-hostlist_client.c:1566
 #, c-format
 msgid "Error writing hostlist URIs to file `%s'\n"
 msgstr ""
 
-#: src/hostlist/gnunet-daemon-hostlist_client.c:1558
+#: src/hostlist/gnunet-daemon-hostlist_client.c:1560
 msgid "# hostlist URIs written to file"
 msgstr ""
 
-#: src/hostlist/gnunet-daemon-hostlist_client.c:1655
+#: src/hostlist/gnunet-daemon-hostlist_client.c:1657
 #: src/transport/plugin_transport_http_client.c:2301
 #, c-format
 msgid "Invalid proxy type: `%s', disabling proxy! Check configuration!\n"
 msgstr ""
 
-#: src/hostlist/gnunet-daemon-hostlist_client.c:1684
+#: src/hostlist/gnunet-daemon-hostlist_client.c:1686
 msgid "Learning is enabled on this peer\n"
 msgstr ""
 
-#: src/hostlist/gnunet-daemon-hostlist_client.c:1697
+#: src/hostlist/gnunet-daemon-hostlist_client.c:1699
 msgid "Learning is not enabled on this peer\n"
 msgstr ""
 
-#: src/hostlist/gnunet-daemon-hostlist_client.c:1711
+#: src/hostlist/gnunet-daemon-hostlist_client.c:1713
 #, c-format
 msgid ""
 "Since learning is not enabled on this peer, hostlist file `%s' was removed\n"
@@ -4566,48 +4570,48 @@ msgstr ""
 msgid "Failed to set default ego: %s\n"
 msgstr ""
 
-#: src/identity/gnunet-identity.c:445
+#: src/identity/gnunet-identity.c:446
 msgid "create ego NAME"
 msgstr ""
 
-#: src/identity/gnunet-identity.c:450
+#: src/identity/gnunet-identity.c:451
 msgid "delete ego NAME "
 msgstr ""
 
-#: src/identity/gnunet-identity.c:455
+#: src/identity/gnunet-identity.c:457
 msgid ""
 "set the private key for the identity to PRIVATE_KEY (use together with -C)"
 msgstr ""
 
-#: src/identity/gnunet-identity.c:459
+#: src/identity/gnunet-identity.c:461
 msgid "display all egos"
 msgstr ""
 
-#: src/identity/gnunet-identity.c:463
+#: src/identity/gnunet-identity.c:465
 #, fuzzy
 msgid "reduce output"
 msgstr "sortie verbeuse"
 
-#: src/identity/gnunet-identity.c:470
+#: src/identity/gnunet-identity.c:472
 msgid ""
 "set default identity to NAME for a subsystem SUBSYSTEM (use together with -"
 "s) or restrict results to NAME (use together with -d)"
 msgstr ""
 
-#: src/identity/gnunet-identity.c:474
+#: src/identity/gnunet-identity.c:476
 msgid "run in monitor mode egos"
 msgstr ""
 
-#: src/identity/gnunet-identity.c:478
+#: src/identity/gnunet-identity.c:480
 msgid "display private keys as well"
 msgstr ""
 
-#: src/identity/gnunet-identity.c:485
+#: src/identity/gnunet-identity.c:487
 msgid ""
 "set default identity to EGO for a subsystem SUBSYSTEM (use together with -e)"
 msgstr ""
 
-#: src/identity/gnunet-identity.c:500
+#: src/identity/gnunet-identity.c:502
 msgid "Maintain egos"
 msgstr ""
 
@@ -4658,7 +4662,7 @@ msgstr ""
 msgid "Failed to create directory `%s' for storing egos\n"
 msgstr ""
 
-#: src/identity/plugin_rest_identity.c:1406
+#: src/identity/plugin_rest_identity.c:1384
 msgid "Identity REST API initialized\n"
 msgstr ""
 
@@ -4707,7 +4711,7 @@ msgstr "fornat invalide : « %s »\n"
 msgid "You must specify a name\n"
 msgstr ""
 
-#: src/namecache/gnunet-namecache.c:214 src/namestore/gnunet-namestore.c:1639
+#: src/namecache/gnunet-namecache.c:214 src/namestore/gnunet-namestore.c:1640
 msgid "name of the record to add/delete/display"
 msgstr ""
 
@@ -4715,7 +4719,7 @@ msgstr ""
 msgid "specifies the public key of the zone to look in"
 msgstr ""
 
-#: src/namecache/gnunet-namecache.c:233 src/namestore/gnunet-namestore.c:1700
+#: src/namecache/gnunet-namecache.c:233 src/namestore/gnunet-namestore.c:1701
 msgid "GNUnet zone manipulation tool"
 msgstr ""
 
@@ -4821,10 +4825,10 @@ msgstr "Résolution de « %s » échouée : %s\n"
 msgid "No options given\n"
 msgstr ""
 
-#: src/namestore/gnunet-namestore.c:1014 src/namestore/gnunet-namestore.c:1065
-#: src/namestore/gnunet-namestore.c:1075 src/namestore/gnunet-namestore.c:1104
-#: src/namestore/gnunet-namestore.c:1125 src/namestore/gnunet-namestore.c:1152
-#: src/namestore/gnunet-namestore.c:1228
+#: src/namestore/gnunet-namestore.c:1014 src/namestore/gnunet-namestore.c:1066
+#: src/namestore/gnunet-namestore.c:1076 src/namestore/gnunet-namestore.c:1105
+#: src/namestore/gnunet-namestore.c:1126 src/namestore/gnunet-namestore.c:1153
+#: src/namestore/gnunet-namestore.c:1229
 #, c-format
 msgid "Missing option `%s' for operation `%s'\n"
 msgstr ""
@@ -4838,53 +4842,53 @@ msgstr ""
 msgid "Invalid nick `%s'\n"
 msgstr ""
 
-#: src/namestore/gnunet-namestore.c:1067 src/namestore/gnunet-namestore.c:1077
-#: src/namestore/gnunet-namestore.c:1106 src/namestore/gnunet-namestore.c:1127
-#: src/namestore/gnunet-namestore.c:1230
+#: src/namestore/gnunet-namestore.c:1068 src/namestore/gnunet-namestore.c:1078
+#: src/namestore/gnunet-namestore.c:1107 src/namestore/gnunet-namestore.c:1128
+#: src/namestore/gnunet-namestore.c:1231
 msgid "add"
 msgstr "ajouter"
 
-#: src/namestore/gnunet-namestore.c:1085
+#: src/namestore/gnunet-namestore.c:1086
 #, c-format
 msgid "Unsupported type `%s'\n"
 msgstr ""
 
-#: src/namestore/gnunet-namestore.c:1095
+#: src/namestore/gnunet-namestore.c:1096
 #, c-format
 msgid "For DNS record types `SRV', `TLSA' and `OPENPGPKEY'"
 msgstr ""
 
-#: src/namestore/gnunet-namestore.c:1115
+#: src/namestore/gnunet-namestore.c:1116
 #, c-format
 msgid "Value `%s' invalid for record type `%s'\n"
 msgstr ""
 
-#: src/namestore/gnunet-namestore.c:1134 src/namestore/gnunet-namestore.c:1237
+#: src/namestore/gnunet-namestore.c:1135 src/namestore/gnunet-namestore.c:1238
 #, c-format
 msgid "Invalid time format `%s'\n"
 msgstr ""
 
-#: src/namestore/gnunet-namestore.c:1154
+#: src/namestore/gnunet-namestore.c:1155
 msgid "del"
 msgstr "supprimer"
 
-#: src/namestore/gnunet-namestore.c:1197
+#: src/namestore/gnunet-namestore.c:1198
 #, c-format
 msgid "Invalid public key for reverse lookup `%s'\n"
 msgstr ""
 
-#: src/namestore/gnunet-namestore.c:1220
+#: src/namestore/gnunet-namestore.c:1221
 #: src/peerinfo-tool/gnunet-peerinfo.c:736
 #, c-format
 msgid "Invalid URI `%s'\n"
 msgstr "URI invalide « %s »\n"
 
-#: src/namestore/gnunet-namestore.c:1290
+#: src/namestore/gnunet-namestore.c:1291
 #, c-format
 msgid "Label `%s' contains `.' which is not allowed\n"
 msgstr ""
 
-#: src/namestore/gnunet-namestore.c:1340
+#: src/namestore/gnunet-namestore.c:1341
 #, c-format
 msgid ""
 "No default identity configured for `namestore' subsystem\n"
@@ -4892,99 +4896,99 @@ msgid ""
 "Run gnunet-identity -d to get a list of choices for $NAME\n"
 msgstr ""
 
-#: src/namestore/gnunet-namestore.c:1405
+#: src/namestore/gnunet-namestore.c:1406
 #, c-format
 msgid "Superfluous command line arguments (starting with `%s') ignored\n"
 msgstr ""
 
-#: src/namestore/gnunet-namestore.c:1434
+#: src/namestore/gnunet-namestore.c:1435
 #, c-format
 msgid "Cannot connect to identity service\n"
 msgstr ""
 
-#: src/namestore/gnunet-namestore.c:1481
+#: src/namestore/gnunet-namestore.c:1482
 msgid "Empty record line argument is not allowed.\n"
 msgstr ""
 
-#: src/namestore/gnunet-namestore.c:1493
+#: src/namestore/gnunet-namestore.c:1494
 #, c-format
 msgid "Invalid expiration time `%s' (must be without unit)\n"
 msgstr ""
 
-#: src/namestore/gnunet-namestore.c:1505 src/namestore/gnunet-namestore.c:1521
-#: src/namestore/gnunet-namestore.c:1538
+#: src/namestore/gnunet-namestore.c:1506 src/namestore/gnunet-namestore.c:1522
+#: src/namestore/gnunet-namestore.c:1539
 #, c-format
 msgid "Missing entries in record line `%s'.\n"
 msgstr ""
 
-#: src/namestore/gnunet-namestore.c:1513
+#: src/namestore/gnunet-namestore.c:1514
 #, fuzzy, c-format
 msgid "Unknown record type `%s'\n"
 msgstr "Commande « %s » inconnue\n"
 
-#: src/namestore/gnunet-namestore.c:1551
+#: src/namestore/gnunet-namestore.c:1552
 #, fuzzy, c-format
 msgid "Invalid record data for type %s: `%s'.\n"
 msgstr "fornat invalide : « %s »\n"
 
-#: src/namestore/gnunet-namestore.c:1608
+#: src/namestore/gnunet-namestore.c:1609
 msgid "add record"
 msgstr "ajouter un enregistrement"
 
-#: src/namestore/gnunet-namestore.c:1611
+#: src/namestore/gnunet-namestore.c:1612
 msgid "delete record"
 msgstr "suprimer un enregistrement"
 
-#: src/namestore/gnunet-namestore.c:1615
+#: src/namestore/gnunet-namestore.c:1616
 msgid "display records"
 msgstr "afficher les enregistrements"
 
-#: src/namestore/gnunet-namestore.c:1622
+#: src/namestore/gnunet-namestore.c:1623
 msgid ""
 "expiration time for record to use (for adding only), \"never\" is possible"
 msgstr ""
 
-#: src/namestore/gnunet-namestore.c:1628
+#: src/namestore/gnunet-namestore.c:1629
 msgid "set the desired nick name for the zone"
 msgstr ""
 
-#: src/namestore/gnunet-namestore.c:1633
+#: src/namestore/gnunet-namestore.c:1634
 msgid "monitor changes in the namestore"
 msgstr ""
 
-#: src/namestore/gnunet-namestore.c:1645
+#: src/namestore/gnunet-namestore.c:1646
 msgid "determine our name for the given PKEY"
 msgstr ""
 
-#: src/namestore/gnunet-namestore.c:1652
+#: src/namestore/gnunet-namestore.c:1653
 msgid ""
 "set record set to values given by (possibly multiple) RECORDLINES; can be "
 "specified multiple times"
 msgstr ""
 
-#: src/namestore/gnunet-namestore.c:1658
+#: src/namestore/gnunet-namestore.c:1659
 msgid "type of the record to add/delete/display"
 msgstr ""
 
-#: src/namestore/gnunet-namestore.c:1663
+#: src/namestore/gnunet-namestore.c:1664
 msgid "URI to import into our zone"
 msgstr ""
 
-#: src/namestore/gnunet-namestore.c:1669
+#: src/namestore/gnunet-namestore.c:1670
 msgid "value of the record to add/delete"
 msgstr ""
 
-#: src/namestore/gnunet-namestore.c:1673
+#: src/namestore/gnunet-namestore.c:1674
 msgid "create or list public record"
 msgstr ""
 
-#: src/namestore/gnunet-namestore.c:1679
+#: src/namestore/gnunet-namestore.c:1680
 msgid ""
 "create shadow record (only valid if all other records of the same type have "
 "expired"
 msgstr ""
 
-#: src/namestore/gnunet-namestore.c:1685
+#: src/namestore/gnunet-namestore.c:1686
 msgid "name of the ego controlling the zone"
 msgstr ""
 
@@ -5081,7 +5085,7 @@ msgstr ""
 msgid "Flat file database running\n"
 msgstr ""
 
-#: src/namestore/plugin_rest_namestore.c:1093
+#: src/namestore/plugin_rest_namestore.c:1103
 msgid "Namestore REST API initialized\n"
 msgstr ""
 
@@ -5343,7 +5347,7 @@ msgstr ""
 msgid "gnunet-helper-nat-server generated malformed address `%s'\n"
 msgstr ""
 
-#: src/nat/gnunet-service-nat_helper.c:250
+#: src/nat/gnunet-service-nat_helper.c:249
 #, c-format
 msgid "Failed to start %s\n"
 msgstr "Échec du démarrage de %s\n"
@@ -5352,7 +5356,7 @@ msgstr "Échec du démarrage de %s\n"
 msgid "`external-ip' command not found\n"
 msgstr ""
 
-#: src/nat/gnunet-service-nat_mini.c:608
+#: src/nat/gnunet-service-nat_mini.c:607
 msgid "`upnpc' command not found\n"
 msgstr ""
 
@@ -5384,8 +5388,8 @@ msgstr ""
 msgid "Measure quality and performance of the NSE service."
 msgstr ""
 
-#: src/nse/gnunet-service-nse.c:1438
-#: src/revocation/gnunet-service-revocation.c:842 src/util/gnunet-scrypt.c:250
+#: src/nse/gnunet-service-nse.c:1443
+#: src/revocation/gnunet-service-revocation.c:834 src/util/gnunet-scrypt.c:257
 msgid "Value is too large.\n"
 msgstr ""
 
@@ -5454,7 +5458,7 @@ msgid "\tExpires: %s \t %s\n"
 msgstr ""
 
 #: src/peerinfo-tool/gnunet-peerinfo.c:292
-#: src/peerinfo-tool/plugin_rest_peerinfo.c:501
+#: src/peerinfo-tool/plugin_rest_peerinfo.c:523
 #, c-format
 msgid "Failure: Cannot convert address to string for peer `%s'\n"
 msgstr ""
@@ -5533,7 +5537,7 @@ msgstr ""
 msgid "Failed to load transport plugin for `%s'\n"
 msgstr ""
 
-#: src/peerinfo-tool/plugin_rest_peerinfo.c:797
+#: src/peerinfo-tool/plugin_rest_peerinfo.c:809
 msgid "Peerinfo REST API initialized\n"
 msgstr ""
 
@@ -5637,94 +5641,98 @@ msgstr ""
 msgid "Daemon to run to perform IP protocol translation to GNUnet"
 msgstr ""
 
-#: src/reclaim/gnunet-reclaim.c:799
+#: src/reclaim/gnunet-reclaim.c:801
 #, c-format
 msgid "Ego is required\n"
 msgstr ""
 
-#: src/reclaim/gnunet-reclaim.c:806
+#: src/reclaim/gnunet-reclaim.c:808
 #, c-format
 msgid "Attribute value missing!\n"
 msgstr ""
 
-#: src/reclaim/gnunet-reclaim.c:813
+#: src/reclaim/gnunet-reclaim.c:815
 #, c-format
 msgid "Requesting party key is required!\n"
 msgstr ""
 
-#: src/reclaim/gnunet-reclaim.c:831
+#: src/reclaim/gnunet-reclaim.c:833
 msgid "Add an attribute NAME"
 msgstr ""
 
-#: src/reclaim/gnunet-reclaim.c:836
+#: src/reclaim/gnunet-reclaim.c:838
 msgid "Delete the attribute with ID"
 msgstr ""
 
-#: src/reclaim/gnunet-reclaim.c:841
+#: src/reclaim/gnunet-reclaim.c:843
 msgid "The attribute VALUE"
 msgstr ""
 
-#: src/reclaim/gnunet-reclaim.c:846
+#: src/reclaim/gnunet-reclaim.c:848
 msgid "The EGO to use"
 msgstr ""
 
-#: src/reclaim/gnunet-reclaim.c:852
+#: src/reclaim/gnunet-reclaim.c:854
 msgid "Specify the relying party for issue"
 msgstr ""
 
-#: src/reclaim/gnunet-reclaim.c:856
+#: src/reclaim/gnunet-reclaim.c:858
 msgid "List attributes for EGO"
 msgstr ""
 
-#: src/reclaim/gnunet-reclaim.c:860
-msgid "List attestations for EGO"
+#: src/reclaim/gnunet-reclaim.c:862
+msgid "List credentials for EGO"
 msgstr ""
 
-#: src/reclaim/gnunet-reclaim.c:866
-msgid "Attestation to use for attribute"
+#: src/reclaim/gnunet-reclaim.c:868
+msgid "Credential to use for attribute"
 msgstr ""
 
-#: src/reclaim/gnunet-reclaim.c:871
-msgid "Attestation name"
+#: src/reclaim/gnunet-reclaim.c:873
+msgid "Credential name"
 msgstr ""
 
-#: src/reclaim/gnunet-reclaim.c:877
+#: src/reclaim/gnunet-reclaim.c:879
 msgid "Issue a ticket for a set of attributes separated by comma"
 msgstr ""
 
-#: src/reclaim/gnunet-reclaim.c:882
+#: src/reclaim/gnunet-reclaim.c:884
 msgid "Consume a ticket"
 msgstr ""
 
-#: src/reclaim/gnunet-reclaim.c:887
+#: src/reclaim/gnunet-reclaim.c:889
 msgid "Revoke a ticket"
 msgstr ""
 
-#: src/reclaim/gnunet-reclaim.c:892
+#: src/reclaim/gnunet-reclaim.c:894
 msgid "Type of attribute"
 msgstr ""
 
-#: src/reclaim/gnunet-reclaim.c:896
+#: src/reclaim/gnunet-reclaim.c:899
+msgid "Type of credential"
+msgstr ""
+
+#: src/reclaim/gnunet-reclaim.c:903
 msgid "List tickets of ego"
 msgstr ""
 
-#: src/reclaim/gnunet-reclaim.c:902
+#: src/reclaim/gnunet-reclaim.c:909
 msgid "Expiration interval of the attribute"
 msgstr ""
 
-#: src/reclaim/gnunet-reclaim.c:910
+#: src/reclaim/gnunet-reclaim.c:917
 msgid "re:claimID command line tool"
 msgstr ""
 
-#: src/reclaim/plugin_rest_openid_connect.c:2481
+#: src/reclaim/plugin_rest_openid_connect.c:2618
 msgid "OpenID Connect REST API initialized\n"
 msgstr ""
 
-#: src/reclaim/plugin_rest_reclaim.c:1476
+#: src/reclaim/plugin_rest_reclaim.c:1502
 msgid "Identity Provider REST API initialized\n"
 msgstr ""
 
-#: src/reclaim/reclaim_api.c:540
+#: src/reclaim/reclaim_api.c:545
 #, fuzzy
 msgid "failed to store record\n"
 msgstr "Échec du démarrage de %s\n"
@@ -5813,15 +5821,15 @@ msgstr ""
 msgid "Search string `%s' is too long!\n"
 msgstr ""
 
-#: src/rest/gnunet-rest-server.c:1051
+#: src/rest/gnunet-rest-server.c:1266
 msgid "GNUnet REST server"
 msgstr ""
 
-#: src/rest/plugin_rest_config.c:402
+#: src/rest/plugin_rest_config.c:427
 msgid "CONFIG REST API initialized\n"
 msgstr ""
 
-#: src/rest/plugin_rest_copying.c:209
+#: src/rest/plugin_rest_copying.c:211
 msgid "COPYING REST API initialized\n"
 msgstr ""
 
@@ -5951,24 +5959,24 @@ msgstr ""
 msgid "# revocation messages received via set union"
 msgstr ""
 
-#: src/revocation/gnunet-service-revocation.c:470
+#: src/revocation/gnunet-service-revocation.c:469
 #, c-format
 msgid "Error computing revocation set union with %s\n"
 msgstr ""
 
-#: src/revocation/gnunet-service-revocation.c:474
+#: src/revocation/gnunet-service-revocation.c:473
 msgid "# revocation set unions failed"
 msgstr ""
 
-#: src/revocation/gnunet-service-revocation.c:486
+#: src/revocation/gnunet-service-revocation.c:481
 msgid "# revocation set unions completed"
 msgstr ""
 
-#: src/revocation/gnunet-service-revocation.c:526
+#: src/revocation/gnunet-service-revocation.c:519
 msgid "SET service crashed, terminating revocation service\n"
 msgstr ""
 
-#: src/revocation/gnunet-service-revocation.c:881
+#: src/revocation/gnunet-service-revocation.c:871
 msgid "Could not open revocation database file!"
 msgstr ""
 
@@ -6055,10 +6063,10 @@ msgstr ""
 msgid "Calculate the Vectorproduct with a GNUnet peer."
 msgstr ""
 
-#: src/scalarproduct/gnunet-service-scalarproduct_alice.c:1363
-#: src/scalarproduct/gnunet-service-scalarproduct_bob.c:1366
-#: src/scalarproduct/gnunet-service-scalarproduct-ecc_alice.c:1127
-#: src/scalarproduct/gnunet-service-scalarproduct-ecc_bob.c:1073
+#: src/scalarproduct/gnunet-service-scalarproduct_alice.c:1358
+#: src/scalarproduct/gnunet-service-scalarproduct_bob.c:1355
+#: src/scalarproduct/gnunet-service-scalarproduct-ecc_alice.c:1118
+#: src/scalarproduct/gnunet-service-scalarproduct-ecc_bob.c:1063
 msgid "Connect to CADET failed\n"
 msgstr ""
 
@@ -6082,51 +6090,62 @@ msgstr "threshold"
 msgid "also profile decryption"
 msgstr ""
 
-#: src/set/gnunet-service-set.c:1916
+#: src/set/gnunet-service-set.c:1916 src/seti/gnunet-service-seti.c:2467
+#: src/setu/gnunet-service-setu.c:3635
 #, fuzzy
 msgid "Could not connect to CADET service\n"
 msgstr "Impossible d’ouvrir « %s ».\n"
 
 #: src/set/gnunet-set-ibf-profiler.c:268
+#: src/setu/gnunet-setu-ibf-profiler.c:268
 msgid "number of element in set A-B"
 msgstr ""
 
 #: src/set/gnunet-set-ibf-profiler.c:274
+#: src/setu/gnunet-setu-ibf-profiler.c:274
 msgid "number of element in set B-A"
 msgstr ""
 
 #: src/set/gnunet-set-ibf-profiler.c:281
+#: src/setu/gnunet-setu-ibf-profiler.c:281
 msgid "number of common elements in A and B"
 msgstr ""
 
 #: src/set/gnunet-set-ibf-profiler.c:287
+#: src/setu/gnunet-setu-ibf-profiler.c:287
 msgid "hash num"
 msgstr "numéro de hash"
 
 #: src/set/gnunet-set-ibf-profiler.c:293
+#: src/setu/gnunet-setu-ibf-profiler.c:293
 msgid "ibf size"
 msgstr "taille ibz"
 
-#: src/set/gnunet-set-profiler.c:462
+#: src/set/gnunet-set-profiler.c:462 src/setu/gnunet-setu-profiler.c:453
 msgid "use byzantine mode"
 msgstr ""
 
-#: src/set/gnunet-set-profiler.c:468
+#: src/set/gnunet-set-profiler.c:468 src/setu/gnunet-setu-profiler.c:459
 msgid "force sending full set"
 msgstr ""
 
-#: src/set/gnunet-set-profiler.c:474
+#: src/set/gnunet-set-profiler.c:474 src/setu/gnunet-setu-profiler.c:465
 msgid "number delta operation"
 msgstr ""
 
-#: src/set/gnunet-set-profiler.c:486
+#: src/set/gnunet-set-profiler.c:486 src/setu/gnunet-setu-profiler.c:477
 msgid "operation to execute"
 msgstr ""
 
-#: src/set/gnunet-set-profiler.c:492
+#: src/set/gnunet-set-profiler.c:492 src/seti/gnunet-seti-profiler.c:462
+#: src/setu/gnunet-setu-profiler.c:483
 msgid "element size"
 msgstr ""
 
+#: src/seti/gnunet-seti-profiler.c:457
+msgid "return intersection instead of delta"
+msgstr ""
+
 #: src/sq/sq.c:54
 #, c-format
 msgid "Failure to bind %u-th SQL parameter\n"
@@ -6141,12 +6160,12 @@ msgstr ""
 msgid "Failed to reset sqlite statement with error: %s\n"
 msgstr "Échec du démarrage de %s\n"
 
-#: src/statistics/gnunet-service-statistics.c:318
+#: src/statistics/gnunet-service-statistics.c:319
 #, c-format
 msgid "Wrote %llu bytes of statistics to `%s'\n"
 msgstr ""
 
-#: src/statistics/gnunet-service-statistics.c:983
+#: src/statistics/gnunet-service-statistics.c:984
 #, c-format
 msgid "Loading %llu bytes of statistics from `%s'\n"
 msgstr ""
@@ -6326,7 +6345,7 @@ msgid ""
 msgstr ""
 
 #: src/testbed/gnunet-daemon-testbed-underlay.c:234 src/testing/list-keys.c:47
-#: src/testing/testing.c:284 src/util/gnunet-ecc.c:318
+#: src/testing/testing.c:278 src/util/gnunet-ecc.c:318
 #, c-format
 msgid "Incorrect hostkey file format: %s\n"
 msgstr ""
@@ -6579,57 +6598,57 @@ msgstr ""
 msgid "list COUNT number of keys"
 msgstr ""
 
-#: src/testing/testing.c:267
+#: src/testing/testing.c:261
 #, c-format
 msgid "Hostkeys file not found: %s\n"
 msgstr ""
 
-#: src/testing/testing.c:721
+#: src/testing/testing.c:714
 #, c-format
 msgid "Key number %u does not exist\n"
 msgstr ""
 
-#: src/testing/testing.c:1195
+#: src/testing/testing.c:1188
 #, c-format
 msgid ""
 "You attempted to create a testbed with more than %u hosts.  Please "
 "precompute more hostkeys first.\n"
 msgstr ""
 
-#: src/testing/testing.c:1204
+#: src/testing/testing.c:1197
 #, c-format
 msgid "Failed to initialize hostkey for peer %u\n"
 msgstr ""
 
-#: src/testing/testing.c:1214
+#: src/testing/testing.c:1207
 msgid "PRIVATE_KEY option in PEER section missing in configuration\n"
 msgstr ""
 
-#: src/testing/testing.c:1227
+#: src/testing/testing.c:1220
 msgid "Failed to create configuration for peer (not enough free ports?)\n"
 msgstr ""
 
-#: src/testing/testing.c:1243
+#: src/testing/testing.c:1236
 #, c-format
 msgid "Cannot open hostkey file `%s': %s\n"
 msgstr ""
 
-#: src/testing/testing.c:1257
+#: src/testing/testing.c:1250
 #, c-format
 msgid "Failed to write hostkey file for peer %u: %s\n"
 msgstr ""
 
-#: src/testing/testing.c:1285
+#: src/testing/testing.c:1278
 #, c-format
 msgid "Failed to write configuration file `%s' for peer %u: %s\n"
 msgstr ""
 
-#: src/testing/testing.c:1392
+#: src/testing/testing.c:1384
 #, c-format
 msgid "Failed to start `%s': %s\n"
 msgstr ""
 
-#: src/testing/testing.c:1691
+#: src/testing/testing.c:1683
 #, c-format
 msgid "Failed to load configuration from %s\n"
 msgstr ""
@@ -6703,37 +6722,37 @@ msgstr ""
 msgid "GNUnet topology control"
 msgstr ""
 
-#: src/transport/gnunet-communicator-tcp.c:2458
-#: src/transport/gnunet-communicator-udp.c:2825
-#: src/transport/gnunet-service-tng.c:10027
+#: src/transport/gnunet-communicator-tcp.c:3189
+#: src/transport/gnunet-communicator-udp.c:2826
+#: src/transport/gnunet-service-tng.c:10014
 #: src/transport/gnunet-service-transport.c:2624
 msgid "Transport service is lacking key configuration settings. Exiting.\n"
 msgstr ""
 
-#: src/transport/gnunet-communicator-tcp.c:2754
+#: src/transport/gnunet-communicator-tcp.c:3494
 msgid "GNUnet TCP communicator"
 msgstr ""
 
-#: src/transport/gnunet-communicator-udp.c:2897
+#: src/transport/gnunet-communicator-udp.c:2898
 msgid "GNUnet UDP communicator"
 msgstr ""
 
-#: src/transport/gnunet-communicator-unix.c:788
+#: src/transport/gnunet-communicator-unix.c:789
 msgid ""
 "Maximum number of UNIX connections exceeded, dropping incoming message\n"
 msgstr ""
 
-#: src/transport/gnunet-communicator-unix.c:1015
+#: src/transport/gnunet-communicator-unix.c:1016
 msgid "UNIX communicator is lacking key configuration settings. Exiting.\n"
 msgstr ""
 
-#: src/transport/gnunet-communicator-unix.c:1060
+#: src/transport/gnunet-communicator-unix.c:1061
 #: src/transport/plugin_transport_unix.c:1383
 #, c-format
 msgid "Cannot create path to `%s'\n"
 msgstr ""
 
-#: src/transport/gnunet-communicator-unix.c:1138
+#: src/transport/gnunet-communicator-unix.c:1139
 msgid "GNUnet UNIX domain socket communicator"
 msgstr ""
 
@@ -7756,7 +7775,7 @@ msgid "do daemonize (detach from terminal)"
 msgstr ""
 
 #: src/transport/tcp_service_legacy.c:1397
-#: src/transport/transport-testing2.c:1061 src/util/service.c:2072
+#: src/transport/transport-testing2.c:1116 src/util/service.c:2072
 #: src/util/service.c:2084
 #, c-format
 msgid "Malformed configuration file `%s', exit ...\n"
@@ -7798,7 +7817,7 @@ msgstr ""
 msgid "Invalid handle type while reading `%s'"
 msgstr ""
 
-#: src/util/bio.c:335 src/util/bio.c:838
+#: src/util/bio.c:335 src/util/bio.c:839
 msgid "string length"
 msgstr ""
 
@@ -7817,7 +7836,7 @@ msgstr ""
 msgid "String `%s' longer than allowed (%u > %u)"
 msgstr ""
 
-#: src/util/bio.c:398 src/util/bio.c:863 src/util/bio.c:880
+#: src/util/bio.c:398 src/util/bio.c:864 src/util/bio.c:881
 msgid "metadata length"
 msgstr ""
 
@@ -7831,25 +7850,25 @@ msgstr ""
 msgid "Failed to deserialize metadata `%s'"
 msgstr "Résolution de « %s » échouée\n"
 
-#: src/util/bio.c:667
+#: src/util/bio.c:668
 msgid "Unable to flush buffer to file"
 msgstr ""
 
-#: src/util/bio.c:729 src/util/bio.c:750
+#: src/util/bio.c:730 src/util/bio.c:751
 #, fuzzy, c-format
 msgid "Error while writing `%s' to file: %s"
 msgstr "Erreur de lecture : « %s » : %s"
 
-#: src/util/bio.c:731
+#: src/util/bio.c:732
 msgid "No associated file"
 msgstr ""
 
-#: src/util/bio.c:815
+#: src/util/bio.c:816
 #, c-format
 msgid "Invalid handle type while writing `%s'"
 msgstr ""
 
-#: src/util/bio.c:875
+#: src/util/bio.c:876
 #, fuzzy, c-format
 msgid "Failed to serialize metadata `%s'"
 msgstr "Échec du démarrage de %s\n"
@@ -8331,15 +8350,15 @@ msgstr ""
 msgid "No handler known for subsystem `%s'\n"
 msgstr ""
 
-#: src/util/gnunet-qr.c:358
+#: src/util/gnunet-qr.c:357
 msgid "use video-device DEVICE (default: /dev/video0"
 msgstr ""
 
-#: src/util/gnunet-qr.c:363
+#: src/util/gnunet-qr.c:362
 msgid "do not show preview windows"
 msgstr ""
 
-#: src/util/gnunet-qr.c:373
+#: src/util/gnunet-qr.c:372
 msgid "Scan a QR code using a video device and import the uri read"
 msgstr ""
 
@@ -8351,28 +8370,28 @@ msgstr ""
 msgid "Use build-in GNUnet stub resolver"
 msgstr ""
 
-#: src/util/gnunet-scrypt.c:222
+#: src/util/gnunet-scrypt.c:229
 #, c-format
 msgid "Loading hostkey from `%s' failed.\n"
 msgstr ""
 
-#: src/util/gnunet-scrypt.c:288
+#: src/util/gnunet-scrypt.c:295
 msgid "number of bits to require for the proof of work"
 msgstr ""
 
-#: src/util/gnunet-scrypt.c:294
+#: src/util/gnunet-scrypt.c:301
 msgid "file with private key, otherwise default is used"
 msgstr ""
 
-#: src/util/gnunet-scrypt.c:300
+#: src/util/gnunet-scrypt.c:307
 msgid "file with proof of work, otherwise default is used"
 msgstr ""
 
-#: src/util/gnunet-scrypt.c:306
+#: src/util/gnunet-scrypt.c:313
 msgid "time to wait between calculations"
 msgstr ""
 
-#: src/util/gnunet-scrypt.c:319
+#: src/util/gnunet-scrypt.c:326
 msgid "Manipulate GNUnet proof of work files"
 msgstr ""
 
@@ -8385,7 +8404,7 @@ msgstr ""
 msgid "No URI specified on command line\n"
 msgstr ""
 
-#: src/util/gnunet-uri.c:179
+#: src/util/gnunet-uri.c:178
 msgid "Perform default-actions for GNUnet URIs"
 msgstr ""
 
@@ -8399,7 +8418,7 @@ msgstr ""
 msgid "Failed to parse inbound message from helper `%s'\n"
 msgstr ""
 
-#: src/util/helper.c:600
+#: src/util/helper.c:602
 #, c-format
 msgid "Error writing to `%s': %s\n"
 msgstr ""
@@ -8526,116 +8545,116 @@ msgstr ""
 msgid "Attempting to proxy service `%s' to invalid port %d or hostname.\n"
 msgstr ""
 
-#: src/util/strings.c:178
+#: src/util/strings.c:179
 msgid "b"
 msgstr "o"
 
-#: src/util/strings.c:502
+#: src/util/strings.c:503
 #, c-format
 msgid "Character sets requested were `%s'->`%s'\n"
 msgstr ""
 
-#: src/util/strings.c:636
+#: src/util/strings.c:637
 msgid "Failed to expand `$HOME': environment variable `HOME' not set"
 msgstr ""
 
-#: src/util/strings.c:705
+#: src/util/strings.c:706
 msgid "µs"
 msgstr "µs"
 
-#: src/util/strings.c:709
+#: src/util/strings.c:710
 msgid "forever"
 msgstr "perpetuel"
 
-#: src/util/strings.c:711
+#: src/util/strings.c:712
 msgid "0 ms"
 msgstr "0 ms"
 
-#: src/util/strings.c:715
+#: src/util/strings.c:716
 msgid "ms"
 msgstr "ms"
 
-#: src/util/strings.c:719
+#: src/util/strings.c:720
 msgid "s"
 msgstr "s"
 
-#: src/util/strings.c:723
+#: src/util/strings.c:724
 msgid "m"
 msgstr "m"
 
-#: src/util/strings.c:727
+#: src/util/strings.c:728
 msgid "h"
 msgstr "h"
 
-#: src/util/strings.c:733
+#: src/util/strings.c:734
 msgid "day"
 msgstr "jour"
 
-#: src/util/strings.c:735
+#: src/util/strings.c:736
 msgid "days"
 msgstr "jours"
 
-#: src/util/strings.c:763
+#: src/util/strings.c:764
 msgid "end of time"
 msgstr "fin du temps"
 
-#: src/util/strings.c:1239
+#: src/util/strings.c:1240
 msgid "IPv6 address did not start with `['\n"
 msgstr ""
 
-#: src/util/strings.c:1247
+#: src/util/strings.c:1248
 msgid "IPv6 address did contain ':' to separate port number\n"
 msgstr ""
 
-#: src/util/strings.c:1254
+#: src/util/strings.c:1255
 msgid "IPv6 address did contain ']' before ':' to separate port number\n"
 msgstr ""
 
-#: src/util/strings.c:1262
+#: src/util/strings.c:1263
 msgid "IPv6 address did contain a valid port number after the last ':'\n"
 msgstr ""
 
-#: src/util/strings.c:1271
+#: src/util/strings.c:1272
 #, c-format
 msgid "Invalid IPv6 address `%s': %s\n"
 msgstr ""
 
-#: src/util/strings.c:1498 src/util/strings.c:1509
+#: src/util/strings.c:1499 src/util/strings.c:1510
 msgid "Port not in range\n"
 msgstr ""
 
-#: src/util/strings.c:1518
+#: src/util/strings.c:1519
 #, c-format
 msgid "Malformed port policy `%s'\n"
 msgstr ""
 
-#: src/util/strings.c:1601 src/util/strings.c:1630 src/util/strings.c:1677
-#: src/util/strings.c:1697
+#: src/util/strings.c:1602 src/util/strings.c:1631 src/util/strings.c:1678
+#: src/util/strings.c:1698
 #, c-format
 msgid "Invalid format for IP: `%s'\n"
 msgstr ""
 
-#: src/util/strings.c:1655
+#: src/util/strings.c:1656
 #, c-format
 msgid "Invalid network notation ('/%d' is not legal in IPv4 CIDR)."
 msgstr ""
 
-#: src/util/strings.c:1706
+#: src/util/strings.c:1707
 #, c-format
 msgid "Invalid format: `%s'\n"
 msgstr "fornat invalide : « %s »\n"
 
-#: src/util/strings.c:1759
+#: src/util/strings.c:1760
 #, c-format
 msgid "Invalid network notation (does not end with ';': `%s')\n"
 msgstr ""
 
-#: src/util/strings.c:1809
+#: src/util/strings.c:1810
 #, c-format
 msgid "Wrong format `%s' for netmask\n"
 msgstr ""
 
-#: src/util/strings.c:1840
+#: src/util/strings.c:1841
 #, c-format
 msgid "Wrong format `%s' for network\n"
 msgstr ""
diff --git a/po/it.po b/po/it.po
index fcf7d6d7a7488ef56e311d05bd0ba13fe5845c6f..278ad6e5777ee5c7c2eea052b93f1c44352926d9 100644
--- a/po/it.po
+++ b/po/it.po
@@ -8,7 +8,7 @@ msgid ""
 msgstr ""
 "Project-Id-Version: gnunet 0.10.1\n"
 "Report-Msgid-Bugs-To: gnunet-developers@mail.gnu.org\n"
-"POT-Creation-Date: 2020-07-12 17:55+0200\n"
+"POT-Creation-Date: 2020-09-06 10:07+0200\n"
 "PO-Revision-Date: 2019-10-16 11:00+0200\n"
 "Last-Translator: Sebastiano Pistore <sebastianopistore.info@protonmail.ch>\n"
 "Language-Team: Italian <tp@lists.linux.it>\n"
@@ -20,12 +20,12 @@ msgstr ""
 "X-Generator: Poedit 2.2.3\n"
 "Plural-Forms: nplurals=2; plural=(n != 1);\n"
 
-#: src/abd/gnunet-abd.c:397 src/namestore/gnunet-namestore.c:1302
+#: src/abd/gnunet-abd.c:397 src/namestore/gnunet-namestore.c:1303
 #, c-format
 msgid "Ego `%s' not known to identity service\n"
 msgstr ""
 
-#: src/abd/gnunet-abd.c:413 src/abd/gnunet-abd.c:896
+#: src/abd/gnunet-abd.c:413 src/abd/gnunet-abd.c:901
 #, c-format
 msgid "Issuer public key `%s' is not well-formed\n"
 msgstr ""
@@ -37,106 +37,106 @@ msgstr ""
 msgid "Failed to connect to namestore\n"
 msgstr ""
 
-#: src/abd/gnunet-abd.c:835 src/abd/gnunet-abd.c:886
+#: src/abd/gnunet-abd.c:840 src/abd/gnunet-abd.c:891
 #, c-format
 msgid "Issuer public key not well-formed\n"
 msgstr ""
 
-#: src/abd/gnunet-abd.c:844 src/abd/gnunet-abd.c:905
+#: src/abd/gnunet-abd.c:849 src/abd/gnunet-abd.c:910
 #, fuzzy, c-format
 msgid "Failed to connect to ABD\n"
 msgstr "Impossibile avviare il servizio.\n"
 
-#: src/abd/gnunet-abd.c:850
+#: src/abd/gnunet-abd.c:855
 #, c-format
 msgid "You must provide issuer the attribute\n"
 msgstr ""
 
-#: src/abd/gnunet-abd.c:857
+#: src/abd/gnunet-abd.c:862
 #, c-format
 msgid "ego required\n"
 msgstr ""
 
-#: src/abd/gnunet-abd.c:867
+#: src/abd/gnunet-abd.c:872
 #, c-format
 msgid "Subject public key needed\n"
 msgstr ""
 
-#: src/abd/gnunet-abd.c:876
+#: src/abd/gnunet-abd.c:881
 #, c-format
 msgid "Subject public key `%s' is not well-formed\n"
 msgstr ""
 
-#: src/abd/gnunet-abd.c:911
+#: src/abd/gnunet-abd.c:916
 #, c-format
 msgid "You must provide issuer and subject attributes\n"
 msgstr ""
 
-#: src/abd/gnunet-abd.c:970
+#: src/abd/gnunet-abd.c:975
 #, c-format
 msgid "Please specify name to lookup, subject key and issuer key!\n"
 msgstr ""
 
-#: src/abd/gnunet-abd.c:991
+#: src/abd/gnunet-abd.c:996
 msgid "verify credential against attribute"
 msgstr ""
 
-#: src/abd/gnunet-abd.c:998
+#: src/abd/gnunet-abd.c:1003
 msgid ""
 "The public key of the subject to lookup thecredential for, or for issuer "
 "side storage: subject and its attributes"
 msgstr ""
 
-#: src/abd/gnunet-abd.c:1005
+#: src/abd/gnunet-abd.c:1010
 msgid "The private, signed delegate presented by the subject"
 msgstr ""
 
-#: src/abd/gnunet-abd.c:1012
+#: src/abd/gnunet-abd.c:1017
 msgid "The public key of the authority to verify the credential against"
 msgstr ""
 
-#: src/abd/gnunet-abd.c:1017
+#: src/abd/gnunet-abd.c:1022
 msgid "The ego/zone name to use"
 msgstr ""
 
-#: src/abd/gnunet-abd.c:1023
+#: src/abd/gnunet-abd.c:1028
 msgid "The issuer attribute to verify against or to issue"
 msgstr ""
 
-#: src/abd/gnunet-abd.c:1029
+#: src/abd/gnunet-abd.c:1034
 msgid ""
 "The time to live for the credential.e.g. 5m, 6h, \"1990-12-30 12:00:00\""
 msgstr ""
 
-#: src/abd/gnunet-abd.c:1034
+#: src/abd/gnunet-abd.c:1039
 msgid "collect credentials"
 msgstr ""
 
-#: src/abd/gnunet-abd.c:1039
+#: src/abd/gnunet-abd.c:1044
 msgid "Create and issue a credential issuer side."
 msgstr ""
 
-#: src/abd/gnunet-abd.c:1044
+#: src/abd/gnunet-abd.c:1049
 msgid "Issue a credential subject side."
 msgstr ""
 
-#: src/abd/gnunet-abd.c:1049
+#: src/abd/gnunet-abd.c:1054
 msgid "Create, sign and return a credential subject side."
 msgstr ""
 
-#: src/abd/gnunet-abd.c:1056
+#: src/abd/gnunet-abd.c:1061
 msgid "Import signed credentials that should be issued to a zone/ego"
 msgstr ""
 
-#: src/abd/gnunet-abd.c:1060
+#: src/abd/gnunet-abd.c:1065
 msgid "Create private record entry."
 msgstr ""
 
-#: src/abd/gnunet-abd.c:1066 src/abd/gnunet-abd.c:1072
+#: src/abd/gnunet-abd.c:1071 src/abd/gnunet-abd.c:1077
 msgid "Indicates that the collect/verify process is done via forward search."
 msgstr ""
 
-#: src/abd/gnunet-abd.c:1085
+#: src/abd/gnunet-abd.c:1090
 msgid "GNUnet abd resolver tool"
 msgstr ""
 
@@ -426,64 +426,64 @@ msgstr ""
 msgid "Failed to find %saddress for `%s'.\n"
 msgstr ""
 
-#: src/arm/gnunet-service-arm.c:933
+#: src/arm/gnunet-service-arm.c:951
 #, c-format
 msgid "Failed to start service `%s'\n"
 msgstr "Impossibile avviare il servizio ' %s'\n"
 
-#: src/arm/gnunet-service-arm.c:944
+#: src/arm/gnunet-service-arm.c:962
 #, c-format
 msgid "Starting service `%s'\n"
 msgstr "Avvio del servizio '%s' in corso\n"
 
-#: src/arm/gnunet-service-arm.c:1044
+#: src/arm/gnunet-service-arm.c:1062
 #, c-format
 msgid "Unable to create socket for service `%s': %s\n"
 msgstr ""
 
-#: src/arm/gnunet-service-arm.c:1075
+#: src/arm/gnunet-service-arm.c:1093
 #, c-format
 msgid "Unable to bind listening socket for service `%s' to address `%s': %s\n"
 msgstr ""
 
-#: src/arm/gnunet-service-arm.c:1106
+#: src/arm/gnunet-service-arm.c:1124
 #, c-format
 msgid "ARM now monitors connections to service `%s' at `%s'\n"
 msgstr ""
 
-#: src/arm/gnunet-service-arm.c:1254
+#: src/arm/gnunet-service-arm.c:1272
 #, c-format
 msgid "Preparing to stop `%s'\n"
 msgstr ""
 
-#: src/arm/gnunet-service-arm.c:1586
+#: src/arm/gnunet-service-arm.c:1604
 #, c-format
 msgid "Restarting service `%s'.\n"
 msgstr ""
 
-#: src/arm/gnunet-service-arm.c:1737
+#: src/arm/gnunet-service-arm.c:1755
 msgid "exit"
 msgstr "uscita"
 
-#: src/arm/gnunet-service-arm.c:1742
+#: src/arm/gnunet-service-arm.c:1760
 msgid "signal"
 msgstr ""
 
-#: src/arm/gnunet-service-arm.c:1747
+#: src/arm/gnunet-service-arm.c:1765
 msgid "unknown"
 msgstr "sconosciuto"
 
-#: src/arm/gnunet-service-arm.c:1753
+#: src/arm/gnunet-service-arm.c:1771
 #, c-format
 msgid "Service `%s' took %s to terminate\n"
 msgstr ""
 
-#: src/arm/gnunet-service-arm.c:1780
+#: src/arm/gnunet-service-arm.c:1798
 #, c-format
 msgid "Service `%s' terminated normally, will restart at any time\n"
 msgstr ""
 
-#: src/arm/gnunet-service-arm.c:1797
+#: src/arm/gnunet-service-arm.c:1815
 #, c-format
 msgid "Service `%s' terminated with status %s/%d, will restart in %s\n"
 msgstr ""
@@ -806,7 +806,10 @@ msgstr ""
 
 #: src/consensus/gnunet-consensus-profiler.c:543
 #: src/set/gnunet-set-profiler.c:451 src/set/gnunet-set-profiler.c:457
-#: src/set/gnunet-set-profiler.c:480
+#: src/set/gnunet-set-profiler.c:480 src/seti/gnunet-seti-profiler.c:441
+#: src/seti/gnunet-seti-profiler.c:446 src/seti/gnunet-seti-profiler.c:451
+#: src/setu/gnunet-setu-profiler.c:442 src/setu/gnunet-setu-profiler.c:448
+#: src/setu/gnunet-setu-profiler.c:471
 msgid "number of values"
 msgstr ""
 
@@ -819,7 +822,8 @@ msgid "delay until consensus starts"
 msgstr ""
 
 #: src/consensus/gnunet-consensus-profiler.c:563
-#: src/set/gnunet-set-profiler.c:498
+#: src/set/gnunet-set-profiler.c:498 src/seti/gnunet-seti-profiler.c:467
+#: src/setu/gnunet-setu-profiler.c:489
 msgid "write statistics to file"
 msgstr ""
 
@@ -1351,139 +1355,139 @@ msgstr ""
 msgid "Core service of `%s' ready.\n"
 msgstr "Avvio del servizio '%s' in corso\n"
 
-#: src/core/gnunet-service-core_kx.c:625
+#: src/core/gnunet-service-core_kx.c:512
 msgid "# bytes encrypted"
 msgstr "# byte crittografati"
 
-#: src/core/gnunet-service-core_kx.c:683
+#: src/core/gnunet-service-core_kx.c:570
 msgid "# bytes decrypted"
 msgstr "# byte decrittati"
 
-#: src/core/gnunet-service-core_kx.c:780
+#: src/core/gnunet-service-core_kx.c:667
 msgid "# PAYLOAD dropped (out of order)"
 msgstr ""
 
-#: src/core/gnunet-service-core_kx.c:832
+#: src/core/gnunet-service-core_kx.c:719
 msgid "# key exchanges initiated"
 msgstr ""
 
-#: src/core/gnunet-service-core_kx.c:888
+#: src/core/gnunet-service-core_kx.c:775
 msgid "# key exchanges stopped"
 msgstr ""
 
-#: src/core/gnunet-service-core_kx.c:920
+#: src/core/gnunet-service-core_kx.c:807
 msgid "# PING messages transmitted"
 msgstr "# Messaggi PING trasmessi"
 
-#: src/core/gnunet-service-core_kx.c:979
+#: src/core/gnunet-service-core_kx.c:866
 msgid "# old ephemeral keys ignored"
 msgstr ""
 
-#: src/core/gnunet-service-core_kx.c:993
+#: src/core/gnunet-service-core_kx.c:880
 #, fuzzy
 msgid "# duplicate ephemeral keys ignored"
 msgstr "# messaggi PONG ricevuti"
 
-#: src/core/gnunet-service-core_kx.c:1028
+#: src/core/gnunet-service-core_kx.c:915
 #, fuzzy
 msgid "# EPHEMERAL_KEYs rejected (bad signature)"
 msgstr "# messaggi SYN ricevuti"
 
-#: src/core/gnunet-service-core_kx.c:1046
+#: src/core/gnunet-service-core_kx.c:933
 #, c-format
 msgid ""
 "EPHEMERAL_KEY from peer `%s' rejected as its validity range does not match "
 "our system time (%llu not in [%llu,%llu]).\n"
 msgstr ""
 
-#: src/core/gnunet-service-core_kx.c:1053
+#: src/core/gnunet-service-core_kx.c:940
 #, fuzzy
 msgid "# EPHEMERAL_KEY messages rejected due to time"
 msgstr "# messaggi SYN ricevuti"
 
-#: src/core/gnunet-service-core_kx.c:1071
+#: src/core/gnunet-service-core_kx.c:958
 #, fuzzy
 msgid "# valid ephemeral keys received"
 msgstr "# messaggi PONG ricevuti"
 
-#: src/core/gnunet-service-core_kx.c:1180
+#: src/core/gnunet-service-core_kx.c:1067
 #: src/transport/gnunet-service-transport_validation.c:1133
 msgid "# PING messages received"
 msgstr ""
 
-#: src/core/gnunet-service-core_kx.c:1190
+#: src/core/gnunet-service-core_kx.c:1077
 msgid "# PING messages dropped (out of order)"
 msgstr ""
 
-#: src/core/gnunet-service-core_kx.c:1239
+#: src/core/gnunet-service-core_kx.c:1126
 msgid "# PONG messages created"
 msgstr ""
 
-#: src/core/gnunet-service-core_kx.c:1264
+#: src/core/gnunet-service-core_kx.c:1151
 msgid "# sessions terminated by timeout"
 msgstr ""
 
-#: src/core/gnunet-service-core_kx.c:1277
+#: src/core/gnunet-service-core_kx.c:1164
 msgid "# keepalive messages sent"
 msgstr ""
 
-#: src/core/gnunet-service-core_kx.c:1334
+#: src/core/gnunet-service-core_kx.c:1221
 #: src/transport/gnunet-service-transport_validation.c:1476
 msgid "# PONG messages received"
 msgstr "# messaggi PONG ricevuti"
 
-#: src/core/gnunet-service-core_kx.c:1342
+#: src/core/gnunet-service-core_kx.c:1229
 msgid "# PONG messages dropped (connection down)"
 msgstr ""
 
-#: src/core/gnunet-service-core_kx.c:1350
+#: src/core/gnunet-service-core_kx.c:1237
 msgid "# PONG messages dropped (out of order)"
 msgstr ""
 
-#: src/core/gnunet-service-core_kx.c:1389
+#: src/core/gnunet-service-core_kx.c:1276
 msgid "# PONG messages decrypted"
 msgstr "# messaggi PONG decrittati"
 
-#: src/core/gnunet-service-core_kx.c:1429
+#: src/core/gnunet-service-core_kx.c:1316
 msgid "# session keys confirmed via PONG"
 msgstr ""
 
-#: src/core/gnunet-service-core_kx.c:1441
+#: src/core/gnunet-service-core_kx.c:1328
 msgid "# timeouts prevented via PONG"
 msgstr ""
 
-#: src/core/gnunet-service-core_kx.c:1450
+#: src/core/gnunet-service-core_kx.c:1337
 msgid "# rekey operations confirmed via PONG"
 msgstr ""
 
-#: src/core/gnunet-service-core_kx.c:1626
+#: src/core/gnunet-service-core_kx.c:1513
 msgid "# DATA message dropped (out of order)"
 msgstr ""
 
-#: src/core/gnunet-service-core_kx.c:1637
+#: src/core/gnunet-service-core_kx.c:1524
 #, c-format
 msgid ""
 "Session to peer `%s' went down due to key expiration (should not happen)\n"
 msgstr ""
 
-#: src/core/gnunet-service-core_kx.c:1641
+#: src/core/gnunet-service-core_kx.c:1528
 msgid "# sessions terminated by key expiration"
 msgstr ""
 
-#: src/core/gnunet-service-core_kx.c:1719
-#: src/core/gnunet-service-core_kx.c:1746
+#: src/core/gnunet-service-core_kx.c:1606
+#: src/core/gnunet-service-core_kx.c:1633
 msgid "# bytes dropped (duplicates)"
 msgstr ""
 
-#: src/core/gnunet-service-core_kx.c:1732
+#: src/core/gnunet-service-core_kx.c:1619
 msgid "# bytes dropped (out of sequence)"
 msgstr ""
 
-#: src/core/gnunet-service-core_kx.c:1777
+#: src/core/gnunet-service-core_kx.c:1664
 msgid "# bytes dropped (ancient message)"
 msgstr ""
 
-#: src/core/gnunet-service-core_kx.c:1786
+#: src/core/gnunet-service-core_kx.c:1673
 msgid "# bytes of payload decrypted"
 msgstr ""
 
@@ -3026,18 +3030,18 @@ msgstr ""
 msgid "Failed to load state: %s\n"
 msgstr ""
 
-#: src/fs/gnunet-auto-share.c:286 src/fs/gnunet-auto-share.c:295
-#: src/fs/gnunet-auto-share.c:303
+#: src/fs/gnunet-auto-share.c:287 src/fs/gnunet-auto-share.c:296
+#: src/fs/gnunet-auto-share.c:304
 #, c-format
 msgid "Failed to save state to file %s\n"
 msgstr ""
 
-#: src/fs/gnunet-auto-share.c:400
+#: src/fs/gnunet-auto-share.c:401
 #, c-format
 msgid "Publication of `%s' done\n"
 msgstr ""
 
-#: src/fs/gnunet-auto-share.c:479
+#: src/fs/gnunet-auto-share.c:480
 #, c-format
 msgid "Publishing `%s'\n"
 msgstr ""
@@ -3834,38 +3838,38 @@ msgstr ""
 msgid "GNUnet HTTP server to create business cards"
 msgstr ""
 
-#: src/gns/gnunet-dns2gns.c:239
+#: src/gns/gnunet-dns2gns.c:241
 msgid "Failed to pack DNS response into UDP packet!\n"
 msgstr ""
 
-#: src/gns/gnunet-dns2gns.c:442
+#: src/gns/gnunet-dns2gns.c:444
 #, c-format
 msgid "Cannot parse DNS request from %s\n"
 msgstr ""
 
-#: src/gns/gnunet-dns2gns.c:458
+#: src/gns/gnunet-dns2gns.c:460
 #, c-format
 msgid "Received malformed DNS request from %s\n"
 msgstr ""
 
-#: src/gns/gnunet-dns2gns.c:466
+#: src/gns/gnunet-dns2gns.c:468
 #, c-format
 msgid "Received unsupported DNS request from %s\n"
 msgstr ""
 
-#: src/gns/gnunet-dns2gns.c:627
+#: src/gns/gnunet-dns2gns.c:629
 msgid "No DNS server specified!\n"
 msgstr ""
 
-#: src/gns/gnunet-dns2gns.c:776
+#: src/gns/gnunet-dns2gns.c:778
 msgid "IP of recursive DNS resolver to use (required)"
 msgstr ""
 
-#: src/gns/gnunet-dns2gns.c:782
+#: src/gns/gnunet-dns2gns.c:784
 msgid "UDP port to listen on for inbound DNS requests; default: 2853"
 msgstr ""
 
-#: src/gns/gnunet-dns2gns.c:799
+#: src/gns/gnunet-dns2gns.c:801
 msgid "GNUnet DNS-to-GNS proxy (a DNS server)"
 msgstr ""
 
@@ -4003,7 +4007,7 @@ msgstr "Generazione statistiche fallita\n"
 msgid "Failed to start HTTPS server for `%s'\n"
 msgstr ""
 
-#: src/gns/gnunet-gns-proxy.c:2922 src/rest/gnunet-rest-server.c:713
+#: src/gns/gnunet-gns-proxy.c:2922 src/rest/gnunet-rest-server.c:917
 msgid "Failed to pass client to MHD\n"
 msgstr ""
 
@@ -4154,7 +4158,7 @@ msgstr ""
 msgid "Unable to parse BOX record string `%s'\n"
 msgstr "Impossibile avviare il servizio ' %s'\n"
 
-#: src/gns/plugin_rest_gns.c:445
+#: src/gns/plugin_rest_gns.c:447
 msgid "Gns REST API initialized\n"
 msgstr ""
 
@@ -4347,7 +4351,7 @@ msgid "# valid HELLOs downloaded from hostlist servers"
 msgstr ""
 
 #: src/hostlist/gnunet-daemon-hostlist_client.c:677
-#: src/hostlist/gnunet-daemon-hostlist_client.c:1459
+#: src/hostlist/gnunet-daemon-hostlist_client.c:1460
 msgid "# advertised hostlist URIs"
 msgstr ""
 
@@ -4398,7 +4402,7 @@ msgid "# hostlist downloads initiated"
 msgstr ""
 
 #: src/hostlist/gnunet-daemon-hostlist_client.c:1144
-#: src/hostlist/gnunet-daemon-hostlist_client.c:1726
+#: src/hostlist/gnunet-daemon-hostlist_client.c:1728
 msgid "# milliseconds between hostlist downloads"
 msgstr ""
 
@@ -4427,50 +4431,50 @@ msgstr ""
 msgid "Could not open file `%s' for reading to load hostlists: %s\n"
 msgstr ""
 
-#: src/hostlist/gnunet-daemon-hostlist_client.c:1452
+#: src/hostlist/gnunet-daemon-hostlist_client.c:1453
 #, c-format
 msgid "%u hostlist URIs loaded from file\n"
 msgstr ""
 
-#: src/hostlist/gnunet-daemon-hostlist_client.c:1455
+#: src/hostlist/gnunet-daemon-hostlist_client.c:1456
 msgid "# hostlist URIs read from file"
 msgstr ""
 
-#: src/hostlist/gnunet-daemon-hostlist_client.c:1506
+#: src/hostlist/gnunet-daemon-hostlist_client.c:1507
 #, c-format
 msgid "Could not open file `%s' for writing to save hostlists: %s\n"
 msgstr ""
 
-#: src/hostlist/gnunet-daemon-hostlist_client.c:1513
+#: src/hostlist/gnunet-daemon-hostlist_client.c:1514
 #, c-format
 msgid "Writing %u hostlist URIs to `%s'\n"
 msgstr ""
 
-#: src/hostlist/gnunet-daemon-hostlist_client.c:1545
-#: src/hostlist/gnunet-daemon-hostlist_client.c:1564
+#: src/hostlist/gnunet-daemon-hostlist_client.c:1547
+#: src/hostlist/gnunet-daemon-hostlist_client.c:1566
 #, c-format
 msgid "Error writing hostlist URIs to file `%s'\n"
 msgstr ""
 
-#: src/hostlist/gnunet-daemon-hostlist_client.c:1558
+#: src/hostlist/gnunet-daemon-hostlist_client.c:1560
 msgid "# hostlist URIs written to file"
 msgstr ""
 
-#: src/hostlist/gnunet-daemon-hostlist_client.c:1655
+#: src/hostlist/gnunet-daemon-hostlist_client.c:1657
 #: src/transport/plugin_transport_http_client.c:2301
 #, c-format
 msgid "Invalid proxy type: `%s', disabling proxy! Check configuration!\n"
 msgstr ""
 
-#: src/hostlist/gnunet-daemon-hostlist_client.c:1684
+#: src/hostlist/gnunet-daemon-hostlist_client.c:1686
 msgid "Learning is enabled on this peer\n"
 msgstr ""
 
-#: src/hostlist/gnunet-daemon-hostlist_client.c:1697
+#: src/hostlist/gnunet-daemon-hostlist_client.c:1699
 msgid "Learning is not enabled on this peer\n"
 msgstr ""
 
-#: src/hostlist/gnunet-daemon-hostlist_client.c:1711
+#: src/hostlist/gnunet-daemon-hostlist_client.c:1713
 #, c-format
 msgid ""
 "Since learning is not enabled on this peer, hostlist file `%s' was removed\n"
@@ -4594,47 +4598,47 @@ msgstr ""
 msgid "Failed to set default ego: %s\n"
 msgstr ""
 
-#: src/identity/gnunet-identity.c:445
+#: src/identity/gnunet-identity.c:446
 msgid "create ego NAME"
 msgstr ""
 
-#: src/identity/gnunet-identity.c:450
+#: src/identity/gnunet-identity.c:451
 msgid "delete ego NAME "
 msgstr ""
 
-#: src/identity/gnunet-identity.c:455
+#: src/identity/gnunet-identity.c:457
 msgid ""
 "set the private key for the identity to PRIVATE_KEY (use together with -C)"
 msgstr ""
 
-#: src/identity/gnunet-identity.c:459
+#: src/identity/gnunet-identity.c:461
 msgid "display all egos"
 msgstr ""
 
-#: src/identity/gnunet-identity.c:463
+#: src/identity/gnunet-identity.c:465
 msgid "reduce output"
 msgstr ""
 
-#: src/identity/gnunet-identity.c:470
+#: src/identity/gnunet-identity.c:472
 msgid ""
 "set default identity to NAME for a subsystem SUBSYSTEM (use together with -"
 "s) or restrict results to NAME (use together with -d)"
 msgstr ""
 
-#: src/identity/gnunet-identity.c:474
+#: src/identity/gnunet-identity.c:476
 msgid "run in monitor mode egos"
 msgstr ""
 
-#: src/identity/gnunet-identity.c:478
+#: src/identity/gnunet-identity.c:480
 msgid "display private keys as well"
 msgstr ""
 
-#: src/identity/gnunet-identity.c:485
+#: src/identity/gnunet-identity.c:487
 msgid ""
 "set default identity to EGO for a subsystem SUBSYSTEM (use together with -e)"
 msgstr ""
 
-#: src/identity/gnunet-identity.c:500
+#: src/identity/gnunet-identity.c:502
 msgid "Maintain egos"
 msgstr ""
 
@@ -4685,7 +4689,7 @@ msgstr ""
 msgid "Failed to create directory `%s' for storing egos\n"
 msgstr ""
 
-#: src/identity/plugin_rest_identity.c:1406
+#: src/identity/plugin_rest_identity.c:1384
 msgid "Identity REST API initialized\n"
 msgstr ""
 
@@ -4734,7 +4738,7 @@ msgstr "# messaggi PONG ricevuti"
 msgid "You must specify a name\n"
 msgstr "È necessario specificare un nome\n"
 
-#: src/namecache/gnunet-namecache.c:214 src/namestore/gnunet-namestore.c:1639
+#: src/namecache/gnunet-namecache.c:214 src/namestore/gnunet-namestore.c:1640
 msgid "name of the record to add/delete/display"
 msgstr ""
 
@@ -4742,7 +4746,7 @@ msgstr ""
 msgid "specifies the public key of the zone to look in"
 msgstr ""
 
-#: src/namecache/gnunet-namecache.c:233 src/namestore/gnunet-namestore.c:1700
+#: src/namecache/gnunet-namecache.c:233 src/namestore/gnunet-namestore.c:1701
 msgid "GNUnet zone manipulation tool"
 msgstr ""
 
@@ -4848,10 +4852,10 @@ msgstr "Impossibile avviare il servizio ' %s'\n"
 msgid "No options given\n"
 msgstr ""
 
-#: src/namestore/gnunet-namestore.c:1014 src/namestore/gnunet-namestore.c:1065
-#: src/namestore/gnunet-namestore.c:1075 src/namestore/gnunet-namestore.c:1104
-#: src/namestore/gnunet-namestore.c:1125 src/namestore/gnunet-namestore.c:1152
-#: src/namestore/gnunet-namestore.c:1228
+#: src/namestore/gnunet-namestore.c:1014 src/namestore/gnunet-namestore.c:1066
+#: src/namestore/gnunet-namestore.c:1076 src/namestore/gnunet-namestore.c:1105
+#: src/namestore/gnunet-namestore.c:1126 src/namestore/gnunet-namestore.c:1153
+#: src/namestore/gnunet-namestore.c:1229
 #, c-format
 msgid "Missing option `%s' for operation `%s'\n"
 msgstr ""
@@ -4865,53 +4869,53 @@ msgstr ""
 msgid "Invalid nick `%s'\n"
 msgstr ""
 
-#: src/namestore/gnunet-namestore.c:1067 src/namestore/gnunet-namestore.c:1077
-#: src/namestore/gnunet-namestore.c:1106 src/namestore/gnunet-namestore.c:1127
-#: src/namestore/gnunet-namestore.c:1230
+#: src/namestore/gnunet-namestore.c:1068 src/namestore/gnunet-namestore.c:1078
+#: src/namestore/gnunet-namestore.c:1107 src/namestore/gnunet-namestore.c:1128
+#: src/namestore/gnunet-namestore.c:1231
 msgid "add"
 msgstr ""
 
-#: src/namestore/gnunet-namestore.c:1085
+#: src/namestore/gnunet-namestore.c:1086
 #, c-format
 msgid "Unsupported type `%s'\n"
 msgstr ""
 
-#: src/namestore/gnunet-namestore.c:1095
+#: src/namestore/gnunet-namestore.c:1096
 #, c-format
 msgid "For DNS record types `SRV', `TLSA' and `OPENPGPKEY'"
 msgstr ""
 
-#: src/namestore/gnunet-namestore.c:1115
+#: src/namestore/gnunet-namestore.c:1116
 #, c-format
 msgid "Value `%s' invalid for record type `%s'\n"
 msgstr ""
 
-#: src/namestore/gnunet-namestore.c:1134 src/namestore/gnunet-namestore.c:1237
+#: src/namestore/gnunet-namestore.c:1135 src/namestore/gnunet-namestore.c:1238
 #, c-format
 msgid "Invalid time format `%s'\n"
 msgstr ""
 
-#: src/namestore/gnunet-namestore.c:1154
+#: src/namestore/gnunet-namestore.c:1155
 msgid "del"
 msgstr ""
 
-#: src/namestore/gnunet-namestore.c:1197
+#: src/namestore/gnunet-namestore.c:1198
 #, c-format
 msgid "Invalid public key for reverse lookup `%s'\n"
 msgstr ""
 
-#: src/namestore/gnunet-namestore.c:1220
+#: src/namestore/gnunet-namestore.c:1221
 #: src/peerinfo-tool/gnunet-peerinfo.c:736
 #, c-format
 msgid "Invalid URI `%s'\n"
 msgstr ""
 
-#: src/namestore/gnunet-namestore.c:1290
+#: src/namestore/gnunet-namestore.c:1291
 #, c-format
 msgid "Label `%s' contains `.' which is not allowed\n"
 msgstr ""
 
-#: src/namestore/gnunet-namestore.c:1340
+#: src/namestore/gnunet-namestore.c:1341
 #, c-format
 msgid ""
 "No default identity configured for `namestore' subsystem\n"
@@ -4919,99 +4923,99 @@ msgid ""
 "Run gnunet-identity -d to get a list of choices for $NAME\n"
 msgstr ""
 
-#: src/namestore/gnunet-namestore.c:1405
+#: src/namestore/gnunet-namestore.c:1406
 #, c-format
 msgid "Superfluous command line arguments (starting with `%s') ignored\n"
 msgstr ""
 
-#: src/namestore/gnunet-namestore.c:1434
+#: src/namestore/gnunet-namestore.c:1435
 #, c-format
 msgid "Cannot connect to identity service\n"
 msgstr ""
 
-#: src/namestore/gnunet-namestore.c:1481
+#: src/namestore/gnunet-namestore.c:1482
 msgid "Empty record line argument is not allowed.\n"
 msgstr ""
 
-#: src/namestore/gnunet-namestore.c:1493
+#: src/namestore/gnunet-namestore.c:1494
 #, c-format
 msgid "Invalid expiration time `%s' (must be without unit)\n"
 msgstr ""
 
-#: src/namestore/gnunet-namestore.c:1505 src/namestore/gnunet-namestore.c:1521
-#: src/namestore/gnunet-namestore.c:1538
+#: src/namestore/gnunet-namestore.c:1506 src/namestore/gnunet-namestore.c:1522
+#: src/namestore/gnunet-namestore.c:1539
 #, c-format
 msgid "Missing entries in record line `%s'.\n"
 msgstr ""
 
-#: src/namestore/gnunet-namestore.c:1513
+#: src/namestore/gnunet-namestore.c:1514
 #, fuzzy, c-format
 msgid "Unknown record type `%s'\n"
 msgstr "Comando `%s' sconosciuto.\n"
 
-#: src/namestore/gnunet-namestore.c:1551
+#: src/namestore/gnunet-namestore.c:1552
 #, fuzzy, c-format
 msgid "Invalid record data for type %s: `%s'.\n"
 msgstr "Indirizzo IPv6 non valido: `%s'\n"
 
-#: src/namestore/gnunet-namestore.c:1608
+#: src/namestore/gnunet-namestore.c:1609
 msgid "add record"
 msgstr ""
 
-#: src/namestore/gnunet-namestore.c:1611
+#: src/namestore/gnunet-namestore.c:1612
 msgid "delete record"
 msgstr ""
 
-#: src/namestore/gnunet-namestore.c:1615
+#: src/namestore/gnunet-namestore.c:1616
 msgid "display records"
 msgstr ""
 
-#: src/namestore/gnunet-namestore.c:1622
+#: src/namestore/gnunet-namestore.c:1623
 msgid ""
 "expiration time for record to use (for adding only), \"never\" is possible"
 msgstr ""
 
-#: src/namestore/gnunet-namestore.c:1628
+#: src/namestore/gnunet-namestore.c:1629
 msgid "set the desired nick name for the zone"
 msgstr ""
 
-#: src/namestore/gnunet-namestore.c:1633
+#: src/namestore/gnunet-namestore.c:1634
 msgid "monitor changes in the namestore"
 msgstr ""
 
-#: src/namestore/gnunet-namestore.c:1645
+#: src/namestore/gnunet-namestore.c:1646
 msgid "determine our name for the given PKEY"
 msgstr ""
 
-#: src/namestore/gnunet-namestore.c:1652
+#: src/namestore/gnunet-namestore.c:1653
 msgid ""
 "set record set to values given by (possibly multiple) RECORDLINES; can be "
 "specified multiple times"
 msgstr ""
 
-#: src/namestore/gnunet-namestore.c:1658
+#: src/namestore/gnunet-namestore.c:1659
 msgid "type of the record to add/delete/display"
 msgstr ""
 
-#: src/namestore/gnunet-namestore.c:1663
+#: src/namestore/gnunet-namestore.c:1664
 msgid "URI to import into our zone"
 msgstr ""
 
-#: src/namestore/gnunet-namestore.c:1669
+#: src/namestore/gnunet-namestore.c:1670
 msgid "value of the record to add/delete"
 msgstr ""
 
-#: src/namestore/gnunet-namestore.c:1673
+#: src/namestore/gnunet-namestore.c:1674
 msgid "create or list public record"
 msgstr ""
 
-#: src/namestore/gnunet-namestore.c:1679
+#: src/namestore/gnunet-namestore.c:1680
 msgid ""
 "create shadow record (only valid if all other records of the same type have "
 "expired"
 msgstr ""
 
-#: src/namestore/gnunet-namestore.c:1685
+#: src/namestore/gnunet-namestore.c:1686
 msgid "name of the ego controlling the zone"
 msgstr ""
 
@@ -5108,7 +5112,7 @@ msgstr ""
 msgid "Flat file database running\n"
 msgstr ""
 
-#: src/namestore/plugin_rest_namestore.c:1093
+#: src/namestore/plugin_rest_namestore.c:1103
 msgid "Namestore REST API initialized\n"
 msgstr ""
 
@@ -5370,7 +5374,7 @@ msgstr ""
 msgid "gnunet-helper-nat-server generated malformed address `%s'\n"
 msgstr ""
 
-#: src/nat/gnunet-service-nat_helper.c:250
+#: src/nat/gnunet-service-nat_helper.c:249
 #, c-format
 msgid "Failed to start %s\n"
 msgstr ""
@@ -5379,7 +5383,7 @@ msgstr ""
 msgid "`external-ip' command not found\n"
 msgstr ""
 
-#: src/nat/gnunet-service-nat_mini.c:608
+#: src/nat/gnunet-service-nat_mini.c:607
 msgid "`upnpc' command not found\n"
 msgstr ""
 
@@ -5411,8 +5415,8 @@ msgstr ""
 msgid "Measure quality and performance of the NSE service."
 msgstr ""
 
-#: src/nse/gnunet-service-nse.c:1438
-#: src/revocation/gnunet-service-revocation.c:842 src/util/gnunet-scrypt.c:250
+#: src/nse/gnunet-service-nse.c:1443
+#: src/revocation/gnunet-service-revocation.c:834 src/util/gnunet-scrypt.c:257
 msgid "Value is too large.\n"
 msgstr ""
 
@@ -5481,7 +5485,7 @@ msgid "\tExpires: %s \t %s\n"
 msgstr ""
 
 #: src/peerinfo-tool/gnunet-peerinfo.c:292
-#: src/peerinfo-tool/plugin_rest_peerinfo.c:501
+#: src/peerinfo-tool/plugin_rest_peerinfo.c:523
 #, fuzzy, c-format
 msgid "Failure: Cannot convert address to string for peer `%s'\n"
 msgstr "Impossibile avviare il servizio ' %s'\n"
@@ -5560,7 +5564,7 @@ msgstr ""
 msgid "Failed to load transport plugin for `%s'\n"
 msgstr ""
 
-#: src/peerinfo-tool/plugin_rest_peerinfo.c:797
+#: src/peerinfo-tool/plugin_rest_peerinfo.c:809
 msgid "Peerinfo REST API initialized\n"
 msgstr ""
 
@@ -5664,94 +5668,98 @@ msgstr ""
 msgid "Daemon to run to perform IP protocol translation to GNUnet"
 msgstr ""
 
-#: src/reclaim/gnunet-reclaim.c:799
+#: src/reclaim/gnunet-reclaim.c:801
 #, c-format
 msgid "Ego is required\n"
 msgstr ""
 
-#: src/reclaim/gnunet-reclaim.c:806
+#: src/reclaim/gnunet-reclaim.c:808
 #, c-format
 msgid "Attribute value missing!\n"
 msgstr ""
 
-#: src/reclaim/gnunet-reclaim.c:813
+#: src/reclaim/gnunet-reclaim.c:815
 #, c-format
 msgid "Requesting party key is required!\n"
 msgstr ""
 
-#: src/reclaim/gnunet-reclaim.c:831
+#: src/reclaim/gnunet-reclaim.c:833
 msgid "Add an attribute NAME"
 msgstr ""
 
-#: src/reclaim/gnunet-reclaim.c:836
+#: src/reclaim/gnunet-reclaim.c:838
 msgid "Delete the attribute with ID"
 msgstr ""
 
-#: src/reclaim/gnunet-reclaim.c:841
+#: src/reclaim/gnunet-reclaim.c:843
 msgid "The attribute VALUE"
 msgstr ""
 
-#: src/reclaim/gnunet-reclaim.c:846
+#: src/reclaim/gnunet-reclaim.c:848
 msgid "The EGO to use"
 msgstr ""
 
-#: src/reclaim/gnunet-reclaim.c:852
+#: src/reclaim/gnunet-reclaim.c:854
 msgid "Specify the relying party for issue"
 msgstr ""
 
-#: src/reclaim/gnunet-reclaim.c:856
+#: src/reclaim/gnunet-reclaim.c:858
 msgid "List attributes for EGO"
 msgstr ""
 
-#: src/reclaim/gnunet-reclaim.c:860
-msgid "List attestations for EGO"
+#: src/reclaim/gnunet-reclaim.c:862
+msgid "List credentials for EGO"
 msgstr ""
 
-#: src/reclaim/gnunet-reclaim.c:866
-msgid "Attestation to use for attribute"
+#: src/reclaim/gnunet-reclaim.c:868
+msgid "Credential to use for attribute"
 msgstr ""
 
-#: src/reclaim/gnunet-reclaim.c:871
-msgid "Attestation name"
+#: src/reclaim/gnunet-reclaim.c:873
+msgid "Credential name"
 msgstr ""
 
-#: src/reclaim/gnunet-reclaim.c:877
+#: src/reclaim/gnunet-reclaim.c:879
 msgid "Issue a ticket for a set of attributes separated by comma"
 msgstr ""
 
-#: src/reclaim/gnunet-reclaim.c:882
+#: src/reclaim/gnunet-reclaim.c:884
 msgid "Consume a ticket"
 msgstr ""
 
-#: src/reclaim/gnunet-reclaim.c:887
+#: src/reclaim/gnunet-reclaim.c:889
 msgid "Revoke a ticket"
 msgstr ""
 
-#: src/reclaim/gnunet-reclaim.c:892
+#: src/reclaim/gnunet-reclaim.c:894
 msgid "Type of attribute"
 msgstr ""
 
-#: src/reclaim/gnunet-reclaim.c:896
+#: src/reclaim/gnunet-reclaim.c:899
+msgid "Type of credential"
+msgstr ""
+
+#: src/reclaim/gnunet-reclaim.c:903
 msgid "List tickets of ego"
 msgstr ""
 
-#: src/reclaim/gnunet-reclaim.c:902
+#: src/reclaim/gnunet-reclaim.c:909
 msgid "Expiration interval of the attribute"
 msgstr ""
 
-#: src/reclaim/gnunet-reclaim.c:910
+#: src/reclaim/gnunet-reclaim.c:917
 msgid "re:claimID command line tool"
 msgstr ""
 
-#: src/reclaim/plugin_rest_openid_connect.c:2481
+#: src/reclaim/plugin_rest_openid_connect.c:2618
 msgid "OpenID Connect REST API initialized\n"
 msgstr ""
 
-#: src/reclaim/plugin_rest_reclaim.c:1476
+#: src/reclaim/plugin_rest_reclaim.c:1502
 msgid "Identity Provider REST API initialized\n"
 msgstr ""
 
-#: src/reclaim/reclaim_api.c:540
+#: src/reclaim/reclaim_api.c:545
 #, fuzzy
 msgid "failed to store record\n"
 msgstr "Impossibile avviare il servizio.\n"
@@ -5840,15 +5848,15 @@ msgstr ""
 msgid "Search string `%s' is too long!\n"
 msgstr ""
 
-#: src/rest/gnunet-rest-server.c:1051
+#: src/rest/gnunet-rest-server.c:1266
 msgid "GNUnet REST server"
 msgstr ""
 
-#: src/rest/plugin_rest_config.c:402
+#: src/rest/plugin_rest_config.c:427
 msgid "CONFIG REST API initialized\n"
 msgstr ""
 
-#: src/rest/plugin_rest_copying.c:209
+#: src/rest/plugin_rest_copying.c:211
 msgid "COPYING REST API initialized\n"
 msgstr ""
 
@@ -5978,24 +5986,24 @@ msgstr ""
 msgid "# revocation messages received via set union"
 msgstr "# messaggi PONG ricevuti"
 
-#: src/revocation/gnunet-service-revocation.c:470
+#: src/revocation/gnunet-service-revocation.c:469
 #, c-format
 msgid "Error computing revocation set union with %s\n"
 msgstr ""
 
-#: src/revocation/gnunet-service-revocation.c:474
+#: src/revocation/gnunet-service-revocation.c:473
 msgid "# revocation set unions failed"
 msgstr ""
 
-#: src/revocation/gnunet-service-revocation.c:486
+#: src/revocation/gnunet-service-revocation.c:481
 msgid "# revocation set unions completed"
 msgstr ""
 
-#: src/revocation/gnunet-service-revocation.c:526
+#: src/revocation/gnunet-service-revocation.c:519
 msgid "SET service crashed, terminating revocation service\n"
 msgstr ""
 
-#: src/revocation/gnunet-service-revocation.c:881
+#: src/revocation/gnunet-service-revocation.c:871
 msgid "Could not open revocation database file!"
 msgstr ""
 
@@ -6081,10 +6089,10 @@ msgstr ""
 msgid "Calculate the Vectorproduct with a GNUnet peer."
 msgstr ""
 
-#: src/scalarproduct/gnunet-service-scalarproduct_alice.c:1363
-#: src/scalarproduct/gnunet-service-scalarproduct_bob.c:1366
-#: src/scalarproduct/gnunet-service-scalarproduct-ecc_alice.c:1127
-#: src/scalarproduct/gnunet-service-scalarproduct-ecc_bob.c:1073
+#: src/scalarproduct/gnunet-service-scalarproduct_alice.c:1358
+#: src/scalarproduct/gnunet-service-scalarproduct_bob.c:1355
+#: src/scalarproduct/gnunet-service-scalarproduct-ecc_alice.c:1118
+#: src/scalarproduct/gnunet-service-scalarproduct-ecc_bob.c:1063
 msgid "Connect to CADET failed\n"
 msgstr ""
 
@@ -6108,51 +6116,62 @@ msgstr ""
 msgid "also profile decryption"
 msgstr ""
 
-#: src/set/gnunet-service-set.c:1916
+#: src/set/gnunet-service-set.c:1916 src/seti/gnunet-service-seti.c:2467
+#: src/setu/gnunet-service-setu.c:3635
 #, fuzzy
 msgid "Could not connect to CADET service\n"
 msgstr "Impossibile avviare il servizio.\n"
 
 #: src/set/gnunet-set-ibf-profiler.c:268
+#: src/setu/gnunet-setu-ibf-profiler.c:268
 msgid "number of element in set A-B"
 msgstr ""
 
 #: src/set/gnunet-set-ibf-profiler.c:274
+#: src/setu/gnunet-setu-ibf-profiler.c:274
 msgid "number of element in set B-A"
 msgstr ""
 
 #: src/set/gnunet-set-ibf-profiler.c:281
+#: src/setu/gnunet-setu-ibf-profiler.c:281
 msgid "number of common elements in A and B"
 msgstr ""
 
 #: src/set/gnunet-set-ibf-profiler.c:287
+#: src/setu/gnunet-setu-ibf-profiler.c:287
 msgid "hash num"
 msgstr ""
 
 #: src/set/gnunet-set-ibf-profiler.c:293
+#: src/setu/gnunet-setu-ibf-profiler.c:293
 msgid "ibf size"
 msgstr ""
 
-#: src/set/gnunet-set-profiler.c:462
+#: src/set/gnunet-set-profiler.c:462 src/setu/gnunet-setu-profiler.c:453
 msgid "use byzantine mode"
 msgstr ""
 
-#: src/set/gnunet-set-profiler.c:468
+#: src/set/gnunet-set-profiler.c:468 src/setu/gnunet-setu-profiler.c:459
 msgid "force sending full set"
 msgstr ""
 
-#: src/set/gnunet-set-profiler.c:474
+#: src/set/gnunet-set-profiler.c:474 src/setu/gnunet-setu-profiler.c:465
 msgid "number delta operation"
 msgstr ""
 
-#: src/set/gnunet-set-profiler.c:486
+#: src/set/gnunet-set-profiler.c:486 src/setu/gnunet-setu-profiler.c:477
 msgid "operation to execute"
 msgstr ""
 
-#: src/set/gnunet-set-profiler.c:492
+#: src/set/gnunet-set-profiler.c:492 src/seti/gnunet-seti-profiler.c:462
+#: src/setu/gnunet-setu-profiler.c:483
 msgid "element size"
 msgstr ""
 
+#: src/seti/gnunet-seti-profiler.c:457
+msgid "return intersection instead of delta"
+msgstr ""
+
 #: src/sq/sq.c:54
 #, c-format
 msgid "Failure to bind %u-th SQL parameter\n"
@@ -6167,12 +6186,12 @@ msgstr ""
 msgid "Failed to reset sqlite statement with error: %s\n"
 msgstr "Impossibile avviare il servizio ' %s'\n"
 
-#: src/statistics/gnunet-service-statistics.c:318
+#: src/statistics/gnunet-service-statistics.c:319
 #, c-format
 msgid "Wrote %llu bytes of statistics to `%s'\n"
 msgstr ""
 
-#: src/statistics/gnunet-service-statistics.c:983
+#: src/statistics/gnunet-service-statistics.c:984
 #, c-format
 msgid "Loading %llu bytes of statistics from `%s'\n"
 msgstr ""
@@ -6353,7 +6372,7 @@ msgid ""
 msgstr ""
 
 #: src/testbed/gnunet-daemon-testbed-underlay.c:234 src/testing/list-keys.c:47
-#: src/testing/testing.c:284 src/util/gnunet-ecc.c:318
+#: src/testing/testing.c:278 src/util/gnunet-ecc.c:318
 #, c-format
 msgid "Incorrect hostkey file format: %s\n"
 msgstr ""
@@ -6606,57 +6625,57 @@ msgstr ""
 msgid "list COUNT number of keys"
 msgstr ""
 
-#: src/testing/testing.c:267
+#: src/testing/testing.c:261
 #, c-format
 msgid "Hostkeys file not found: %s\n"
 msgstr ""
 
-#: src/testing/testing.c:721
+#: src/testing/testing.c:714
 #, c-format
 msgid "Key number %u does not exist\n"
 msgstr ""
 
-#: src/testing/testing.c:1195
+#: src/testing/testing.c:1188
 #, c-format
 msgid ""
 "You attempted to create a testbed with more than %u hosts.  Please "
 "precompute more hostkeys first.\n"
 msgstr ""
 
-#: src/testing/testing.c:1204
+#: src/testing/testing.c:1197
 #, c-format
 msgid "Failed to initialize hostkey for peer %u\n"
 msgstr ""
 
-#: src/testing/testing.c:1214
+#: src/testing/testing.c:1207
 msgid "PRIVATE_KEY option in PEER section missing in configuration\n"
 msgstr ""
 
-#: src/testing/testing.c:1227
+#: src/testing/testing.c:1220
 msgid "Failed to create configuration for peer (not enough free ports?)\n"
 msgstr ""
 
-#: src/testing/testing.c:1243
+#: src/testing/testing.c:1236
 #, c-format
 msgid "Cannot open hostkey file `%s': %s\n"
 msgstr ""
 
-#: src/testing/testing.c:1257
+#: src/testing/testing.c:1250
 #, c-format
 msgid "Failed to write hostkey file for peer %u: %s\n"
 msgstr ""
 
-#: src/testing/testing.c:1285
+#: src/testing/testing.c:1278
 #, c-format
 msgid "Failed to write configuration file `%s' for peer %u: %s\n"
 msgstr ""
 
-#: src/testing/testing.c:1392
+#: src/testing/testing.c:1384
 #, c-format
 msgid "Failed to start `%s': %s\n"
 msgstr ""
 
-#: src/testing/testing.c:1691
+#: src/testing/testing.c:1683
 #, c-format
 msgid "Failed to load configuration from %s\n"
 msgstr ""
@@ -6730,37 +6749,37 @@ msgstr ""
 msgid "GNUnet topology control"
 msgstr ""
 
-#: src/transport/gnunet-communicator-tcp.c:2458
-#: src/transport/gnunet-communicator-udp.c:2825
-#: src/transport/gnunet-service-tng.c:10027
+#: src/transport/gnunet-communicator-tcp.c:3189
+#: src/transport/gnunet-communicator-udp.c:2826
+#: src/transport/gnunet-service-tng.c:10014
 #: src/transport/gnunet-service-transport.c:2624
 msgid "Transport service is lacking key configuration settings. Exiting.\n"
 msgstr ""
 
-#: src/transport/gnunet-communicator-tcp.c:2754
+#: src/transport/gnunet-communicator-tcp.c:3494
 msgid "GNUnet TCP communicator"
 msgstr ""
 
-#: src/transport/gnunet-communicator-udp.c:2897
+#: src/transport/gnunet-communicator-udp.c:2898
 msgid "GNUnet UDP communicator"
 msgstr ""
 
-#: src/transport/gnunet-communicator-unix.c:788
+#: src/transport/gnunet-communicator-unix.c:789
 msgid ""
 "Maximum number of UNIX connections exceeded, dropping incoming message\n"
 msgstr ""
 
-#: src/transport/gnunet-communicator-unix.c:1015
+#: src/transport/gnunet-communicator-unix.c:1016
 msgid "UNIX communicator is lacking key configuration settings. Exiting.\n"
 msgstr ""
 
-#: src/transport/gnunet-communicator-unix.c:1060
+#: src/transport/gnunet-communicator-unix.c:1061
 #: src/transport/plugin_transport_unix.c:1383
 #, c-format
 msgid "Cannot create path to `%s'\n"
 msgstr ""
 
-#: src/transport/gnunet-communicator-unix.c:1138
+#: src/transport/gnunet-communicator-unix.c:1139
 msgid "GNUnet UNIX domain socket communicator"
 msgstr ""
 
@@ -7805,7 +7824,7 @@ msgid "do daemonize (detach from terminal)"
 msgstr ""
 
 #: src/transport/tcp_service_legacy.c:1397
-#: src/transport/transport-testing2.c:1061 src/util/service.c:2072
+#: src/transport/transport-testing2.c:1116 src/util/service.c:2072
 #: src/util/service.c:2084
 #, c-format
 msgid "Malformed configuration file `%s', exit ...\n"
@@ -7847,7 +7866,7 @@ msgstr ""
 msgid "Invalid handle type while reading `%s'"
 msgstr ""
 
-#: src/util/bio.c:335 src/util/bio.c:838
+#: src/util/bio.c:335 src/util/bio.c:839
 msgid "string length"
 msgstr ""
 
@@ -7866,7 +7885,7 @@ msgstr ""
 msgid "String `%s' longer than allowed (%u > %u)"
 msgstr ""
 
-#: src/util/bio.c:398 src/util/bio.c:863 src/util/bio.c:880
+#: src/util/bio.c:398 src/util/bio.c:864 src/util/bio.c:881
 msgid "metadata length"
 msgstr ""
 
@@ -7880,25 +7899,25 @@ msgstr ""
 msgid "Failed to deserialize metadata `%s'"
 msgstr "Impossibile avviare il servizio ' %s'\n"
 
-#: src/util/bio.c:667
+#: src/util/bio.c:668
 msgid "Unable to flush buffer to file"
 msgstr ""
 
-#: src/util/bio.c:729 src/util/bio.c:750
+#: src/util/bio.c:730 src/util/bio.c:751
 #, fuzzy, c-format
 msgid "Error while writing `%s' to file: %s"
 msgstr "Errore di lettura del file `%s'\n"
 
-#: src/util/bio.c:731
+#: src/util/bio.c:732
 msgid "No associated file"
 msgstr ""
 
-#: src/util/bio.c:815
+#: src/util/bio.c:816
 #, c-format
 msgid "Invalid handle type while writing `%s'"
 msgstr ""
 
-#: src/util/bio.c:875
+#: src/util/bio.c:876
 #, fuzzy, c-format
 msgid "Failed to serialize metadata `%s'"
 msgstr "Impossibile avviare il servizio ' %s'\n"
@@ -8379,15 +8398,15 @@ msgstr ""
 msgid "No handler known for subsystem `%s'\n"
 msgstr ""
 
-#: src/util/gnunet-qr.c:358
+#: src/util/gnunet-qr.c:357
 msgid "use video-device DEVICE (default: /dev/video0"
 msgstr ""
 
-#: src/util/gnunet-qr.c:363
+#: src/util/gnunet-qr.c:362
 msgid "do not show preview windows"
 msgstr ""
 
-#: src/util/gnunet-qr.c:373
+#: src/util/gnunet-qr.c:372
 msgid "Scan a QR code using a video device and import the uri read"
 msgstr ""
 
@@ -8399,28 +8418,28 @@ msgstr ""
 msgid "Use build-in GNUnet stub resolver"
 msgstr ""
 
-#: src/util/gnunet-scrypt.c:222
+#: src/util/gnunet-scrypt.c:229
 #, c-format
 msgid "Loading hostkey from `%s' failed.\n"
 msgstr ""
 
-#: src/util/gnunet-scrypt.c:288
+#: src/util/gnunet-scrypt.c:295
 msgid "number of bits to require for the proof of work"
 msgstr ""
 
-#: src/util/gnunet-scrypt.c:294
+#: src/util/gnunet-scrypt.c:301
 msgid "file with private key, otherwise default is used"
 msgstr ""
 
-#: src/util/gnunet-scrypt.c:300
+#: src/util/gnunet-scrypt.c:307
 msgid "file with proof of work, otherwise default is used"
 msgstr ""
 
-#: src/util/gnunet-scrypt.c:306
+#: src/util/gnunet-scrypt.c:313
 msgid "time to wait between calculations"
 msgstr ""
 
-#: src/util/gnunet-scrypt.c:319
+#: src/util/gnunet-scrypt.c:326
 msgid "Manipulate GNUnet proof of work files"
 msgstr ""
 
@@ -8433,7 +8452,7 @@ msgstr ""
 msgid "No URI specified on command line\n"
 msgstr ""
 
-#: src/util/gnunet-uri.c:179
+#: src/util/gnunet-uri.c:178
 msgid "Perform default-actions for GNUnet URIs"
 msgstr ""
 
@@ -8447,7 +8466,7 @@ msgstr "Errore di lettura da '%s': %s\n"
 msgid "Failed to parse inbound message from helper `%s'\n"
 msgstr ""
 
-#: src/util/helper.c:600
+#: src/util/helper.c:602
 #, c-format
 msgid "Error writing to `%s': %s\n"
 msgstr ""
@@ -8573,116 +8592,116 @@ msgstr ""
 msgid "Attempting to proxy service `%s' to invalid port %d or hostname.\n"
 msgstr ""
 
-#: src/util/strings.c:178
+#: src/util/strings.c:179
 msgid "b"
 msgstr ""
 
-#: src/util/strings.c:502
+#: src/util/strings.c:503
 #, c-format
 msgid "Character sets requested were `%s'->`%s'\n"
 msgstr ""
 
-#: src/util/strings.c:636
+#: src/util/strings.c:637
 msgid "Failed to expand `$HOME': environment variable `HOME' not set"
 msgstr ""
 
-#: src/util/strings.c:705
+#: src/util/strings.c:706
 msgid "µs"
 msgstr "µs"
 
-#: src/util/strings.c:709
+#: src/util/strings.c:710
 msgid "forever"
 msgstr "per sempre"
 
-#: src/util/strings.c:711
+#: src/util/strings.c:712
 msgid "0 ms"
 msgstr "0 ms"
 
-#: src/util/strings.c:715
+#: src/util/strings.c:716
 msgid "ms"
 msgstr "ms"
 
-#: src/util/strings.c:719
+#: src/util/strings.c:720
 msgid "s"
 msgstr "s"
 
-#: src/util/strings.c:723
+#: src/util/strings.c:724
 msgid "m"
 msgstr ""
 
-#: src/util/strings.c:727
+#: src/util/strings.c:728
 msgid "h"
 msgstr "o"
 
-#: src/util/strings.c:733
+#: src/util/strings.c:734
 msgid "day"
 msgstr "giorno"
 
-#: src/util/strings.c:735
+#: src/util/strings.c:736
 msgid "days"
 msgstr "giorni"
 
-#: src/util/strings.c:763
+#: src/util/strings.c:764
 msgid "end of time"
 msgstr ""
 
-#: src/util/strings.c:1239
+#: src/util/strings.c:1240
 msgid "IPv6 address did not start with `['\n"
 msgstr ""
 
-#: src/util/strings.c:1247
+#: src/util/strings.c:1248
 msgid "IPv6 address did contain ':' to separate port number\n"
 msgstr ""
 
-#: src/util/strings.c:1254
+#: src/util/strings.c:1255
 msgid "IPv6 address did contain ']' before ':' to separate port number\n"
 msgstr ""
 
-#: src/util/strings.c:1262
+#: src/util/strings.c:1263
 msgid "IPv6 address did contain a valid port number after the last ':'\n"
 msgstr ""
 
-#: src/util/strings.c:1271
+#: src/util/strings.c:1272
 #, c-format
 msgid "Invalid IPv6 address `%s': %s\n"
 msgstr ""
 
-#: src/util/strings.c:1498 src/util/strings.c:1509
+#: src/util/strings.c:1499 src/util/strings.c:1510
 msgid "Port not in range\n"
 msgstr ""
 
-#: src/util/strings.c:1518
+#: src/util/strings.c:1519
 #, c-format
 msgid "Malformed port policy `%s'\n"
 msgstr ""
 
-#: src/util/strings.c:1601 src/util/strings.c:1630 src/util/strings.c:1677
-#: src/util/strings.c:1697
+#: src/util/strings.c:1602 src/util/strings.c:1631 src/util/strings.c:1678
+#: src/util/strings.c:1698
 #, c-format
 msgid "Invalid format for IP: `%s'\n"
 msgstr ""
 
-#: src/util/strings.c:1655
+#: src/util/strings.c:1656
 #, c-format
 msgid "Invalid network notation ('/%d' is not legal in IPv4 CIDR)."
 msgstr ""
 
-#: src/util/strings.c:1706
+#: src/util/strings.c:1707
 #, c-format
 msgid "Invalid format: `%s'\n"
 msgstr ""
 
-#: src/util/strings.c:1759
+#: src/util/strings.c:1760
 #, c-format
 msgid "Invalid network notation (does not end with ';': `%s')\n"
 msgstr ""
 
-#: src/util/strings.c:1809
+#: src/util/strings.c:1810
 #, c-format
 msgid "Wrong format `%s' for netmask\n"
 msgstr ""
 
-#: src/util/strings.c:1840
+#: src/util/strings.c:1841
 #, c-format
 msgid "Wrong format `%s' for network\n"
 msgstr ""
diff --git a/po/sv.po b/po/sv.po
index ee2eb28a6f0d07cec99278a0ec0f9ac2969ef59a..25812f069131155279ff8cda3f136c36f032b1b9 100644
--- a/po/sv.po
+++ b/po/sv.po
@@ -7,7 +7,7 @@ msgid ""
 msgstr ""
 "Project-Id-Version: GNUnet 0.7.0b\n"
 "Report-Msgid-Bugs-To: gnunet-developers@mail.gnu.org\n"
-"POT-Creation-Date: 2020-07-12 17:55+0200\n"
+"POT-Creation-Date: 2020-09-06 10:07+0200\n"
 "PO-Revision-Date: 2006-01-21 17:16+0100\n"
 "Last-Translator: Daniel Nylander <po@danielnylander.se>\n"
 "Language-Team: Swedish <tp-sv@listor.tp-sv.se>\n"
@@ -16,12 +16,12 @@ msgstr ""
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
 
-#: src/abd/gnunet-abd.c:397 src/namestore/gnunet-namestore.c:1302
+#: src/abd/gnunet-abd.c:397 src/namestore/gnunet-namestore.c:1303
 #, fuzzy, c-format
 msgid "Ego `%s' not known to identity service\n"
 msgstr "\"%s\": okänd tjänst: %s\n"
 
-#: src/abd/gnunet-abd.c:413 src/abd/gnunet-abd.c:896
+#: src/abd/gnunet-abd.c:413 src/abd/gnunet-abd.c:901
 #, fuzzy, c-format
 msgid "Issuer public key `%s' is not well-formed\n"
 msgstr "Ogiltigt argument: \"%s\"\n"
@@ -33,109 +33,109 @@ msgstr "Ogiltigt argument: \"%s\"\n"
 msgid "Failed to connect to namestore\n"
 msgstr "Misslyckades att ansluta till gnunetd.\n"
 
-#: src/abd/gnunet-abd.c:835 src/abd/gnunet-abd.c:886
+#: src/abd/gnunet-abd.c:840 src/abd/gnunet-abd.c:891
 #, fuzzy, c-format
 msgid "Issuer public key not well-formed\n"
 msgstr "Ogiltigt argument: \"%s\"\n"
 
-#: src/abd/gnunet-abd.c:844 src/abd/gnunet-abd.c:905
+#: src/abd/gnunet-abd.c:849 src/abd/gnunet-abd.c:910
 #, fuzzy, c-format
 msgid "Failed to connect to ABD\n"
 msgstr "Misslyckades att ansluta till gnunetd.\n"
 
-#: src/abd/gnunet-abd.c:850
+#: src/abd/gnunet-abd.c:855
 #, c-format
 msgid "You must provide issuer the attribute\n"
 msgstr ""
 
-#: src/abd/gnunet-abd.c:857
+#: src/abd/gnunet-abd.c:862
 #, c-format
 msgid "ego required\n"
 msgstr ""
 
-#: src/abd/gnunet-abd.c:867
+#: src/abd/gnunet-abd.c:872
 #, c-format
 msgid "Subject public key needed\n"
 msgstr ""
 
-#: src/abd/gnunet-abd.c:876
+#: src/abd/gnunet-abd.c:881
 #, fuzzy, c-format
 msgid "Subject public key `%s' is not well-formed\n"
 msgstr "Ogiltigt argument: \"%s\"\n"
 
-#: src/abd/gnunet-abd.c:911
+#: src/abd/gnunet-abd.c:916
 #, c-format
 msgid "You must provide issuer and subject attributes\n"
 msgstr ""
 
-#: src/abd/gnunet-abd.c:970
+#: src/abd/gnunet-abd.c:975
 #, c-format
 msgid "Please specify name to lookup, subject key and issuer key!\n"
 msgstr ""
 
-#: src/abd/gnunet-abd.c:991
+#: src/abd/gnunet-abd.c:996
 msgid "verify credential against attribute"
 msgstr ""
 
-#: src/abd/gnunet-abd.c:998
+#: src/abd/gnunet-abd.c:1003
 #, fuzzy
 msgid ""
 "The public key of the subject to lookup thecredential for, or for issuer "
 "side storage: subject and its attributes"
 msgstr "ange prioritet för innehållet"
 
-#: src/abd/gnunet-abd.c:1005
+#: src/abd/gnunet-abd.c:1010
 msgid "The private, signed delegate presented by the subject"
 msgstr ""
 
-#: src/abd/gnunet-abd.c:1012
+#: src/abd/gnunet-abd.c:1017
 #, fuzzy
 msgid "The public key of the authority to verify the credential against"
 msgstr "ange prioritet för innehållet"
 
-#: src/abd/gnunet-abd.c:1017
+#: src/abd/gnunet-abd.c:1022
 #, fuzzy
 msgid "The ego/zone name to use"
 msgstr "meddelandestorlek"
 
-#: src/abd/gnunet-abd.c:1023
+#: src/abd/gnunet-abd.c:1028
 msgid "The issuer attribute to verify against or to issue"
 msgstr ""
 
-#: src/abd/gnunet-abd.c:1029
+#: src/abd/gnunet-abd.c:1034
 msgid ""
 "The time to live for the credential.e.g. 5m, 6h, \"1990-12-30 12:00:00\""
 msgstr ""
 
-#: src/abd/gnunet-abd.c:1034
+#: src/abd/gnunet-abd.c:1039
 msgid "collect credentials"
 msgstr ""
 
-#: src/abd/gnunet-abd.c:1039
+#: src/abd/gnunet-abd.c:1044
 msgid "Create and issue a credential issuer side."
 msgstr ""
 
-#: src/abd/gnunet-abd.c:1044
+#: src/abd/gnunet-abd.c:1049
 msgid "Issue a credential subject side."
 msgstr ""
 
-#: src/abd/gnunet-abd.c:1049
+#: src/abd/gnunet-abd.c:1054
 msgid "Create, sign and return a credential subject side."
 msgstr ""
 
-#: src/abd/gnunet-abd.c:1056
+#: src/abd/gnunet-abd.c:1061
 msgid "Import signed credentials that should be issued to a zone/ego"
 msgstr ""
 
-#: src/abd/gnunet-abd.c:1060
+#: src/abd/gnunet-abd.c:1065
 msgid "Create private record entry."
 msgstr ""
 
-#: src/abd/gnunet-abd.c:1066 src/abd/gnunet-abd.c:1072
+#: src/abd/gnunet-abd.c:1071 src/abd/gnunet-abd.c:1077
 msgid "Indicates that the collect/verify process is done via forward search."
 msgstr ""
 
-#: src/abd/gnunet-abd.c:1085
+#: src/abd/gnunet-abd.c:1090
 #, fuzzy
 msgid "GNUnet abd resolver tool"
 msgstr "Spåra GNUnets nätverkstopologi."
@@ -435,65 +435,65 @@ msgstr "Misslyckades att leverera \"%s\" meddelande.\n"
 msgid "Failed to find %saddress for `%s'.\n"
 msgstr "Misslyckades att binda till UDP-port %d.\n"
 
-#: src/arm/gnunet-service-arm.c:933
+#: src/arm/gnunet-service-arm.c:951
 #, fuzzy, c-format
 msgid "Failed to start service `%s'\n"
 msgstr "Misslyckades att starta samling.\n"
 
-#: src/arm/gnunet-service-arm.c:944
+#: src/arm/gnunet-service-arm.c:962
 #, fuzzy, c-format
 msgid "Starting service `%s'\n"
 msgstr "Startade samling \"%s\".\n"
 
-#: src/arm/gnunet-service-arm.c:1044
+#: src/arm/gnunet-service-arm.c:1062
 #, fuzzy, c-format
 msgid "Unable to create socket for service `%s': %s\n"
 msgstr "Kunde inte skapa användarkonto:"
 
-#: src/arm/gnunet-service-arm.c:1075
+#: src/arm/gnunet-service-arm.c:1093
 #, c-format
 msgid "Unable to bind listening socket for service `%s' to address `%s': %s\n"
 msgstr ""
 
-#: src/arm/gnunet-service-arm.c:1106
+#: src/arm/gnunet-service-arm.c:1124
 #, c-format
 msgid "ARM now monitors connections to service `%s' at `%s'\n"
 msgstr ""
 
-#: src/arm/gnunet-service-arm.c:1254
+#: src/arm/gnunet-service-arm.c:1272
 #, fuzzy, c-format
 msgid "Preparing to stop `%s'\n"
 msgstr "Startade samling \"%s\".\n"
 
-#: src/arm/gnunet-service-arm.c:1586
+#: src/arm/gnunet-service-arm.c:1604
 #, fuzzy, c-format
 msgid "Restarting service `%s'.\n"
 msgstr "Startade samling \"%s\".\n"
 
-#: src/arm/gnunet-service-arm.c:1737
+#: src/arm/gnunet-service-arm.c:1755
 msgid "exit"
 msgstr ""
 
-#: src/arm/gnunet-service-arm.c:1742
+#: src/arm/gnunet-service-arm.c:1760
 msgid "signal"
 msgstr ""
 
-#: src/arm/gnunet-service-arm.c:1747
+#: src/arm/gnunet-service-arm.c:1765
 #, fuzzy
 msgid "unknown"
 msgstr "Okänt fel"
 
-#: src/arm/gnunet-service-arm.c:1753
+#: src/arm/gnunet-service-arm.c:1771
 #, fuzzy, c-format
 msgid "Service `%s' took %s to terminate\n"
 msgstr "Tjänst borttagen.\n"
 
-#: src/arm/gnunet-service-arm.c:1780
+#: src/arm/gnunet-service-arm.c:1798
 #, c-format
 msgid "Service `%s' terminated normally, will restart at any time\n"
 msgstr ""
 
-#: src/arm/gnunet-service-arm.c:1797
+#: src/arm/gnunet-service-arm.c:1815
 #, c-format
 msgid "Service `%s' terminated with status %s/%d, will restart in %s\n"
 msgstr ""
@@ -829,7 +829,10 @@ msgstr ""
 
 #: src/consensus/gnunet-consensus-profiler.c:543
 #: src/set/gnunet-set-profiler.c:451 src/set/gnunet-set-profiler.c:457
-#: src/set/gnunet-set-profiler.c:480
+#: src/set/gnunet-set-profiler.c:480 src/seti/gnunet-seti-profiler.c:441
+#: src/seti/gnunet-seti-profiler.c:446 src/seti/gnunet-seti-profiler.c:451
+#: src/setu/gnunet-setu-profiler.c:442 src/setu/gnunet-setu-profiler.c:448
+#: src/setu/gnunet-setu-profiler.c:471
 #, fuzzy
 msgid "number of values"
 msgstr "antal iterationer"
@@ -844,7 +847,8 @@ msgid "delay until consensus starts"
 msgstr ""
 
 #: src/consensus/gnunet-consensus-profiler.c:563
-#: src/set/gnunet-set-profiler.c:498
+#: src/set/gnunet-set-profiler.c:498 src/seti/gnunet-seti-profiler.c:467
+#: src/setu/gnunet-setu-profiler.c:489
 msgid "write statistics to file"
 msgstr ""
 
@@ -1396,158 +1400,158 @@ msgstr "GNUnet-konfiguration"
 msgid "Core service of `%s' ready.\n"
 msgstr "\"%s\" är inte en fil.\n"
 
-#: src/core/gnunet-service-core_kx.c:625
+#: src/core/gnunet-service-core_kx.c:512
 msgid "# bytes encrypted"
 msgstr "# byte krypterade"
 
-#: src/core/gnunet-service-core_kx.c:683
+#: src/core/gnunet-service-core_kx.c:570
 msgid "# bytes decrypted"
 msgstr "# byte dekrypterade"
 
-#: src/core/gnunet-service-core_kx.c:780
+#: src/core/gnunet-service-core_kx.c:667
 #, fuzzy
 msgid "# PAYLOAD dropped (out of order)"
 msgstr "# byte kastade via UDP (utgående)"
 
-#: src/core/gnunet-service-core_kx.c:832
+#: src/core/gnunet-service-core_kx.c:719
 msgid "# key exchanges initiated"
 msgstr ""
 
-#: src/core/gnunet-service-core_kx.c:888
+#: src/core/gnunet-service-core_kx.c:775
 msgid "# key exchanges stopped"
 msgstr ""
 
-#: src/core/gnunet-service-core_kx.c:920
+#: src/core/gnunet-service-core_kx.c:807
 #, fuzzy
 msgid "# PING messages transmitted"
 msgstr "# PING-meddelanden skapade"
 
-#: src/core/gnunet-service-core_kx.c:979
+#: src/core/gnunet-service-core_kx.c:866
 msgid "# old ephemeral keys ignored"
 msgstr ""
 
-#: src/core/gnunet-service-core_kx.c:993
+#: src/core/gnunet-service-core_kx.c:880
 #, fuzzy
 msgid "# duplicate ephemeral keys ignored"
 msgstr "# krypterade PONG-meddelanden mottagna"
 
-#: src/core/gnunet-service-core_kx.c:1028
+#: src/core/gnunet-service-core_kx.c:915
 #, fuzzy
 msgid "# EPHEMERAL_KEYs rejected (bad signature)"
 msgstr "# PING-meddelanden skapade"
 
-#: src/core/gnunet-service-core_kx.c:1046
+#: src/core/gnunet-service-core_kx.c:933
 #, c-format
 msgid ""
 "EPHEMERAL_KEY from peer `%s' rejected as its validity range does not match "
 "our system time (%llu not in [%llu,%llu]).\n"
 msgstr ""
 
-#: src/core/gnunet-service-core_kx.c:1053
+#: src/core/gnunet-service-core_kx.c:940
 #, fuzzy
 msgid "# EPHEMERAL_KEY messages rejected due to time"
 msgstr "# PING-meddelanden skapade"
 
-#: src/core/gnunet-service-core_kx.c:1071
+#: src/core/gnunet-service-core_kx.c:958
 #, fuzzy
 msgid "# valid ephemeral keys received"
 msgstr "# krypterade PONG-meddelanden mottagna"
 
-#: src/core/gnunet-service-core_kx.c:1180
+#: src/core/gnunet-service-core_kx.c:1067
 #: src/transport/gnunet-service-transport_validation.c:1133
 #, fuzzy
 msgid "# PING messages received"
 msgstr "# PING-meddelanden skapade"
 
-#: src/core/gnunet-service-core_kx.c:1190
+#: src/core/gnunet-service-core_kx.c:1077
 #, fuzzy
 msgid "# PING messages dropped (out of order)"
 msgstr "Nätverksannonsering avstängd i konfigurationen!\n"
 
-#: src/core/gnunet-service-core_kx.c:1239
+#: src/core/gnunet-service-core_kx.c:1126
 #, fuzzy
 msgid "# PONG messages created"
 msgstr "# PING-meddelanden skapade"
 
-#: src/core/gnunet-service-core_kx.c:1264
+#: src/core/gnunet-service-core_kx.c:1151
 #, fuzzy
 msgid "# sessions terminated by timeout"
 msgstr "# byte kastade via TCP (utgående)"
 
-#: src/core/gnunet-service-core_kx.c:1277
+#: src/core/gnunet-service-core_kx.c:1164
 #, fuzzy
 msgid "# keepalive messages sent"
 msgstr "# PING-meddelanden i klartext skickade"
 
-#: src/core/gnunet-service-core_kx.c:1334
+#: src/core/gnunet-service-core_kx.c:1221
 #: src/transport/gnunet-service-transport_validation.c:1476
 #, fuzzy
 msgid "# PONG messages received"
 msgstr "# krypterade PONG-meddelanden mottagna"
 
-#: src/core/gnunet-service-core_kx.c:1342
+#: src/core/gnunet-service-core_kx.c:1229
 #, fuzzy
 msgid "# PONG messages dropped (connection down)"
 msgstr "# krypterade PONG-meddelanden mottagna"
 
-#: src/core/gnunet-service-core_kx.c:1350
+#: src/core/gnunet-service-core_kx.c:1237
 #, fuzzy
 msgid "# PONG messages dropped (out of order)"
 msgstr "Nätverksannonsering avstängd i konfigurationen!\n"
 
-#: src/core/gnunet-service-core_kx.c:1389
+#: src/core/gnunet-service-core_kx.c:1276
 #, fuzzy
 msgid "# PONG messages decrypted"
 msgstr "# PING-meddelanden skapade"
 
-#: src/core/gnunet-service-core_kx.c:1429
+#: src/core/gnunet-service-core_kx.c:1316
 #, fuzzy
 msgid "# session keys confirmed via PONG"
 msgstr "# sessionnycklar vägrade"
 
-#: src/core/gnunet-service-core_kx.c:1441
+#: src/core/gnunet-service-core_kx.c:1328
 #, fuzzy
 msgid "# timeouts prevented via PONG"
 msgstr "# byte mottogs via TCP"
 
-#: src/core/gnunet-service-core_kx.c:1450
+#: src/core/gnunet-service-core_kx.c:1337
 #, fuzzy
 msgid "# rekey operations confirmed via PONG"
 msgstr "# sessionnycklar vägrade"
 
-#: src/core/gnunet-service-core_kx.c:1626
+#: src/core/gnunet-service-core_kx.c:1513
 #, fuzzy
 msgid "# DATA message dropped (out of order)"
 msgstr "# byte kastade via UDP (utgående)"
 
-#: src/core/gnunet-service-core_kx.c:1637
+#: src/core/gnunet-service-core_kx.c:1524
 #, c-format
 msgid ""
 "Session to peer `%s' went down due to key expiration (should not happen)\n"
 msgstr ""
 
-#: src/core/gnunet-service-core_kx.c:1641
+#: src/core/gnunet-service-core_kx.c:1528
 #, fuzzy
 msgid "# sessions terminated by key expiration"
 msgstr "# byte kastade via TCP (utgående)"
 
-#: src/core/gnunet-service-core_kx.c:1719
-#: src/core/gnunet-service-core_kx.c:1746
+#: src/core/gnunet-service-core_kx.c:1606
+#: src/core/gnunet-service-core_kx.c:1633
 #, fuzzy
 msgid "# bytes dropped (duplicates)"
 msgstr "# byte kastade via UDP (utgående)"
 
-#: src/core/gnunet-service-core_kx.c:1732
+#: src/core/gnunet-service-core_kx.c:1619
 #, fuzzy
 msgid "# bytes dropped (out of sequence)"
 msgstr "# byte kastade via UDP (utgående)"
 
-#: src/core/gnunet-service-core_kx.c:1777
+#: src/core/gnunet-service-core_kx.c:1664
 #, fuzzy
 msgid "# bytes dropped (ancient message)"
 msgstr "# byte kastade via UDP (utgående)"
 
-#: src/core/gnunet-service-core_kx.c:1786
+#: src/core/gnunet-service-core_kx.c:1673
 #, fuzzy
 msgid "# bytes of payload decrypted"
 msgstr "# byte dekrypterade"
@@ -3175,18 +3179,18 @@ msgstr ""
 msgid "Failed to load state: %s\n"
 msgstr "Misslyckades att starta samling.\n"
 
-#: src/fs/gnunet-auto-share.c:286 src/fs/gnunet-auto-share.c:295
-#: src/fs/gnunet-auto-share.c:303
+#: src/fs/gnunet-auto-share.c:287 src/fs/gnunet-auto-share.c:296
+#: src/fs/gnunet-auto-share.c:304
 #, fuzzy, c-format
 msgid "Failed to save state to file %s\n"
 msgstr "Misslyckades att läsa kompislista från \"%s\"\n"
 
-#: src/fs/gnunet-auto-share.c:400
+#: src/fs/gnunet-auto-share.c:401
 #, c-format
 msgid "Publication of `%s' done\n"
 msgstr ""
 
-#: src/fs/gnunet-auto-share.c:479
+#: src/fs/gnunet-auto-share.c:480
 #, fuzzy, c-format
 msgid "Publishing `%s'\n"
 msgstr ""
@@ -4020,40 +4024,40 @@ msgstr ""
 msgid "GNUnet HTTP server to create business cards"
 msgstr ""
 
-#: src/gns/gnunet-dns2gns.c:239
+#: src/gns/gnunet-dns2gns.c:241
 #, fuzzy
 msgid "Failed to pack DNS response into UDP packet!\n"
 msgstr "Misslyckades att skicka HTTP-begäran till värd \"%s\": %s\n"
 
-#: src/gns/gnunet-dns2gns.c:442
+#: src/gns/gnunet-dns2gns.c:444
 #, fuzzy, c-format
 msgid "Cannot parse DNS request from %s\n"
 msgstr "Misslyckades att skicka HTTP-begäran till värd \"%s\": %s\n"
 
-#: src/gns/gnunet-dns2gns.c:458
+#: src/gns/gnunet-dns2gns.c:460
 #, fuzzy, c-format
 msgid "Received malformed DNS request from %s\n"
 msgstr "Mottog ogiltig \"%s\" begäran (storlek %d)\n"
 
-#: src/gns/gnunet-dns2gns.c:466
+#: src/gns/gnunet-dns2gns.c:468
 #, fuzzy, c-format
 msgid "Received unsupported DNS request from %s\n"
 msgstr "Mottog okänd typ av begäran %d vid %s:%d\n"
 
-#: src/gns/gnunet-dns2gns.c:627
+#: src/gns/gnunet-dns2gns.c:629
 #, fuzzy
 msgid "No DNS server specified!\n"
 msgstr "Inga nyckelord angivna!\n"
 
-#: src/gns/gnunet-dns2gns.c:776
+#: src/gns/gnunet-dns2gns.c:778
 msgid "IP of recursive DNS resolver to use (required)"
 msgstr ""
 
-#: src/gns/gnunet-dns2gns.c:782
+#: src/gns/gnunet-dns2gns.c:784
 msgid "UDP port to listen on for inbound DNS requests; default: 2853"
 msgstr ""
 
-#: src/gns/gnunet-dns2gns.c:799
+#: src/gns/gnunet-dns2gns.c:801
 msgid "GNUnet DNS-to-GNS proxy (a DNS server)"
 msgstr ""
 
@@ -4194,7 +4198,7 @@ msgstr "Kunde inte spara konfigurationsfil \"%s\":"
 msgid "Failed to start HTTPS server for `%s'\n"
 msgstr "Misslyckades att starta samling.\n"
 
-#: src/gns/gnunet-gns-proxy.c:2922 src/rest/gnunet-rest-server.c:713
+#: src/gns/gnunet-gns-proxy.c:2922 src/rest/gnunet-rest-server.c:917
 #, fuzzy
 msgid "Failed to pass client to MHD\n"
 msgstr "Misslyckades att ansluta till gnunetd.\n"
@@ -4350,7 +4354,7 @@ msgstr "Misslyckades att läsa kompislista från \"%s\"\n"
 msgid "Unable to parse BOX record string `%s'\n"
 msgstr "Misslyckades att läsa kompislista från \"%s\"\n"
 
-#: src/gns/plugin_rest_gns.c:445
+#: src/gns/plugin_rest_gns.c:447
 #, fuzzy
 msgid "Gns REST API initialized\n"
 msgstr " Anslutning misslyckades\n"
@@ -4548,7 +4552,7 @@ msgid "# valid HELLOs downloaded from hostlist servers"
 msgstr ""
 
 #: src/hostlist/gnunet-daemon-hostlist_client.c:677
-#: src/hostlist/gnunet-daemon-hostlist_client.c:1459
+#: src/hostlist/gnunet-daemon-hostlist_client.c:1460
 msgid "# advertised hostlist URIs"
 msgstr ""
 
@@ -4601,7 +4605,7 @@ msgid "# hostlist downloads initiated"
 msgstr ""
 
 #: src/hostlist/gnunet-daemon-hostlist_client.c:1144
-#: src/hostlist/gnunet-daemon-hostlist_client.c:1726
+#: src/hostlist/gnunet-daemon-hostlist_client.c:1728
 msgid "# milliseconds between hostlist downloads"
 msgstr ""
 
@@ -4631,50 +4635,50 @@ msgstr "antal meddelanden att använda per iteration"
 msgid "Could not open file `%s' for reading to load hostlists: %s\n"
 msgstr "Kunde inte slå upp \"%s\": %s\n"
 
-#: src/hostlist/gnunet-daemon-hostlist_client.c:1452
+#: src/hostlist/gnunet-daemon-hostlist_client.c:1453
 #, c-format
 msgid "%u hostlist URIs loaded from file\n"
 msgstr ""
 
-#: src/hostlist/gnunet-daemon-hostlist_client.c:1455
+#: src/hostlist/gnunet-daemon-hostlist_client.c:1456
 msgid "# hostlist URIs read from file"
 msgstr ""
 
-#: src/hostlist/gnunet-daemon-hostlist_client.c:1506
+#: src/hostlist/gnunet-daemon-hostlist_client.c:1507
 #, fuzzy, c-format
 msgid "Could not open file `%s' for writing to save hostlists: %s\n"
 msgstr "Kunde inte slå upp \"%s\": %s\n"
 
-#: src/hostlist/gnunet-daemon-hostlist_client.c:1513
+#: src/hostlist/gnunet-daemon-hostlist_client.c:1514
 #, fuzzy, c-format
 msgid "Writing %u hostlist URIs to `%s'\n"
 msgstr "Misslyckades att läsa kompislista från \"%s\"\n"
 
-#: src/hostlist/gnunet-daemon-hostlist_client.c:1545
-#: src/hostlist/gnunet-daemon-hostlist_client.c:1564
+#: src/hostlist/gnunet-daemon-hostlist_client.c:1547
+#: src/hostlist/gnunet-daemon-hostlist_client.c:1566
 #, c-format
 msgid "Error writing hostlist URIs to file `%s'\n"
 msgstr ""
 
-#: src/hostlist/gnunet-daemon-hostlist_client.c:1558
+#: src/hostlist/gnunet-daemon-hostlist_client.c:1560
 msgid "# hostlist URIs written to file"
 msgstr ""
 
-#: src/hostlist/gnunet-daemon-hostlist_client.c:1655
+#: src/hostlist/gnunet-daemon-hostlist_client.c:1657
 #: src/transport/plugin_transport_http_client.c:2301
 #, c-format
 msgid "Invalid proxy type: `%s', disabling proxy! Check configuration!\n"
 msgstr ""
 
-#: src/hostlist/gnunet-daemon-hostlist_client.c:1684
+#: src/hostlist/gnunet-daemon-hostlist_client.c:1686
 msgid "Learning is enabled on this peer\n"
 msgstr ""
 
-#: src/hostlist/gnunet-daemon-hostlist_client.c:1697
+#: src/hostlist/gnunet-daemon-hostlist_client.c:1699
 msgid "Learning is not enabled on this peer\n"
 msgstr ""
 
-#: src/hostlist/gnunet-daemon-hostlist_client.c:1711
+#: src/hostlist/gnunet-daemon-hostlist_client.c:1713
 #, c-format
 msgid ""
 "Since learning is not enabled on this peer, hostlist file `%s' was removed\n"
@@ -4800,47 +4804,47 @@ msgstr "Kunde inte skapa namnrymd \"%s\" (existerar?).\n"
 msgid "Failed to set default ego: %s\n"
 msgstr "Kunde inte skapa namnrymd \"%s\" (existerar?).\n"
 
-#: src/identity/gnunet-identity.c:445
+#: src/identity/gnunet-identity.c:446
 msgid "create ego NAME"
 msgstr ""
 
-#: src/identity/gnunet-identity.c:450
+#: src/identity/gnunet-identity.c:451
 msgid "delete ego NAME "
 msgstr ""
 
-#: src/identity/gnunet-identity.c:455
+#: src/identity/gnunet-identity.c:457
 msgid ""
 "set the private key for the identity to PRIVATE_KEY (use together with -C)"
 msgstr ""
 
-#: src/identity/gnunet-identity.c:459
+#: src/identity/gnunet-identity.c:461
 msgid "display all egos"
 msgstr ""
 
-#: src/identity/gnunet-identity.c:463
+#: src/identity/gnunet-identity.c:465
 msgid "reduce output"
 msgstr ""
 
-#: src/identity/gnunet-identity.c:470
+#: src/identity/gnunet-identity.c:472
 msgid ""
 "set default identity to NAME for a subsystem SUBSYSTEM (use together with -"
 "s) or restrict results to NAME (use together with -d)"
 msgstr ""
 
-#: src/identity/gnunet-identity.c:474
+#: src/identity/gnunet-identity.c:476
 msgid "run in monitor mode egos"
 msgstr ""
 
-#: src/identity/gnunet-identity.c:478
+#: src/identity/gnunet-identity.c:480
 msgid "display private keys as well"
 msgstr ""
 
-#: src/identity/gnunet-identity.c:485
+#: src/identity/gnunet-identity.c:487
 msgid ""
 "set default identity to EGO for a subsystem SUBSYSTEM (use together with -e)"
 msgstr ""
 
-#: src/identity/gnunet-identity.c:500
+#: src/identity/gnunet-identity.c:502
 msgid "Maintain egos"
 msgstr ""
 
@@ -4891,7 +4895,7 @@ msgstr "Kunde inte spara konfigurationsfil \"%s\":"
 msgid "Failed to create directory `%s' for storing egos\n"
 msgstr "Misslyckades att läsa kompislista från \"%s\"\n"
 
-#: src/identity/plugin_rest_identity.c:1406
+#: src/identity/plugin_rest_identity.c:1384
 #, fuzzy
 msgid "Identity REST API initialized\n"
 msgstr " Anslutning misslyckades\n"
@@ -4941,7 +4945,7 @@ msgstr "Ogiltigt argument: \"%s\"\n"
 msgid "You must specify a name\n"
 msgstr "Du måste ange en mottagare!\n"
 
-#: src/namecache/gnunet-namecache.c:214 src/namestore/gnunet-namestore.c:1639
+#: src/namecache/gnunet-namecache.c:214 src/namestore/gnunet-namestore.c:1640
 msgid "name of the record to add/delete/display"
 msgstr ""
 
@@ -4950,7 +4954,7 @@ msgstr ""
 msgid "specifies the public key of the zone to look in"
 msgstr "ange prioritet för innehållet"
 
-#: src/namecache/gnunet-namecache.c:233 src/namestore/gnunet-namestore.c:1700
+#: src/namecache/gnunet-namecache.c:233 src/namestore/gnunet-namestore.c:1701
 #, fuzzy
 msgid "GNUnet zone manipulation tool"
 msgstr "GNUnet-konfiguration"
@@ -5064,10 +5068,10 @@ msgstr "Misslyckades att skicka HTTP-begäran till värd \"%s\": %s\n"
 msgid "No options given\n"
 msgstr ""
 
-#: src/namestore/gnunet-namestore.c:1014 src/namestore/gnunet-namestore.c:1065
-#: src/namestore/gnunet-namestore.c:1075 src/namestore/gnunet-namestore.c:1104
-#: src/namestore/gnunet-namestore.c:1125 src/namestore/gnunet-namestore.c:1152
-#: src/namestore/gnunet-namestore.c:1228
+#: src/namestore/gnunet-namestore.c:1014 src/namestore/gnunet-namestore.c:1066
+#: src/namestore/gnunet-namestore.c:1076 src/namestore/gnunet-namestore.c:1105
+#: src/namestore/gnunet-namestore.c:1126 src/namestore/gnunet-namestore.c:1153
+#: src/namestore/gnunet-namestore.c:1229
 #, fuzzy, c-format
 msgid "Missing option `%s' for operation `%s'\n"
 msgstr "Konfigurationsfil \"%s\" skapad.\n"
@@ -5081,53 +5085,53 @@ msgstr ""
 msgid "Invalid nick `%s'\n"
 msgstr "Ogiltiga argument: "
 
-#: src/namestore/gnunet-namestore.c:1067 src/namestore/gnunet-namestore.c:1077
-#: src/namestore/gnunet-namestore.c:1106 src/namestore/gnunet-namestore.c:1127
-#: src/namestore/gnunet-namestore.c:1230
+#: src/namestore/gnunet-namestore.c:1068 src/namestore/gnunet-namestore.c:1078
+#: src/namestore/gnunet-namestore.c:1107 src/namestore/gnunet-namestore.c:1128
+#: src/namestore/gnunet-namestore.c:1231
 msgid "add"
 msgstr ""
 
-#: src/namestore/gnunet-namestore.c:1085
+#: src/namestore/gnunet-namestore.c:1086
 #, fuzzy, c-format
 msgid "Unsupported type `%s'\n"
 msgstr "Kommando \"%s\" stöds ej.  Avbryter.\n"
 
-#: src/namestore/gnunet-namestore.c:1095
+#: src/namestore/gnunet-namestore.c:1096
 #, c-format
 msgid "For DNS record types `SRV', `TLSA' and `OPENPGPKEY'"
 msgstr ""
 
-#: src/namestore/gnunet-namestore.c:1115
+#: src/namestore/gnunet-namestore.c:1116
 #, fuzzy, c-format
 msgid "Value `%s' invalid for record type `%s'\n"
 msgstr "%s: symbolvärde \"%s\" ogiltigt för %s\n"
 
-#: src/namestore/gnunet-namestore.c:1134 src/namestore/gnunet-namestore.c:1237
+#: src/namestore/gnunet-namestore.c:1135 src/namestore/gnunet-namestore.c:1238
 #, fuzzy, c-format
 msgid "Invalid time format `%s'\n"
 msgstr "Ogiltigt format för IP: \"%s\"\n"
 
-#: src/namestore/gnunet-namestore.c:1154
+#: src/namestore/gnunet-namestore.c:1155
 msgid "del"
 msgstr ""
 
-#: src/namestore/gnunet-namestore.c:1197
+#: src/namestore/gnunet-namestore.c:1198
 #, fuzzy, c-format
 msgid "Invalid public key for reverse lookup `%s'\n"
 msgstr "Ogiltigt argument: \"%s\"\n"
 
-#: src/namestore/gnunet-namestore.c:1220
+#: src/namestore/gnunet-namestore.c:1221
 #: src/peerinfo-tool/gnunet-peerinfo.c:736
 #, fuzzy, c-format
 msgid "Invalid URI `%s'\n"
 msgstr "Ogiltiga argument: "
 
-#: src/namestore/gnunet-namestore.c:1290
+#: src/namestore/gnunet-namestore.c:1291
 #, c-format
 msgid "Label `%s' contains `.' which is not allowed\n"
 msgstr ""
 
-#: src/namestore/gnunet-namestore.c:1340
+#: src/namestore/gnunet-namestore.c:1341
 #, c-format
 msgid ""
 "No default identity configured for `namestore' subsystem\n"
@@ -5135,102 +5139,102 @@ msgid ""
 "Run gnunet-identity -d to get a list of choices for $NAME\n"
 msgstr ""
 
-#: src/namestore/gnunet-namestore.c:1405
+#: src/namestore/gnunet-namestore.c:1406
 #, fuzzy, c-format
 msgid "Superfluous command line arguments (starting with `%s') ignored\n"
 msgstr "Onödiga argument (ignorerade).\n"
 
-#: src/namestore/gnunet-namestore.c:1434
+#: src/namestore/gnunet-namestore.c:1435
 #, fuzzy, c-format
 msgid "Cannot connect to identity service\n"
 msgstr "Kunde inte ansluta till gnunetd.\n"
 
-#: src/namestore/gnunet-namestore.c:1481
+#: src/namestore/gnunet-namestore.c:1482
 msgid "Empty record line argument is not allowed.\n"
 msgstr ""
 
-#: src/namestore/gnunet-namestore.c:1493
+#: src/namestore/gnunet-namestore.c:1494
 #, c-format
 msgid "Invalid expiration time `%s' (must be without unit)\n"
 msgstr ""
 
-#: src/namestore/gnunet-namestore.c:1505 src/namestore/gnunet-namestore.c:1521
-#: src/namestore/gnunet-namestore.c:1538
+#: src/namestore/gnunet-namestore.c:1506 src/namestore/gnunet-namestore.c:1522
+#: src/namestore/gnunet-namestore.c:1539
 #, fuzzy, c-format
 msgid "Missing entries in record line `%s'.\n"
 msgstr "Kunde inte slå upp \"%s\": %s\n"
 
-#: src/namestore/gnunet-namestore.c:1513
+#: src/namestore/gnunet-namestore.c:1514
 #, fuzzy, c-format
 msgid "Unknown record type `%s'\n"
 msgstr "Okänd operation \"%s\"\n"
 
-#: src/namestore/gnunet-namestore.c:1551
+#: src/namestore/gnunet-namestore.c:1552
 #, fuzzy, c-format
 msgid "Invalid record data for type %s: `%s'.\n"
 msgstr "Ogiltigt format för IP: \"%s\"\n"
 
-#: src/namestore/gnunet-namestore.c:1608
+#: src/namestore/gnunet-namestore.c:1609
 msgid "add record"
 msgstr ""
 
-#: src/namestore/gnunet-namestore.c:1611
+#: src/namestore/gnunet-namestore.c:1612
 msgid "delete record"
 msgstr ""
 
-#: src/namestore/gnunet-namestore.c:1615
+#: src/namestore/gnunet-namestore.c:1616
 msgid "display records"
 msgstr ""
 
-#: src/namestore/gnunet-namestore.c:1622
+#: src/namestore/gnunet-namestore.c:1623
 msgid ""
 "expiration time for record to use (for adding only), \"never\" is possible"
 msgstr ""
 
-#: src/namestore/gnunet-namestore.c:1628
+#: src/namestore/gnunet-namestore.c:1629
 #, fuzzy
 msgid "set the desired nick name for the zone"
 msgstr "Skriv ut information om GNUnets motparter."
 
-#: src/namestore/gnunet-namestore.c:1633
+#: src/namestore/gnunet-namestore.c:1634
 #, fuzzy
 msgid "monitor changes in the namestore"
 msgstr "Misslyckades att ansluta till gnunetd.\n"
 
-#: src/namestore/gnunet-namestore.c:1645
+#: src/namestore/gnunet-namestore.c:1646
 #, fuzzy
 msgid "determine our name for the given PKEY"
 msgstr "Skriv ut information om GNUnets motparter."
 
-#: src/namestore/gnunet-namestore.c:1652
+#: src/namestore/gnunet-namestore.c:1653
 msgid ""
 "set record set to values given by (possibly multiple) RECORDLINES; can be "
 "specified multiple times"
 msgstr ""
 
-#: src/namestore/gnunet-namestore.c:1658
+#: src/namestore/gnunet-namestore.c:1659
 msgid "type of the record to add/delete/display"
 msgstr ""
 
-#: src/namestore/gnunet-namestore.c:1663
+#: src/namestore/gnunet-namestore.c:1664
 msgid "URI to import into our zone"
 msgstr ""
 
-#: src/namestore/gnunet-namestore.c:1669
+#: src/namestore/gnunet-namestore.c:1670
 msgid "value of the record to add/delete"
 msgstr ""
 
-#: src/namestore/gnunet-namestore.c:1673
+#: src/namestore/gnunet-namestore.c:1674
 msgid "create or list public record"
 msgstr ""
 
-#: src/namestore/gnunet-namestore.c:1679
+#: src/namestore/gnunet-namestore.c:1680
 msgid ""
 "create shadow record (only valid if all other records of the same type have "
 "expired"
 msgstr ""
 
-#: src/namestore/gnunet-namestore.c:1685
+#: src/namestore/gnunet-namestore.c:1686
 #, fuzzy
 msgid "name of the ego controlling the zone"
 msgstr "Visa värde av alternativet"
@@ -5330,7 +5334,7 @@ msgstr ""
 msgid "Flat file database running\n"
 msgstr ""
 
-#: src/namestore/plugin_rest_namestore.c:1093
+#: src/namestore/plugin_rest_namestore.c:1103
 #, fuzzy
 msgid "Namestore REST API initialized\n"
 msgstr " Anslutning misslyckades\n"
@@ -5608,7 +5612,7 @@ msgstr ""
 msgid "gnunet-helper-nat-server generated malformed address `%s'\n"
 msgstr ""
 
-#: src/nat/gnunet-service-nat_helper.c:250
+#: src/nat/gnunet-service-nat_helper.c:249
 #, fuzzy, c-format
 msgid "Failed to start %s\n"
 msgstr "Misslyckades att starta samling.\n"
@@ -5617,7 +5621,7 @@ msgstr "Misslyckades att starta samling.\n"
 msgid "`external-ip' command not found\n"
 msgstr ""
 
-#: src/nat/gnunet-service-nat_mini.c:608
+#: src/nat/gnunet-service-nat_mini.c:607
 msgid "`upnpc' command not found\n"
 msgstr ""
 
@@ -5652,8 +5656,8 @@ msgstr ""
 msgid "Measure quality and performance of the NSE service."
 msgstr "Kan inte tillgå tjänsten"
 
-#: src/nse/gnunet-service-nse.c:1438
-#: src/revocation/gnunet-service-revocation.c:842 src/util/gnunet-scrypt.c:250
+#: src/nse/gnunet-service-nse.c:1443
+#: src/revocation/gnunet-service-revocation.c:834 src/util/gnunet-scrypt.c:257
 msgid "Value is too large.\n"
 msgstr ""
 
@@ -5723,7 +5727,7 @@ msgid "\tExpires: %s \t %s\n"
 msgstr ""
 
 #: src/peerinfo-tool/gnunet-peerinfo.c:292
-#: src/peerinfo-tool/plugin_rest_peerinfo.c:501
+#: src/peerinfo-tool/plugin_rest_peerinfo.c:523
 #, fuzzy, c-format
 msgid "Failure: Cannot convert address to string for peer `%s'\n"
 msgstr "Misslyckades att binda till UDP-port %d.\n"
@@ -5803,7 +5807,7 @@ msgstr "Testar transport(er) %s\n"
 msgid "Failed to load transport plugin for `%s'\n"
 msgstr "Kunde inte slå upp \"%s\": %s\n"
 
-#: src/peerinfo-tool/plugin_rest_peerinfo.c:797
+#: src/peerinfo-tool/plugin_rest_peerinfo.c:809
 #, fuzzy
 msgid "Peerinfo REST API initialized\n"
 msgstr " Anslutning misslyckades\n"
@@ -5919,97 +5923,101 @@ msgstr "Misslyckades att initiera tjänsten \"%s\".\n"
 msgid "Daemon to run to perform IP protocol translation to GNUnet"
 msgstr ""
 
-#: src/reclaim/gnunet-reclaim.c:799
+#: src/reclaim/gnunet-reclaim.c:801
 #, fuzzy, c-format
 msgid "Ego is required\n"
 msgstr "%s: flagga \"%s\" är tvetydig\n"
 
-#: src/reclaim/gnunet-reclaim.c:806
+#: src/reclaim/gnunet-reclaim.c:808
 #, c-format
 msgid "Attribute value missing!\n"
 msgstr ""
 
-#: src/reclaim/gnunet-reclaim.c:813
+#: src/reclaim/gnunet-reclaim.c:815
 #, fuzzy, c-format
 msgid "Requesting party key is required!\n"
 msgstr "%s: flagga \"%s\" är tvetydig\n"
 
-#: src/reclaim/gnunet-reclaim.c:831
+#: src/reclaim/gnunet-reclaim.c:833
 msgid "Add an attribute NAME"
 msgstr ""
 
-#: src/reclaim/gnunet-reclaim.c:836
+#: src/reclaim/gnunet-reclaim.c:838
 msgid "Delete the attribute with ID"
 msgstr ""
 
-#: src/reclaim/gnunet-reclaim.c:841
+#: src/reclaim/gnunet-reclaim.c:843
 msgid "The attribute VALUE"
 msgstr ""
 
-#: src/reclaim/gnunet-reclaim.c:846
+#: src/reclaim/gnunet-reclaim.c:848
 #, fuzzy
 msgid "The EGO to use"
 msgstr "meddelandestorlek"
 
-#: src/reclaim/gnunet-reclaim.c:852
+#: src/reclaim/gnunet-reclaim.c:854
 msgid "Specify the relying party for issue"
 msgstr ""
 
-#: src/reclaim/gnunet-reclaim.c:856
+#: src/reclaim/gnunet-reclaim.c:858
 msgid "List attributes for EGO"
 msgstr ""
 
-#: src/reclaim/gnunet-reclaim.c:860
-msgid "List attestations for EGO"
+#: src/reclaim/gnunet-reclaim.c:862
+msgid "List credentials for EGO"
 msgstr ""
 
-#: src/reclaim/gnunet-reclaim.c:866
-msgid "Attestation to use for attribute"
+#: src/reclaim/gnunet-reclaim.c:868
+msgid "Credential to use for attribute"
 msgstr ""
 
-#: src/reclaim/gnunet-reclaim.c:871
-msgid "Attestation name"
+#: src/reclaim/gnunet-reclaim.c:873
+msgid "Credential name"
 msgstr ""
 
-#: src/reclaim/gnunet-reclaim.c:877
+#: src/reclaim/gnunet-reclaim.c:879
 msgid "Issue a ticket for a set of attributes separated by comma"
 msgstr ""
 
-#: src/reclaim/gnunet-reclaim.c:882
+#: src/reclaim/gnunet-reclaim.c:884
 msgid "Consume a ticket"
 msgstr ""
 
-#: src/reclaim/gnunet-reclaim.c:887
+#: src/reclaim/gnunet-reclaim.c:889
 msgid "Revoke a ticket"
 msgstr ""
 
-#: src/reclaim/gnunet-reclaim.c:892
+#: src/reclaim/gnunet-reclaim.c:894
 msgid "Type of attribute"
 msgstr ""
 
-#: src/reclaim/gnunet-reclaim.c:896
+#: src/reclaim/gnunet-reclaim.c:899
+msgid "Type of credential"
+msgstr ""
+
+#: src/reclaim/gnunet-reclaim.c:903
 msgid "List tickets of ego"
 msgstr ""
 
-#: src/reclaim/gnunet-reclaim.c:902
+#: src/reclaim/gnunet-reclaim.c:909
 msgid "Expiration interval of the attribute"
 msgstr ""
 
-#: src/reclaim/gnunet-reclaim.c:910
+#: src/reclaim/gnunet-reclaim.c:917
 msgid "re:claimID command line tool"
 msgstr ""
 
-#: src/reclaim/plugin_rest_openid_connect.c:2481
+#: src/reclaim/plugin_rest_openid_connect.c:2618
 #, fuzzy
 msgid "OpenID Connect REST API initialized\n"
 msgstr " Anslutning misslyckades\n"
 
-#: src/reclaim/plugin_rest_reclaim.c:1476
+#: src/reclaim/plugin_rest_reclaim.c:1502
 #, fuzzy
 msgid "Identity Provider REST API initialized\n"
 msgstr " Anslutning misslyckades\n"
 
-#: src/reclaim/reclaim_api.c:540
+#: src/reclaim/reclaim_api.c:545
 #, fuzzy
 msgid "failed to store record\n"
 msgstr "Misslyckades att starta samling.\n"
@@ -6104,17 +6112,17 @@ msgstr "\"%s\" är inte en fil.\n"
 msgid "Search string `%s' is too long!\n"
 msgstr "\"%s\" är inte en fil.\n"
 
-#: src/rest/gnunet-rest-server.c:1051
+#: src/rest/gnunet-rest-server.c:1266
 #, fuzzy
 msgid "GNUnet REST server"
 msgstr "Spåra GNUnets nätverkstopologi."
 
-#: src/rest/plugin_rest_config.c:402
+#: src/rest/plugin_rest_config.c:427
 #, fuzzy
 msgid "CONFIG REST API initialized\n"
 msgstr " Anslutning misslyckades\n"
 
-#: src/rest/plugin_rest_copying.c:209
+#: src/rest/plugin_rest_copying.c:211
 #, fuzzy
 msgid "COPYING REST API initialized\n"
 msgstr " Anslutning misslyckades\n"
@@ -6251,26 +6259,26 @@ msgstr "# byte mottogs via TCP"
 msgid "# revocation messages received via set union"
 msgstr "# krypterade PONG-meddelanden mottagna"
 
-#: src/revocation/gnunet-service-revocation.c:470
+#: src/revocation/gnunet-service-revocation.c:469
 #, c-format
 msgid "Error computing revocation set union with %s\n"
 msgstr ""
 
-#: src/revocation/gnunet-service-revocation.c:474
+#: src/revocation/gnunet-service-revocation.c:473
 #, fuzzy
 msgid "# revocation set unions failed"
 msgstr "# sessionsnycklar accepterade"
 
-#: src/revocation/gnunet-service-revocation.c:486
+#: src/revocation/gnunet-service-revocation.c:481
 #, fuzzy
 msgid "# revocation set unions completed"
 msgstr "# klartext PONG-meddelanden mottagna"
 
-#: src/revocation/gnunet-service-revocation.c:526
+#: src/revocation/gnunet-service-revocation.c:519
 msgid "SET service crashed, terminating revocation service\n"
 msgstr ""
 
-#: src/revocation/gnunet-service-revocation.c:881
+#: src/revocation/gnunet-service-revocation.c:871
 #, fuzzy
 msgid "Could not open revocation database file!"
 msgstr "Kunde inte ansluta till gnunetd.\n"
@@ -6361,10 +6369,10 @@ msgstr ""
 msgid "Calculate the Vectorproduct with a GNUnet peer."
 msgstr ""
 
-#: src/scalarproduct/gnunet-service-scalarproduct_alice.c:1363
-#: src/scalarproduct/gnunet-service-scalarproduct_bob.c:1366
-#: src/scalarproduct/gnunet-service-scalarproduct-ecc_alice.c:1127
-#: src/scalarproduct/gnunet-service-scalarproduct-ecc_bob.c:1073
+#: src/scalarproduct/gnunet-service-scalarproduct_alice.c:1358
+#: src/scalarproduct/gnunet-service-scalarproduct_bob.c:1355
+#: src/scalarproduct/gnunet-service-scalarproduct-ecc_alice.c:1118
+#: src/scalarproduct/gnunet-service-scalarproduct-ecc_bob.c:1063
 #, fuzzy
 msgid "Connect to CADET failed\n"
 msgstr " Anslutning misslyckades (fel?)\n"
@@ -6389,53 +6397,64 @@ msgstr ""
 msgid "also profile decryption"
 msgstr ""
 
-#: src/set/gnunet-service-set.c:1916
+#: src/set/gnunet-service-set.c:1916 src/seti/gnunet-service-seti.c:2467
+#: src/setu/gnunet-service-setu.c:3635
 #, fuzzy
 msgid "Could not connect to CADET service\n"
 msgstr "Kunde inte ansluta till gnunetd.\n"
 
 #: src/set/gnunet-set-ibf-profiler.c:268
+#: src/setu/gnunet-setu-ibf-profiler.c:268
 #, fuzzy
 msgid "number of element in set A-B"
 msgstr "antal iterationer"
 
 #: src/set/gnunet-set-ibf-profiler.c:274
+#: src/setu/gnunet-setu-ibf-profiler.c:274
 #, fuzzy
 msgid "number of element in set B-A"
 msgstr "antal iterationer"
 
 #: src/set/gnunet-set-ibf-profiler.c:281
+#: src/setu/gnunet-setu-ibf-profiler.c:281
 msgid "number of common elements in A and B"
 msgstr ""
 
 #: src/set/gnunet-set-ibf-profiler.c:287
+#: src/setu/gnunet-setu-ibf-profiler.c:287
 msgid "hash num"
 msgstr ""
 
 #: src/set/gnunet-set-ibf-profiler.c:293
+#: src/setu/gnunet-setu-ibf-profiler.c:293
 msgid "ibf size"
 msgstr ""
 
-#: src/set/gnunet-set-profiler.c:462
+#: src/set/gnunet-set-profiler.c:462 src/setu/gnunet-setu-profiler.c:453
 msgid "use byzantine mode"
 msgstr ""
 
-#: src/set/gnunet-set-profiler.c:468
+#: src/set/gnunet-set-profiler.c:468 src/setu/gnunet-setu-profiler.c:459
 msgid "force sending full set"
 msgstr ""
 
-#: src/set/gnunet-set-profiler.c:474
+#: src/set/gnunet-set-profiler.c:474 src/setu/gnunet-setu-profiler.c:465
 msgid "number delta operation"
 msgstr ""
 
-#: src/set/gnunet-set-profiler.c:486
+#: src/set/gnunet-set-profiler.c:486 src/setu/gnunet-setu-profiler.c:477
 msgid "operation to execute"
 msgstr ""
 
-#: src/set/gnunet-set-profiler.c:492
+#: src/set/gnunet-set-profiler.c:492 src/seti/gnunet-seti-profiler.c:462
+#: src/setu/gnunet-setu-profiler.c:483
 msgid "element size"
 msgstr ""
 
+#: src/seti/gnunet-seti-profiler.c:457
+msgid "return intersection instead of delta"
+msgstr ""
+
 #: src/sq/sq.c:54
 #, c-format
 msgid "Failure to bind %u-th SQL parameter\n"
@@ -6450,12 +6469,12 @@ msgstr ""
 msgid "Failed to reset sqlite statement with error: %s\n"
 msgstr "\"%s\" misslyckades för fil \"%s\" vid %s:%d med fel: %s\n"
 
-#: src/statistics/gnunet-service-statistics.c:318
+#: src/statistics/gnunet-service-statistics.c:319
 #, fuzzy, c-format
 msgid "Wrote %llu bytes of statistics to `%s'\n"
 msgstr "Ladda ner filer från GNUnet."
 
-#: src/statistics/gnunet-service-statistics.c:983
+#: src/statistics/gnunet-service-statistics.c:984
 #, fuzzy, c-format
 msgid "Loading %llu bytes of statistics from `%s'\n"
 msgstr "Ladda ner filer från GNUnet."
@@ -6638,7 +6657,7 @@ msgid ""
 msgstr ""
 
 #: src/testbed/gnunet-daemon-testbed-underlay.c:234 src/testing/list-keys.c:47
-#: src/testing/testing.c:284 src/util/gnunet-ecc.c:318
+#: src/testing/testing.c:278 src/util/gnunet-ecc.c:318
 #, c-format
 msgid "Incorrect hostkey file format: %s\n"
 msgstr ""
@@ -6895,59 +6914,59 @@ msgstr ""
 msgid "list COUNT number of keys"
 msgstr ""
 
-#: src/testing/testing.c:267
+#: src/testing/testing.c:261
 #, c-format
 msgid "Hostkeys file not found: %s\n"
 msgstr ""
 
-#: src/testing/testing.c:721
+#: src/testing/testing.c:714
 #, fuzzy, c-format
 msgid "Key number %u does not exist\n"
 msgstr "antal meddelanden att använda per iteration"
 
-#: src/testing/testing.c:1195
+#: src/testing/testing.c:1188
 #, c-format
 msgid ""
 "You attempted to create a testbed with more than %u hosts.  Please "
 "precompute more hostkeys first.\n"
 msgstr ""
 
-#: src/testing/testing.c:1204
+#: src/testing/testing.c:1197
 #, fuzzy, c-format
 msgid "Failed to initialize hostkey for peer %u\n"
 msgstr "Misslyckades att initiera tjänsten \"%s\".\n"
 
-#: src/testing/testing.c:1214
+#: src/testing/testing.c:1207
 #, fuzzy
 msgid "PRIVATE_KEY option in PEER section missing in configuration\n"
 msgstr "Inga applikationer definierade i konfiguration!\n"
 
-#: src/testing/testing.c:1227
+#: src/testing/testing.c:1220
 #, fuzzy
 msgid "Failed to create configuration for peer (not enough free ports?)\n"
 msgstr "Kunde inte komma åt namnrymdsinformation.\n"
 
-#: src/testing/testing.c:1243
+#: src/testing/testing.c:1236
 #, fuzzy, c-format
 msgid "Cannot open hostkey file `%s': %s\n"
 msgstr "Kunde inte skapa värdnyckel!\n"
 
-#: src/testing/testing.c:1257
+#: src/testing/testing.c:1250
 #, fuzzy, c-format
 msgid "Failed to write hostkey file for peer %u: %s\n"
 msgstr "Kunde inte skapa användarkonto:"
 
-#: src/testing/testing.c:1285
+#: src/testing/testing.c:1278
 #, fuzzy, c-format
 msgid "Failed to write configuration file `%s' for peer %u: %s\n"
 msgstr "Kunde inte spara konfigurationsfil \"%s\":"
 
-#: src/testing/testing.c:1392
+#: src/testing/testing.c:1384
 #, fuzzy, c-format
 msgid "Failed to start `%s': %s\n"
 msgstr "Fel vid %s:%d.\n"
 
-#: src/testing/testing.c:1691
+#: src/testing/testing.c:1683
 #, fuzzy, c-format
 msgid "Failed to load configuration from %s\n"
 msgstr "Kunde inte spara konfigurationsfil \"%s\":"
@@ -7025,40 +7044,40 @@ msgstr "# krypterade PONG-meddelanden mottagna"
 msgid "GNUnet topology control"
 msgstr ""
 
-#: src/transport/gnunet-communicator-tcp.c:2458
-#: src/transport/gnunet-communicator-udp.c:2825
-#: src/transport/gnunet-service-tng.c:10027
+#: src/transport/gnunet-communicator-tcp.c:3189
+#: src/transport/gnunet-communicator-udp.c:2826
+#: src/transport/gnunet-service-tng.c:10014
 #: src/transport/gnunet-service-transport.c:2624
 #, fuzzy
 msgid "Transport service is lacking key configuration settings. Exiting.\n"
 msgstr "GNUnet-konfiguration"
 
-#: src/transport/gnunet-communicator-tcp.c:2754
+#: src/transport/gnunet-communicator-tcp.c:3494
 msgid "GNUnet TCP communicator"
 msgstr ""
 
-#: src/transport/gnunet-communicator-udp.c:2897
+#: src/transport/gnunet-communicator-udp.c:2898
 msgid "GNUnet UDP communicator"
 msgstr ""
 
-#: src/transport/gnunet-communicator-unix.c:788
+#: src/transport/gnunet-communicator-unix.c:789
 #, fuzzy
 msgid ""
 "Maximum number of UNIX connections exceeded, dropping incoming message\n"
 msgstr "Maximalt antal chattklienter uppnått.\n"
 
-#: src/transport/gnunet-communicator-unix.c:1015
+#: src/transport/gnunet-communicator-unix.c:1016
 #, fuzzy
 msgid "UNIX communicator is lacking key configuration settings. Exiting.\n"
 msgstr "GNUnet-konfiguration"
 
-#: src/transport/gnunet-communicator-unix.c:1060
+#: src/transport/gnunet-communicator-unix.c:1061
 #: src/transport/plugin_transport_unix.c:1383
 #, fuzzy, c-format
 msgid "Cannot create path to `%s'\n"
 msgstr "Kunde inte skapa namnrymd \"%s\" (existerar?).\n"
 
-#: src/transport/gnunet-communicator-unix.c:1138
+#: src/transport/gnunet-communicator-unix.c:1139
 msgid "GNUnet UNIX domain socket communicator"
 msgstr ""
 
@@ -8165,7 +8184,7 @@ msgid "do daemonize (detach from terminal)"
 msgstr ""
 
 #: src/transport/tcp_service_legacy.c:1397
-#: src/transport/transport-testing2.c:1061 src/util/service.c:2072
+#: src/transport/transport-testing2.c:1116 src/util/service.c:2072
 #: src/util/service.c:2084
 #, fuzzy, c-format
 msgid "Malformed configuration file `%s', exit ...\n"
@@ -8209,7 +8228,7 @@ msgstr ""
 msgid "Invalid handle type while reading `%s'"
 msgstr "Ogiltiga kommandoradsargument:\n"
 
-#: src/util/bio.c:335 src/util/bio.c:838
+#: src/util/bio.c:335 src/util/bio.c:839
 msgid "string length"
 msgstr ""
 
@@ -8228,7 +8247,7 @@ msgstr ""
 msgid "String `%s' longer than allowed (%u > %u)"
 msgstr ""
 
-#: src/util/bio.c:398 src/util/bio.c:863 src/util/bio.c:880
+#: src/util/bio.c:398 src/util/bio.c:864 src/util/bio.c:881
 msgid "metadata length"
 msgstr ""
 
@@ -8242,25 +8261,25 @@ msgstr ""
 msgid "Failed to deserialize metadata `%s'"
 msgstr "Misslyckades att leverera \"%s\" meddelande.\n"
 
-#: src/util/bio.c:667
+#: src/util/bio.c:668
 msgid "Unable to flush buffer to file"
 msgstr ""
 
-#: src/util/bio.c:729 src/util/bio.c:750
+#: src/util/bio.c:730 src/util/bio.c:751
 #, fuzzy, c-format
 msgid "Error while writing `%s' to file: %s"
 msgstr "Fel vid nedladdning: %s\n"
 
-#: src/util/bio.c:731
+#: src/util/bio.c:732
 msgid "No associated file"
 msgstr ""
 
-#: src/util/bio.c:815
+#: src/util/bio.c:816
 #, fuzzy, c-format
 msgid "Invalid handle type while writing `%s'"
 msgstr "Ogiltigt format för IP: \"%s\"\n"
 
-#: src/util/bio.c:875
+#: src/util/bio.c:876
 #, fuzzy, c-format
 msgid "Failed to serialize metadata `%s'"
 msgstr "Misslyckades att leverera \"%s\" meddelande.\n"
@@ -8748,15 +8767,15 @@ msgstr ""
 msgid "No handler known for subsystem `%s'\n"
 msgstr ""
 
-#: src/util/gnunet-qr.c:358
+#: src/util/gnunet-qr.c:357
 msgid "use video-device DEVICE (default: /dev/video0"
 msgstr ""
 
-#: src/util/gnunet-qr.c:363
+#: src/util/gnunet-qr.c:362
 msgid "do not show preview windows"
 msgstr ""
 
-#: src/util/gnunet-qr.c:373
+#: src/util/gnunet-qr.c:372
 msgid "Scan a QR code using a video device and import the uri read"
 msgstr ""
 
@@ -8768,28 +8787,28 @@ msgstr ""
 msgid "Use build-in GNUnet stub resolver"
 msgstr ""
 
-#: src/util/gnunet-scrypt.c:222
+#: src/util/gnunet-scrypt.c:229
 #, fuzzy, c-format
 msgid "Loading hostkey from `%s' failed.\n"
 msgstr "Tolkning av HTTP-svar för URL \"%s\" misslyckades.\n"
 
-#: src/util/gnunet-scrypt.c:288
+#: src/util/gnunet-scrypt.c:295
 msgid "number of bits to require for the proof of work"
 msgstr ""
 
-#: src/util/gnunet-scrypt.c:294
+#: src/util/gnunet-scrypt.c:301
 msgid "file with private key, otherwise default is used"
 msgstr ""
 
-#: src/util/gnunet-scrypt.c:300
+#: src/util/gnunet-scrypt.c:307
 msgid "file with proof of work, otherwise default is used"
 msgstr ""
 
-#: src/util/gnunet-scrypt.c:306
+#: src/util/gnunet-scrypt.c:313
 msgid "time to wait between calculations"
 msgstr ""
 
-#: src/util/gnunet-scrypt.c:319
+#: src/util/gnunet-scrypt.c:326
 #, fuzzy
 msgid "Manipulate GNUnet proof of work files"
 msgstr "skriv ut ett värde från konfigurationsfilen till standard ut"
@@ -8803,7 +8822,7 @@ msgstr ""
 msgid "No URI specified on command line\n"
 msgstr ""
 
-#: src/util/gnunet-uri.c:179
+#: src/util/gnunet-uri.c:178
 msgid "Perform default-actions for GNUnet URIs"
 msgstr ""
 
@@ -8817,7 +8836,7 @@ msgstr "Fel vid skapandet av användare"
 msgid "Failed to parse inbound message from helper `%s'\n"
 msgstr "Misslyckades att läsa kompislista från \"%s\"\n"
 
-#: src/util/helper.c:600
+#: src/util/helper.c:602
 #, fuzzy, c-format
 msgid "Error writing to `%s': %s\n"
 msgstr "Fel vid skapandet av användare"
@@ -8947,118 +8966,118 @@ msgstr ""
 msgid "Attempting to proxy service `%s' to invalid port %d or hostname.\n"
 msgstr ""
 
-#: src/util/strings.c:178
+#: src/util/strings.c:179
 msgid "b"
 msgstr "b"
 
-#: src/util/strings.c:502
+#: src/util/strings.c:503
 #, c-format
 msgid "Character sets requested were `%s'->`%s'\n"
 msgstr ""
 
-#: src/util/strings.c:636
+#: src/util/strings.c:637
 msgid "Failed to expand `$HOME': environment variable `HOME' not set"
 msgstr ""
 
-#: src/util/strings.c:705
+#: src/util/strings.c:706
 msgid "µs"
 msgstr ""
 
-#: src/util/strings.c:709
+#: src/util/strings.c:710
 msgid "forever"
 msgstr ""
 
-#: src/util/strings.c:711
+#: src/util/strings.c:712
 msgid "0 ms"
 msgstr ""
 
-#: src/util/strings.c:715
+#: src/util/strings.c:716
 msgid "ms"
 msgstr "ms"
 
-#: src/util/strings.c:719
+#: src/util/strings.c:720
 msgid "s"
 msgstr "s"
 
-#: src/util/strings.c:723
+#: src/util/strings.c:724
 msgid "m"
 msgstr "m"
 
-#: src/util/strings.c:727
+#: src/util/strings.c:728
 msgid "h"
 msgstr "h"
 
-#: src/util/strings.c:733
+#: src/util/strings.c:734
 #, fuzzy
 msgid "day"
 msgstr " dagar"
 
-#: src/util/strings.c:735
+#: src/util/strings.c:736
 #, fuzzy
 msgid "days"
 msgstr " dagar"
 
-#: src/util/strings.c:763
+#: src/util/strings.c:764
 msgid "end of time"
 msgstr ""
 
-#: src/util/strings.c:1239
+#: src/util/strings.c:1240
 msgid "IPv6 address did not start with `['\n"
 msgstr ""
 
-#: src/util/strings.c:1247
+#: src/util/strings.c:1248
 msgid "IPv6 address did contain ':' to separate port number\n"
 msgstr ""
 
-#: src/util/strings.c:1254
+#: src/util/strings.c:1255
 msgid "IPv6 address did contain ']' before ':' to separate port number\n"
 msgstr ""
 
-#: src/util/strings.c:1262
+#: src/util/strings.c:1263
 msgid "IPv6 address did contain a valid port number after the last ':'\n"
 msgstr ""
 
-#: src/util/strings.c:1271
+#: src/util/strings.c:1272
 #, fuzzy, c-format
 msgid "Invalid IPv6 address `%s': %s\n"
 msgstr "Ogiltigt svar på \"%s\".\n"
 
-#: src/util/strings.c:1498 src/util/strings.c:1509
+#: src/util/strings.c:1499 src/util/strings.c:1510
 msgid "Port not in range\n"
 msgstr ""
 
-#: src/util/strings.c:1518
+#: src/util/strings.c:1519
 #, fuzzy, c-format
 msgid "Malformed port policy `%s'\n"
 msgstr "Misslyckades att starta samling.\n"
 
-#: src/util/strings.c:1601 src/util/strings.c:1630 src/util/strings.c:1677
-#: src/util/strings.c:1697
+#: src/util/strings.c:1602 src/util/strings.c:1631 src/util/strings.c:1678
+#: src/util/strings.c:1698
 #, c-format
 msgid "Invalid format for IP: `%s'\n"
 msgstr "Ogiltigt format för IP: \"%s\"\n"
 
-#: src/util/strings.c:1655
+#: src/util/strings.c:1656
 #, c-format
 msgid "Invalid network notation ('/%d' is not legal in IPv4 CIDR)."
 msgstr "Ogiltig nätverksnotation (\"/%d\" är inte giltig i IPv4 CIDR)."
 
-#: src/util/strings.c:1706
+#: src/util/strings.c:1707
 #, fuzzy, c-format
 msgid "Invalid format: `%s'\n"
 msgstr "Ogiltigt format för IP: \"%s\"\n"
 
-#: src/util/strings.c:1759
+#: src/util/strings.c:1760
 #, c-format
 msgid "Invalid network notation (does not end with ';': `%s')\n"
 msgstr "Ogiltig nätverksnotation (slutar inte med \";\": \"%s\")\n"
 
-#: src/util/strings.c:1809
+#: src/util/strings.c:1810
 #, fuzzy, c-format
 msgid "Wrong format `%s' for netmask\n"
 msgstr "Fel format \"%s\" för nätmask: %s\n"
 
-#: src/util/strings.c:1840
+#: src/util/strings.c:1841
 #, fuzzy, c-format
 msgid "Wrong format `%s' for network\n"
 msgstr "Fel format \"%s\" för nätverk: %s\n"
diff --git a/po/update.pl.in b/po/update.pl.in
new file mode 100644
index 0000000000000000000000000000000000000000..7b7af52ef44d7f6603f043c88906942e520b54a9
--- /dev/null
+++ b/po/update.pl.in
@@ -0,0 +1,230 @@
+#!@PERL@ -w
+
+#  GNOME po update utility.
+#  (C) 2000 The Free Software Foundation
+#
+#  Author(s): Kenneth Christiansen
+#  Patches:   Björn Voigt <bjoern@cs.tu-berlin.de>
+
+
+$VERSION = "1.2.5 beta 2";
+$LANG    = $ARGV[0];
+$PACKAGE  = "GNUnet";
+
+if (! $LANG){
+    print "update.pl:  missing file arguments\n";
+    print "Try `update.pl --help' for more information.\n";
+    exit;
+}
+
+if ($LANG=~/^-(.)*/){
+
+    if ("$LANG" eq "--version" || "$LANG" eq "-V"){
+        print "GNOME PO Updater $VERSION\n";
+        print "Written by Kenneth Christiansen <kenneth\@gnome.org>, 2000.\n\n";
+        print "Copyright (C) 2000 Free Software Foundation, Inc.\n";
+        print "This is free software; see the source for copying conditions.  There is NO\n";
+        print "warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n";
+	exit;
+    }
+
+
+    elsif ($LANG eq "--help" || "$LANG" eq "-H"){
+        print "Usage: ./update.pl [OPTIONS] ...LANGCODE\n";
+        print "Updates pot files and merge them with the translations.\n\n";
+        print "  -V, --version                shows the version\n";
+        print "  -H, --help                   shows this help page\n";
+        print "  -P, --pot                    only generates the potfile\n";
+        print "  -M, --maintain               search for missing files in POTFILES.in\n";
+	print "\nExamples of use:\n";
+        print "update.sh --pot    just creates a new pot file from the source\n";
+	print "update.sh da       created new pot file and updated the da.po file\n\n";
+        print "Report bugs to <kenneth\@gnome.org>.\n";
+	exit;
+    }
+
+    elsif($LANG eq "--pot" || "$LANG" eq "-P"){
+
+        print "Building the $PACKAGE.pot ...";
+
+        $b="xgettext --default-domain\=$PACKAGE --directory\=\.\."
+          ." --add-comments --keyword\=\_ --keyword\=N\_"
+          ." --files-from\=\.\/POTFILES\.in ";
+        $b1="test \! -f $PACKAGE\.po \|\| \( rm -f \.\/$PACKAGE\.pot "
+           ."&& mv $PACKAGE\.po \.\/$PACKAGE\.pot \)";
+	if(($ret=system($b . " && " . $b1))==0) {
+	    print "...done\n";
+	}
+	else {
+	    print "...failed\n";
+	}
+
+        exit $ret;
+    }
+
+    elsif ($LANG eq "--maintain" || "$LANG" eq "-M"){
+
+        $a="find ../ -path ../intl -prune -o -print | egrep '.*\\.(c|y|cc|c++|h|gob)\$' ";
+
+        open(BUF2, "POTFILES.in") || die "update.pl:  there's not POTFILES.in!!!\n";
+        print "Searching for missing _(\" \") entries and for deleted files...\n";
+        open(BUF1, "$a|");
+
+
+        @buf2 = <BUF2>;
+        @buf1 = <BUF1>;
+
+        if (-s "POTFILES.ignore") {
+            open FILE, "POTFILES.ignore";
+            while (<FILE>) {
+                if ($_=~/^[^#]/o) {
+                    push @bup, $_;
+                }
+            }
+            print "POTFILES.ignore found! Ignoring files...\n";
+	    @buf2 = (@bup, @buf2);
+	    }
+
+        foreach my $file (@buf1) {
+	    $cmd="xgettext -o - --omit-header --keyword=_ " .
+		"--keyword=N_ " . $file . " |";
+	    open XGET, $cmd;
+	    if(<XGET>) {
+		$file = unpack("x3 A*",$file) . "\n";
+		push @buff1, $file;
+	    }
+	    close XGET;
+#	    open FILE, "<$file";
+#            while (<FILE>) {
+#                if ($_=~/_\(\"/o || $_=~/ngettext\(\"/o){
+#                    $file = unpack("x3 A*",$file) . "\n";
+#                    push @buff1, $file;
+#                    last;
+#                }
+#            }
+	}
+
+        @bufff1 = sort (@buff1);
+
+        @bufff2 = sort (@buf2);
+
+        my %in2;
+        foreach (@bufff2) {
+	    chomp;
+            $in2{$_} = 1;
+        }
+
+        my %in1;
+        foreach (@bufff1) {
+	    chomp;
+            $in1{$_} = 1;
+        }
+
+        foreach (@bufff1) {
+	    chomp;
+            if (!exists($in2{$_})) {
+                push @result, $_ . "\n";
+	    }
+	}
+
+        foreach (@bufff2) {
+	    chomp;
+            if (! -f "../" . $_) {
+                push @deletedfiles, $_ . "\n"; 
+	    }
+	}
+	
+	foreach (@bufff2) {
+	    if (!exists($in1{$_})) {
+		push @noi18nfiles, $_ . "\n";
+	    }
+	}
+
+        if(@result){
+            open OUT, ">POTFILES.in.missing";
+            print OUT @result;
+            print "\nHere are the missing files:\n\n", @result, "\n";
+            print "File POTFILES.in.missing is being placed in directory...\n";
+            print "Please add the files that should be ignored in POTFILES.ignore\n";
+        }
+        else{
+	    unlink("POTFILES.in.missing");
+        }
+	    
+        if(@deletedfiles){
+            open OUT, ">POTFILES.in.deleted";
+            print OUT @deletedfiles;
+            print "\nHere are the deleted files:\n\n", @deletedfiles, "\n";
+            print "File POTFILES.in.deleted is being placed in directory...\n";
+            print "Please delete the files from POTFILES.in or POTFILES.ignore\n";
+        }
+        else{
+	    unlink("POTFILES.in.deleted");
+        }
+
+        if(@noi18nfiles){
+            open OUT, ">POTFILES.in.noi18n";
+            print OUT @noi18nfiles;
+            print "\nHere are the files which currently have no i18n strings:\n\n", 
+	    @noi18nfiles, "\n";
+            print "File POTFILES.in.noi18n is being placed in directory...\n";
+            print "Please delete the files from POTFILES.in or POTFILES.ignore\n";
+	    print "or ignore the files.\n";
+        }
+        else{
+	    unlink("POTFILES.in.noi18n");
+        }
+
+        if( ! @result && ! @deletedfiles ) {
+            print "\nWell, it's all perfect! Congratulation!\n";
+        }
+    }
+
+
+    else{
+        print "update.pl: invalid option -- $LANG\n";
+        print "Try `update.pl --help' for more information.\n";
+    }
+    exit;
+    }
+
+elsif(-s "$LANG.po"){
+
+    print "Building the $PACKAGE.pot ...";
+
+    $c="xgettext --default-domain\=$PACKAGE --directory\=\.\."
+      ." --add-comments --keyword\=\_ --keyword\=N\_"
+      ." --files-from\=\.\/POTFILES\.in ";  
+    $c1="test \! -f $PACKAGE\.po \|\| \( rm -f \.\/$PACKAGE\.pot "
+       ."&& mv $PACKAGE\.po \.\/$PACKAGE\.pot \)";
+
+    if(($ret=system($c . " && " . $c1))==0) {
+	print "...done\n";
+    }
+    else {
+	print "...failed\n";
+    }
+
+    if($ret==0) {
+	print "\nNow merging $LANG.po with $PACKAGE.pot, and creating an updated $LANG.po ...\n";
+
+    
+	$d="if msgmerge $LANG.po $PACKAGE.pot -o $LANG.new.po; then " .
+	    "  mv -f $LANG.new.po $LANG.po; " .
+	    "  msgfmt --statistics  -c -v -o /dev/null $LANG.po; " .
+	    "else " .
+	    "  echo \"msgmerge failed!\"; " .
+	    "  rm -f $LANG.new.po; ".
+	    "fi";
+
+	$ret=system($d);
+
+	exit $ret;
+    }
+}
+
+else{
+    print "update.pl:  sorry $LANG.po does not exist!\n";
+    print "Try `update.pl --help' for more information.\n";    
+    exit;
+}
diff --git a/po/vi.po b/po/vi.po
index 508d64293a63f82ca2f67cd2620d6d34cdd9d698..732d1d4327d8d829fa51372b86963140d4fc0cb6 100644
--- a/po/vi.po
+++ b/po/vi.po
@@ -8,7 +8,7 @@ msgid ""
 msgstr ""
 "Project-Id-Version: gnunet 0.8.0a\n"
 "Report-Msgid-Bugs-To: gnunet-developers@mail.gnu.org\n"
-"POT-Creation-Date: 2020-07-12 17:55+0200\n"
+"POT-Creation-Date: 2020-09-06 10:07+0200\n"
 "PO-Revision-Date: 2008-09-10 22:05+0930\n"
 "Last-Translator: Clytie Siddall <clytie@riverland.net.au>\n"
 "Language-Team: Vietnamese <vi-VN@googlegroups.com>\n"
@@ -19,12 +19,12 @@ msgstr ""
 "Plural-Forms: nplurals=1; plural=0;\n"
 "X-Generator: LocFactoryEditor 1.7b3\n"
 
-#: src/abd/gnunet-abd.c:397 src/namestore/gnunet-namestore.c:1302
+#: src/abd/gnunet-abd.c:397 src/namestore/gnunet-namestore.c:1303
 #, c-format
 msgid "Ego `%s' not known to identity service\n"
 msgstr ""
 
-#: src/abd/gnunet-abd.c:413 src/abd/gnunet-abd.c:896
+#: src/abd/gnunet-abd.c:413 src/abd/gnunet-abd.c:901
 #, fuzzy, c-format
 msgid "Issuer public key `%s' is not well-formed\n"
 msgstr "Đối số không hợp lệ cho « %s ».\n"
@@ -36,109 +36,109 @@ msgstr "Đối số không hợp lệ cho « %s ».\n"
 msgid "Failed to connect to namestore\n"
 msgstr "Không kết nối được đến trình nền gnunetd."
 
-#: src/abd/gnunet-abd.c:835 src/abd/gnunet-abd.c:886
+#: src/abd/gnunet-abd.c:840 src/abd/gnunet-abd.c:891
 #, fuzzy, c-format
 msgid "Issuer public key not well-formed\n"
 msgstr "Đối số không hợp lệ cho « %s ».\n"
 
-#: src/abd/gnunet-abd.c:844 src/abd/gnunet-abd.c:905
+#: src/abd/gnunet-abd.c:849 src/abd/gnunet-abd.c:910
 #, fuzzy, c-format
 msgid "Failed to connect to ABD\n"
 msgstr "Lỗi kết nối đến gnunetd.\n"
 
-#: src/abd/gnunet-abd.c:850
+#: src/abd/gnunet-abd.c:855
 #, c-format
 msgid "You must provide issuer the attribute\n"
 msgstr ""
 
-#: src/abd/gnunet-abd.c:857
+#: src/abd/gnunet-abd.c:862
 #, c-format
 msgid "ego required\n"
 msgstr ""
 
-#: src/abd/gnunet-abd.c:867
+#: src/abd/gnunet-abd.c:872
 #, c-format
 msgid "Subject public key needed\n"
 msgstr ""
 
-#: src/abd/gnunet-abd.c:876
+#: src/abd/gnunet-abd.c:881
 #, fuzzy, c-format
 msgid "Subject public key `%s' is not well-formed\n"
 msgstr "Đối số không hợp lệ cho « %s ».\n"
 
-#: src/abd/gnunet-abd.c:911
+#: src/abd/gnunet-abd.c:916
 #, c-format
 msgid "You must provide issuer and subject attributes\n"
 msgstr ""
 
-#: src/abd/gnunet-abd.c:970
+#: src/abd/gnunet-abd.c:975
 #, c-format
 msgid "Please specify name to lookup, subject key and issuer key!\n"
 msgstr ""
 
-#: src/abd/gnunet-abd.c:991
+#: src/abd/gnunet-abd.c:996
 msgid "verify credential against attribute"
 msgstr ""
 
-#: src/abd/gnunet-abd.c:998
+#: src/abd/gnunet-abd.c:1003
 #, fuzzy
 msgid ""
 "The public key of the subject to lookup thecredential for, or for issuer "
 "side storage: subject and its attributes"
 msgstr "xác định mức ưu tiên của nội dung"
 
-#: src/abd/gnunet-abd.c:1005
+#: src/abd/gnunet-abd.c:1010
 msgid "The private, signed delegate presented by the subject"
 msgstr ""
 
-#: src/abd/gnunet-abd.c:1012
+#: src/abd/gnunet-abd.c:1017
 #, fuzzy
 msgid "The public key of the authority to verify the credential against"
 msgstr "xác định mức ưu tiên của nội dung"
 
-#: src/abd/gnunet-abd.c:1017
+#: src/abd/gnunet-abd.c:1022
 #, fuzzy
 msgid "The ego/zone name to use"
 msgstr "kích cỡ tin nhắn"
 
-#: src/abd/gnunet-abd.c:1023
+#: src/abd/gnunet-abd.c:1028
 msgid "The issuer attribute to verify against or to issue"
 msgstr ""
 
-#: src/abd/gnunet-abd.c:1029
+#: src/abd/gnunet-abd.c:1034
 msgid ""
 "The time to live for the credential.e.g. 5m, 6h, \"1990-12-30 12:00:00\""
 msgstr ""
 
-#: src/abd/gnunet-abd.c:1034
+#: src/abd/gnunet-abd.c:1039
 msgid "collect credentials"
 msgstr ""
 
-#: src/abd/gnunet-abd.c:1039
+#: src/abd/gnunet-abd.c:1044
 msgid "Create and issue a credential issuer side."
 msgstr ""
 
-#: src/abd/gnunet-abd.c:1044
+#: src/abd/gnunet-abd.c:1049
 msgid "Issue a credential subject side."
 msgstr ""
 
-#: src/abd/gnunet-abd.c:1049
+#: src/abd/gnunet-abd.c:1054
 msgid "Create, sign and return a credential subject side."
 msgstr ""
 
-#: src/abd/gnunet-abd.c:1056
+#: src/abd/gnunet-abd.c:1061
 msgid "Import signed credentials that should be issued to a zone/ego"
 msgstr ""
 
-#: src/abd/gnunet-abd.c:1060
+#: src/abd/gnunet-abd.c:1065
 msgid "Create private record entry."
 msgstr ""
 
-#: src/abd/gnunet-abd.c:1066 src/abd/gnunet-abd.c:1072
+#: src/abd/gnunet-abd.c:1071 src/abd/gnunet-abd.c:1077
 msgid "Indicates that the collect/verify process is done via forward search."
 msgstr ""
 
-#: src/abd/gnunet-abd.c:1085
+#: src/abd/gnunet-abd.c:1090
 #, fuzzy
 msgid "GNUnet abd resolver tool"
 msgstr "Bản ghi lỗi GNUnet"
@@ -442,65 +442,65 @@ msgstr "Lỗi mở tập tin ghi sự kiện « %s »: %s\n"
 msgid "Failed to find %saddress for `%s'.\n"
 msgstr "Lỗi đóng kết đến cổng %s %d.\n"
 
-#: src/arm/gnunet-service-arm.c:933
+#: src/arm/gnunet-service-arm.c:951
 #, fuzzy, c-format
 msgid "Failed to start service `%s'\n"
 msgstr "Lỗi bắt đầu thu thập.\n"
 
-#: src/arm/gnunet-service-arm.c:944
+#: src/arm/gnunet-service-arm.c:962
 #, fuzzy, c-format
 msgid "Starting service `%s'\n"
 msgstr "Đang bắt đầu tài về « %s »\n"
 
-#: src/arm/gnunet-service-arm.c:1044
+#: src/arm/gnunet-service-arm.c:1062
 #, fuzzy, c-format
 msgid "Unable to create socket for service `%s': %s\n"
 msgstr "Không thể tạo tài khoản người dùng:"
 
-#: src/arm/gnunet-service-arm.c:1075
+#: src/arm/gnunet-service-arm.c:1093
 #, c-format
 msgid "Unable to bind listening socket for service `%s' to address `%s': %s\n"
 msgstr ""
 
-#: src/arm/gnunet-service-arm.c:1106
+#: src/arm/gnunet-service-arm.c:1124
 #, c-format
 msgid "ARM now monitors connections to service `%s' at `%s'\n"
 msgstr ""
 
-#: src/arm/gnunet-service-arm.c:1254
+#: src/arm/gnunet-service-arm.c:1272
 #, fuzzy, c-format
 msgid "Preparing to stop `%s'\n"
 msgstr "Đang bắt đầu tài lên « %s ».\n"
 
-#: src/arm/gnunet-service-arm.c:1586
+#: src/arm/gnunet-service-arm.c:1604
 #, fuzzy, c-format
 msgid "Restarting service `%s'.\n"
 msgstr "Đang nạp và khởi động dùng « %s ».\n"
 
-#: src/arm/gnunet-service-arm.c:1737
+#: src/arm/gnunet-service-arm.c:1755
 msgid "exit"
 msgstr ""
 
-#: src/arm/gnunet-service-arm.c:1742
+#: src/arm/gnunet-service-arm.c:1760
 msgid "signal"
 msgstr ""
 
-#: src/arm/gnunet-service-arm.c:1747
+#: src/arm/gnunet-service-arm.c:1765
 #, fuzzy
 msgid "unknown"
 msgstr "Lỗi không rõ"
 
-#: src/arm/gnunet-service-arm.c:1753
+#: src/arm/gnunet-service-arm.c:1771
 #, fuzzy, c-format
 msgid "Service `%s' took %s to terminate\n"
 msgstr "Dịch vụ đã bị xoá.\n"
 
-#: src/arm/gnunet-service-arm.c:1780
+#: src/arm/gnunet-service-arm.c:1798
 #, c-format
 msgid "Service `%s' terminated normally, will restart at any time\n"
 msgstr ""
 
-#: src/arm/gnunet-service-arm.c:1797
+#: src/arm/gnunet-service-arm.c:1815
 #, c-format
 msgid "Service `%s' terminated with status %s/%d, will restart in %s\n"
 msgstr ""
@@ -838,7 +838,10 @@ msgstr ""
 
 #: src/consensus/gnunet-consensus-profiler.c:543
 #: src/set/gnunet-set-profiler.c:451 src/set/gnunet-set-profiler.c:457
-#: src/set/gnunet-set-profiler.c:480
+#: src/set/gnunet-set-profiler.c:480 src/seti/gnunet-seti-profiler.c:441
+#: src/seti/gnunet-seti-profiler.c:446 src/seti/gnunet-seti-profiler.c:451
+#: src/setu/gnunet-setu-profiler.c:442 src/setu/gnunet-setu-profiler.c:448
+#: src/setu/gnunet-setu-profiler.c:471
 #, fuzzy
 msgid "number of values"
 msgstr "số lần lặp lại"
@@ -853,7 +856,8 @@ msgid "delay until consensus starts"
 msgstr ""
 
 #: src/consensus/gnunet-consensus-profiler.c:563
-#: src/set/gnunet-set-profiler.c:498
+#: src/set/gnunet-set-profiler.c:498 src/seti/gnunet-seti-profiler.c:467
+#: src/setu/gnunet-setu-profiler.c:489
 msgid "write statistics to file"
 msgstr ""
 
@@ -1404,158 +1408,158 @@ msgstr "Lưu cấu hình ngay bây giờ không?"
 msgid "Core service of `%s' ready.\n"
 msgstr "Không gian tên « %s » có đánh giá %d.\n"
 
-#: src/core/gnunet-service-core_kx.c:625
+#: src/core/gnunet-service-core_kx.c:512
 msgid "# bytes encrypted"
 msgstr "# các byte đã mã hoá"
 
-#: src/core/gnunet-service-core_kx.c:683
+#: src/core/gnunet-service-core_kx.c:570
 msgid "# bytes decrypted"
 msgstr "# các byte đã giải mã"
 
-#: src/core/gnunet-service-core_kx.c:780
+#: src/core/gnunet-service-core_kx.c:667
 #, fuzzy
 msgid "# PAYLOAD dropped (out of order)"
 msgstr "# các byte loại bỏ bởi UDP (đi ra)"
 
-#: src/core/gnunet-service-core_kx.c:832
+#: src/core/gnunet-service-core_kx.c:719
 msgid "# key exchanges initiated"
 msgstr ""
 
-#: src/core/gnunet-service-core_kx.c:888
+#: src/core/gnunet-service-core_kx.c:775
 msgid "# key exchanges stopped"
 msgstr ""
 
-#: src/core/gnunet-service-core_kx.c:920
+#: src/core/gnunet-service-core_kx.c:807
 #, fuzzy
 msgid "# PING messages transmitted"
 msgstr "# các thông báo PING được tạo"
 
-#: src/core/gnunet-service-core_kx.c:979
+#: src/core/gnunet-service-core_kx.c:866
 msgid "# old ephemeral keys ignored"
 msgstr ""
 
-#: src/core/gnunet-service-core_kx.c:993
+#: src/core/gnunet-service-core_kx.c:880
 #, fuzzy
 msgid "# duplicate ephemeral keys ignored"
 msgstr "# các thông báo phát hiện dht được nhận"
 
-#: src/core/gnunet-service-core_kx.c:1028
+#: src/core/gnunet-service-core_kx.c:915
 #, fuzzy
 msgid "# EPHEMERAL_KEYs rejected (bad signature)"
 msgstr "# các thông báo được chắp liền"
 
-#: src/core/gnunet-service-core_kx.c:1046
+#: src/core/gnunet-service-core_kx.c:933
 #, c-format
 msgid ""
 "EPHEMERAL_KEY from peer `%s' rejected as its validity range does not match "
 "our system time (%llu not in [%llu,%llu]).\n"
 msgstr ""
 
-#: src/core/gnunet-service-core_kx.c:1053
+#: src/core/gnunet-service-core_kx.c:940
 #, fuzzy
 msgid "# EPHEMERAL_KEY messages rejected due to time"
 msgstr "# các thông báo được chắp liền"
 
-#: src/core/gnunet-service-core_kx.c:1071
+#: src/core/gnunet-service-core_kx.c:958
 #, fuzzy
 msgid "# valid ephemeral keys received"
 msgstr "# các thông báo phát hiện dht được nhận"
 
-#: src/core/gnunet-service-core_kx.c:1180
+#: src/core/gnunet-service-core_kx.c:1067
 #: src/transport/gnunet-service-transport_validation.c:1133
 #, fuzzy
 msgid "# PING messages received"
 msgstr "# các thông báo PING được tạo"
 
-#: src/core/gnunet-service-core_kx.c:1190
+#: src/core/gnunet-service-core_kx.c:1077
 #, fuzzy
 msgid "# PING messages dropped (out of order)"
 msgstr "# các yêu cầu lỗ hổng bị bỏ do trọng tải"
 
-#: src/core/gnunet-service-core_kx.c:1239
+#: src/core/gnunet-service-core_kx.c:1126
 #, fuzzy
 msgid "# PONG messages created"
 msgstr "# các thông báo PING được tạo"
 
-#: src/core/gnunet-service-core_kx.c:1264
+#: src/core/gnunet-service-core_kx.c:1151
 #, fuzzy
 msgid "# sessions terminated by timeout"
 msgstr "# các byte loại đi bởi TCP (đi ra)"
 
-#: src/core/gnunet-service-core_kx.c:1277
+#: src/core/gnunet-service-core_kx.c:1164
 #, fuzzy
 msgid "# keepalive messages sent"
 msgstr "# các thông báo PING nhập thô được gửi"
 
-#: src/core/gnunet-service-core_kx.c:1334
+#: src/core/gnunet-service-core_kx.c:1221
 #: src/transport/gnunet-service-transport_validation.c:1476
 #, fuzzy
 msgid "# PONG messages received"
 msgstr "# các thông báo PONG đã mật mã được nhận"
 
-#: src/core/gnunet-service-core_kx.c:1342
+#: src/core/gnunet-service-core_kx.c:1229
 #, fuzzy
 msgid "# PONG messages dropped (connection down)"
 msgstr "# các thông báo PONG đã mật mã được nhận"
 
-#: src/core/gnunet-service-core_kx.c:1350
+#: src/core/gnunet-service-core_kx.c:1237
 #, fuzzy
 msgid "# PONG messages dropped (out of order)"
 msgstr "# các yêu cầu lỗ hổng bị bỏ do trọng tải"
 
-#: src/core/gnunet-service-core_kx.c:1389
+#: src/core/gnunet-service-core_kx.c:1276
 #, fuzzy
 msgid "# PONG messages decrypted"
 msgstr "# các thông báo PING được tạo"
 
-#: src/core/gnunet-service-core_kx.c:1429
+#: src/core/gnunet-service-core_kx.c:1316
 #, fuzzy
 msgid "# session keys confirmed via PONG"
 msgstr "# Các quảng cáo đồng đẳng được xác nhận qua PONG"
 
-#: src/core/gnunet-service-core_kx.c:1441
+#: src/core/gnunet-service-core_kx.c:1328
 #, fuzzy
 msgid "# timeouts prevented via PONG"
 msgstr "# các byte đã nhận qua TCP"
 
-#: src/core/gnunet-service-core_kx.c:1450
+#: src/core/gnunet-service-core_kx.c:1337
 #, fuzzy
 msgid "# rekey operations confirmed via PONG"
 msgstr "# Các quảng cáo đồng đẳng được xác nhận qua PONG"
 
-#: src/core/gnunet-service-core_kx.c:1626
+#: src/core/gnunet-service-core_kx.c:1513
 #, fuzzy
 msgid "# DATA message dropped (out of order)"
 msgstr "# các byte loại bỏ bởi UDP (đi ra)"
 
-#: src/core/gnunet-service-core_kx.c:1637
+#: src/core/gnunet-service-core_kx.c:1524
 #, c-format
 msgid ""
 "Session to peer `%s' went down due to key expiration (should not happen)\n"
 msgstr ""
 
-#: src/core/gnunet-service-core_kx.c:1641
+#: src/core/gnunet-service-core_kx.c:1528
 #, fuzzy
 msgid "# sessions terminated by key expiration"
 msgstr "# các byte loại đi bởi TCP (đi ra)"
 
-#: src/core/gnunet-service-core_kx.c:1719
-#: src/core/gnunet-service-core_kx.c:1746
+#: src/core/gnunet-service-core_kx.c:1606
+#: src/core/gnunet-service-core_kx.c:1633
 #, fuzzy
 msgid "# bytes dropped (duplicates)"
 msgstr "# các byte loại bỏ bởi UDP (đi ra)"
 
-#: src/core/gnunet-service-core_kx.c:1732
+#: src/core/gnunet-service-core_kx.c:1619
 #, fuzzy
 msgid "# bytes dropped (out of sequence)"
 msgstr "# các byte loại bỏ bởi UDP (đi ra)"
 
-#: src/core/gnunet-service-core_kx.c:1777
+#: src/core/gnunet-service-core_kx.c:1664
 #, fuzzy
 msgid "# bytes dropped (ancient message)"
 msgstr "# các byte loại bỏ bởi UDP (đi ra)"
 
-#: src/core/gnunet-service-core_kx.c:1786
+#: src/core/gnunet-service-core_kx.c:1673
 #, fuzzy
 msgid "# bytes of payload decrypted"
 msgstr "# các byte đã giải mã"
@@ -3196,18 +3200,18 @@ msgstr "Có dấu nháy kép thừa hay thiếu.\n"
 msgid "Failed to load state: %s\n"
 msgstr "Lỗi bắt đầu thu thập.\n"
 
-#: src/fs/gnunet-auto-share.c:286 src/fs/gnunet-auto-share.c:295
-#: src/fs/gnunet-auto-share.c:303
+#: src/fs/gnunet-auto-share.c:287 src/fs/gnunet-auto-share.c:296
+#: src/fs/gnunet-auto-share.c:304
 #, fuzzy, c-format
 msgid "Failed to save state to file %s\n"
 msgstr "Lỗi đọc danh sách bạn bè từ « %s »\n"
 
-#: src/fs/gnunet-auto-share.c:400
+#: src/fs/gnunet-auto-share.c:401
 #, c-format
 msgid "Publication of `%s' done\n"
 msgstr ""
 
-#: src/fs/gnunet-auto-share.c:479
+#: src/fs/gnunet-auto-share.c:480
 #, fuzzy, c-format
 msgid "Publishing `%s'\n"
 msgstr "Gặp lỗi khi tải lên tập tin: %s\n"
@@ -4067,40 +4071,40 @@ msgstr ""
 msgid "GNUnet HTTP server to create business cards"
 msgstr ""
 
-#: src/gns/gnunet-dns2gns.c:239
+#: src/gns/gnunet-dns2gns.c:241
 #, fuzzy
 msgid "Failed to pack DNS response into UDP packet!\n"
 msgstr "Lỗi mở tập tin ghi sự kiện « %s »: %s\n"
 
-#: src/gns/gnunet-dns2gns.c:442
+#: src/gns/gnunet-dns2gns.c:444
 #, c-format
 msgid "Cannot parse DNS request from %s\n"
 msgstr ""
 
-#: src/gns/gnunet-dns2gns.c:458
+#: src/gns/gnunet-dns2gns.c:460
 #, fuzzy, c-format
 msgid "Received malformed DNS request from %s\n"
 msgstr "Nhận yêu cầu định tuyến\n"
 
-#: src/gns/gnunet-dns2gns.c:466
+#: src/gns/gnunet-dns2gns.c:468
 #, fuzzy, c-format
 msgid "Received unsupported DNS request from %s\n"
 msgstr "Nhận yêu cầu định tuyến\n"
 
-#: src/gns/gnunet-dns2gns.c:627
+#: src/gns/gnunet-dns2gns.c:629
 #, fuzzy
 msgid "No DNS server specified!\n"
 msgstr "Chưa ghi rõ từ khoá.\n"
 
-#: src/gns/gnunet-dns2gns.c:776
+#: src/gns/gnunet-dns2gns.c:778
 msgid "IP of recursive DNS resolver to use (required)"
 msgstr ""
 
-#: src/gns/gnunet-dns2gns.c:782
+#: src/gns/gnunet-dns2gns.c:784
 msgid "UDP port to listen on for inbound DNS requests; default: 2853"
 msgstr ""
 
-#: src/gns/gnunet-dns2gns.c:799
+#: src/gns/gnunet-dns2gns.c:801
 msgid "GNUnet DNS-to-GNS proxy (a DNS server)"
 msgstr ""
 
@@ -4241,7 +4245,7 @@ msgstr "Không thể lưu tập tin cấu hình « %s »:"
 msgid "Failed to start HTTPS server for `%s'\n"
 msgstr "Lỗi bắt đầu thu thập.\n"
 
-#: src/gns/gnunet-gns-proxy.c:2922 src/rest/gnunet-rest-server.c:713
+#: src/gns/gnunet-gns-proxy.c:2922 src/rest/gnunet-rest-server.c:917
 #, fuzzy
 msgid "Failed to pass client to MHD\n"
 msgstr "Lỗi kết nối đến gnunetd.\n"
@@ -4398,7 +4402,7 @@ msgstr "Lỗi đọc danh sách bạn bè từ « %s »\n"
 msgid "Unable to parse BOX record string `%s'\n"
 msgstr "Lỗi đọc danh sách bạn bè từ « %s »\n"
 
-#: src/gns/plugin_rest_gns.c:445
+#: src/gns/plugin_rest_gns.c:447
 #, fuzzy
 msgid "Gns REST API initialized\n"
 msgstr "Lỗi sơ khởi lõi.\n"
@@ -4602,7 +4606,7 @@ msgid "# valid HELLOs downloaded from hostlist servers"
 msgstr "# các HELLO tải xuống qua HTTP"
 
 #: src/hostlist/gnunet-daemon-hostlist_client.c:677
-#: src/hostlist/gnunet-daemon-hostlist_client.c:1459
+#: src/hostlist/gnunet-daemon-hostlist_client.c:1460
 msgid "# advertised hostlist URIs"
 msgstr ""
 
@@ -4653,7 +4657,7 @@ msgid "# hostlist downloads initiated"
 msgstr ""
 
 #: src/hostlist/gnunet-daemon-hostlist_client.c:1144
-#: src/hostlist/gnunet-daemon-hostlist_client.c:1726
+#: src/hostlist/gnunet-daemon-hostlist_client.c:1728
 msgid "# milliseconds between hostlist downloads"
 msgstr ""
 
@@ -4683,52 +4687,52 @@ msgstr "Khoá phiên chạy từ đồng đẳng « %s » không thể được
 msgid "Could not open file `%s' for reading to load hostlists: %s\n"
 msgstr "Lỗi mở tập tin theo dõi « %s »: %s\n"
 
-#: src/hostlist/gnunet-daemon-hostlist_client.c:1452
+#: src/hostlist/gnunet-daemon-hostlist_client.c:1453
 #, c-format
 msgid "%u hostlist URIs loaded from file\n"
 msgstr ""
 
-#: src/hostlist/gnunet-daemon-hostlist_client.c:1455
+#: src/hostlist/gnunet-daemon-hostlist_client.c:1456
 #, fuzzy
 msgid "# hostlist URIs read from file"
 msgstr "# các byte danh sách máy được trả về"
 
-#: src/hostlist/gnunet-daemon-hostlist_client.c:1506
+#: src/hostlist/gnunet-daemon-hostlist_client.c:1507
 #, fuzzy, c-format
 msgid "Could not open file `%s' for writing to save hostlists: %s\n"
 msgstr "Lỗi mở tập tin theo dõi « %s »: %s\n"
 
-#: src/hostlist/gnunet-daemon-hostlist_client.c:1513
+#: src/hostlist/gnunet-daemon-hostlist_client.c:1514
 #, fuzzy, c-format
 msgid "Writing %u hostlist URIs to `%s'\n"
 msgstr "Đang thử tải danh sách các máy xuống « %s »\n"
 
-#: src/hostlist/gnunet-daemon-hostlist_client.c:1545
-#: src/hostlist/gnunet-daemon-hostlist_client.c:1564
+#: src/hostlist/gnunet-daemon-hostlist_client.c:1547
+#: src/hostlist/gnunet-daemon-hostlist_client.c:1566
 #, c-format
 msgid "Error writing hostlist URIs to file `%s'\n"
 msgstr ""
 
-#: src/hostlist/gnunet-daemon-hostlist_client.c:1558
+#: src/hostlist/gnunet-daemon-hostlist_client.c:1560
 #, fuzzy
 msgid "# hostlist URIs written to file"
 msgstr "# các byte danh sách máy được trả về"
 
-#: src/hostlist/gnunet-daemon-hostlist_client.c:1655
+#: src/hostlist/gnunet-daemon-hostlist_client.c:1657
 #: src/transport/plugin_transport_http_client.c:2301
 #, c-format
 msgid "Invalid proxy type: `%s', disabling proxy! Check configuration!\n"
 msgstr ""
 
-#: src/hostlist/gnunet-daemon-hostlist_client.c:1684
+#: src/hostlist/gnunet-daemon-hostlist_client.c:1686
 msgid "Learning is enabled on this peer\n"
 msgstr ""
 
-#: src/hostlist/gnunet-daemon-hostlist_client.c:1697
+#: src/hostlist/gnunet-daemon-hostlist_client.c:1699
 msgid "Learning is not enabled on this peer\n"
 msgstr ""
 
-#: src/hostlist/gnunet-daemon-hostlist_client.c:1711
+#: src/hostlist/gnunet-daemon-hostlist_client.c:1713
 #, c-format
 msgid ""
 "Since learning is not enabled on this peer, hostlist file `%s' was removed\n"
@@ -4860,48 +4864,48 @@ msgstr "Không thể tạo miền tên.\n"
 msgid "Failed to set default ego: %s\n"
 msgstr "Không thể tạo miền tên.\n"
 
-#: src/identity/gnunet-identity.c:445
+#: src/identity/gnunet-identity.c:446
 msgid "create ego NAME"
 msgstr ""
 
-#: src/identity/gnunet-identity.c:450
+#: src/identity/gnunet-identity.c:451
 msgid "delete ego NAME "
 msgstr ""
 
-#: src/identity/gnunet-identity.c:455
+#: src/identity/gnunet-identity.c:457
 msgid ""
 "set the private key for the identity to PRIVATE_KEY (use together with -C)"
 msgstr ""
 
-#: src/identity/gnunet-identity.c:459
+#: src/identity/gnunet-identity.c:461
 msgid "display all egos"
 msgstr ""
 
-#: src/identity/gnunet-identity.c:463
+#: src/identity/gnunet-identity.c:465
 msgid "reduce output"
 msgstr ""
 
-#: src/identity/gnunet-identity.c:470
+#: src/identity/gnunet-identity.c:472
 msgid ""
 "set default identity to NAME for a subsystem SUBSYSTEM (use together with -"
 "s) or restrict results to NAME (use together with -d)"
 msgstr ""
 
-#: src/identity/gnunet-identity.c:474
+#: src/identity/gnunet-identity.c:476
 msgid "run in monitor mode egos"
 msgstr ""
 
-#: src/identity/gnunet-identity.c:478
+#: src/identity/gnunet-identity.c:480
 #, fuzzy
 msgid "display private keys as well"
 msgstr "hiển thị giá trị tổng kiểm của tập tin"
 
-#: src/identity/gnunet-identity.c:485
+#: src/identity/gnunet-identity.c:487
 msgid ""
 "set default identity to EGO for a subsystem SUBSYSTEM (use together with -e)"
 msgstr ""
 
-#: src/identity/gnunet-identity.c:500
+#: src/identity/gnunet-identity.c:502
 msgid "Maintain egos"
 msgstr ""
 
@@ -4952,7 +4956,7 @@ msgstr "Không thể lưu tập tin cấu hình « %s »:"
 msgid "Failed to create directory `%s' for storing egos\n"
 msgstr "Lỗi đọc danh sách bạn bè từ « %s »\n"
 
-#: src/identity/plugin_rest_identity.c:1406
+#: src/identity/plugin_rest_identity.c:1384
 #, fuzzy
 msgid "Identity REST API initialized\n"
 msgstr "Lỗi sơ khởi lõi.\n"
@@ -5002,7 +5006,7 @@ msgstr "Đối số không hợp lệ cho « %s ».\n"
 msgid "You must specify a name\n"
 msgstr "Phải ghi rõ tên hiệu\n"
 
-#: src/namecache/gnunet-namecache.c:214 src/namestore/gnunet-namestore.c:1639
+#: src/namecache/gnunet-namecache.c:214 src/namestore/gnunet-namestore.c:1640
 msgid "name of the record to add/delete/display"
 msgstr ""
 
@@ -5011,7 +5015,7 @@ msgstr ""
 msgid "specifies the public key of the zone to look in"
 msgstr "xác định mức ưu tiên của nội dung"
 
-#: src/namecache/gnunet-namecache.c:233 src/namestore/gnunet-namestore.c:1700
+#: src/namecache/gnunet-namecache.c:233 src/namestore/gnunet-namestore.c:1701
 #, fuzzy
 msgid "GNUnet zone manipulation tool"
 msgstr "Cấu hình GNUnet"
@@ -5120,10 +5124,10 @@ msgstr "Lỗi mở tập tin ghi sự kiện « %s »: %s\n"
 msgid "No options given\n"
 msgstr "chưa đưa ra tên"
 
-#: src/namestore/gnunet-namestore.c:1014 src/namestore/gnunet-namestore.c:1065
-#: src/namestore/gnunet-namestore.c:1075 src/namestore/gnunet-namestore.c:1104
-#: src/namestore/gnunet-namestore.c:1125 src/namestore/gnunet-namestore.c:1152
-#: src/namestore/gnunet-namestore.c:1228
+#: src/namestore/gnunet-namestore.c:1014 src/namestore/gnunet-namestore.c:1066
+#: src/namestore/gnunet-namestore.c:1076 src/namestore/gnunet-namestore.c:1105
+#: src/namestore/gnunet-namestore.c:1126 src/namestore/gnunet-namestore.c:1153
+#: src/namestore/gnunet-namestore.c:1229
 #, fuzzy, c-format
 msgid "Missing option `%s' for operation `%s'\n"
 msgstr "Giá trị cấu hình « %s » cho « %s » trong phần « %s » nên là con số\n"
@@ -5137,53 +5141,53 @@ msgstr ""
 msgid "Invalid nick `%s'\n"
 msgstr "Dữ liệu nhập không hợp lệ.\n"
 
-#: src/namestore/gnunet-namestore.c:1067 src/namestore/gnunet-namestore.c:1077
-#: src/namestore/gnunet-namestore.c:1106 src/namestore/gnunet-namestore.c:1127
-#: src/namestore/gnunet-namestore.c:1230
+#: src/namestore/gnunet-namestore.c:1068 src/namestore/gnunet-namestore.c:1078
+#: src/namestore/gnunet-namestore.c:1107 src/namestore/gnunet-namestore.c:1128
+#: src/namestore/gnunet-namestore.c:1231
 msgid "add"
 msgstr ""
 
-#: src/namestore/gnunet-namestore.c:1085
+#: src/namestore/gnunet-namestore.c:1086
 #, fuzzy, c-format
 msgid "Unsupported type `%s'\n"
 msgstr "Lệnh không được hỗ trợ « %s ». Đang hủy bỏ.\n"
 
-#: src/namestore/gnunet-namestore.c:1095
+#: src/namestore/gnunet-namestore.c:1096
 #, c-format
 msgid "For DNS record types `SRV', `TLSA' and `OPENPGPKEY'"
 msgstr ""
 
-#: src/namestore/gnunet-namestore.c:1115
+#: src/namestore/gnunet-namestore.c:1116
 #, c-format
 msgid "Value `%s' invalid for record type `%s'\n"
 msgstr ""
 
-#: src/namestore/gnunet-namestore.c:1134 src/namestore/gnunet-namestore.c:1237
+#: src/namestore/gnunet-namestore.c:1135 src/namestore/gnunet-namestore.c:1238
 #, fuzzy, c-format
 msgid "Invalid time format `%s'\n"
 msgstr "Địa chỉ IP định dạng sai: %s\n"
 
-#: src/namestore/gnunet-namestore.c:1154
+#: src/namestore/gnunet-namestore.c:1155
 msgid "del"
 msgstr ""
 
-#: src/namestore/gnunet-namestore.c:1197
+#: src/namestore/gnunet-namestore.c:1198
 #, fuzzy, c-format
 msgid "Invalid public key for reverse lookup `%s'\n"
 msgstr "Đối số không hợp lệ cho « %s ».\n"
 
-#: src/namestore/gnunet-namestore.c:1220
+#: src/namestore/gnunet-namestore.c:1221
 #: src/peerinfo-tool/gnunet-peerinfo.c:736
 #, fuzzy, c-format
 msgid "Invalid URI `%s'\n"
 msgstr "Dữ liệu nhập không hợp lệ.\n"
 
-#: src/namestore/gnunet-namestore.c:1290
+#: src/namestore/gnunet-namestore.c:1291
 #, c-format
 msgid "Label `%s' contains `.' which is not allowed\n"
 msgstr ""
 
-#: src/namestore/gnunet-namestore.c:1340
+#: src/namestore/gnunet-namestore.c:1341
 #, c-format
 msgid ""
 "No default identity configured for `namestore' subsystem\n"
@@ -5191,102 +5195,102 @@ msgid ""
 "Run gnunet-identity -d to get a list of choices for $NAME\n"
 msgstr ""
 
-#: src/namestore/gnunet-namestore.c:1405
+#: src/namestore/gnunet-namestore.c:1406
 #, c-format
 msgid "Superfluous command line arguments (starting with `%s') ignored\n"
 msgstr ""
 
-#: src/namestore/gnunet-namestore.c:1434
+#: src/namestore/gnunet-namestore.c:1435
 #, fuzzy, c-format
 msgid "Cannot connect to identity service\n"
 msgstr "Không thể kết nối tới %s:%u: %s\n"
 
-#: src/namestore/gnunet-namestore.c:1481
+#: src/namestore/gnunet-namestore.c:1482
 msgid "Empty record line argument is not allowed.\n"
 msgstr ""
 
-#: src/namestore/gnunet-namestore.c:1493
+#: src/namestore/gnunet-namestore.c:1494
 #, c-format
 msgid "Invalid expiration time `%s' (must be without unit)\n"
 msgstr ""
 
-#: src/namestore/gnunet-namestore.c:1505 src/namestore/gnunet-namestore.c:1521
-#: src/namestore/gnunet-namestore.c:1538
+#: src/namestore/gnunet-namestore.c:1506 src/namestore/gnunet-namestore.c:1522
+#: src/namestore/gnunet-namestore.c:1539
 #, fuzzy, c-format
 msgid "Missing entries in record line `%s'.\n"
 msgstr "Không thể nạp phần bổ sung truyền tải « %s »\n"
 
-#: src/namestore/gnunet-namestore.c:1513
+#: src/namestore/gnunet-namestore.c:1514
 #, fuzzy, c-format
 msgid "Unknown record type `%s'\n"
 msgstr "Không rõ câu lệnh « %s ».\n"
 
-#: src/namestore/gnunet-namestore.c:1551
+#: src/namestore/gnunet-namestore.c:1552
 #, fuzzy, c-format
 msgid "Invalid record data for type %s: `%s'.\n"
 msgstr "Địa chỉ IP định dạng sai: %s\n"
 
-#: src/namestore/gnunet-namestore.c:1608
+#: src/namestore/gnunet-namestore.c:1609
 msgid "add record"
 msgstr ""
 
-#: src/namestore/gnunet-namestore.c:1611
+#: src/namestore/gnunet-namestore.c:1612
 msgid "delete record"
 msgstr ""
 
-#: src/namestore/gnunet-namestore.c:1615
+#: src/namestore/gnunet-namestore.c:1616
 msgid "display records"
 msgstr ""
 
-#: src/namestore/gnunet-namestore.c:1622
+#: src/namestore/gnunet-namestore.c:1623
 msgid ""
 "expiration time for record to use (for adding only), \"never\" is possible"
 msgstr ""
 
-#: src/namestore/gnunet-namestore.c:1628
+#: src/namestore/gnunet-namestore.c:1629
 #, fuzzy
 msgid "set the desired nick name for the zone"
 msgstr "In ra thông tin về các đồng đẳng GNUnet."
 
-#: src/namestore/gnunet-namestore.c:1633
+#: src/namestore/gnunet-namestore.c:1634
 #, fuzzy
 msgid "monitor changes in the namestore"
 msgstr "Không kết nối được đến trình nền gnunetd."
 
-#: src/namestore/gnunet-namestore.c:1645
+#: src/namestore/gnunet-namestore.c:1646
 #, fuzzy
 msgid "determine our name for the given PKEY"
 msgstr "In ra thông tin về các đồng đẳng GNUnet."
 
-#: src/namestore/gnunet-namestore.c:1652
+#: src/namestore/gnunet-namestore.c:1653
 msgid ""
 "set record set to values given by (possibly multiple) RECORDLINES; can be "
 "specified multiple times"
 msgstr ""
 
-#: src/namestore/gnunet-namestore.c:1658
+#: src/namestore/gnunet-namestore.c:1659
 msgid "type of the record to add/delete/display"
 msgstr ""
 
-#: src/namestore/gnunet-namestore.c:1663
+#: src/namestore/gnunet-namestore.c:1664
 msgid "URI to import into our zone"
 msgstr ""
 
-#: src/namestore/gnunet-namestore.c:1669
+#: src/namestore/gnunet-namestore.c:1670
 msgid "value of the record to add/delete"
 msgstr ""
 
-#: src/namestore/gnunet-namestore.c:1673
+#: src/namestore/gnunet-namestore.c:1674
 msgid "create or list public record"
 msgstr ""
 
-#: src/namestore/gnunet-namestore.c:1679
+#: src/namestore/gnunet-namestore.c:1680
 msgid ""
 "create shadow record (only valid if all other records of the same type have "
 "expired"
 msgstr ""
 
-#: src/namestore/gnunet-namestore.c:1685
+#: src/namestore/gnunet-namestore.c:1686
 msgid "name of the ego controlling the zone"
 msgstr ""
 
@@ -5386,7 +5390,7 @@ msgstr ""
 msgid "Flat file database running\n"
 msgstr "kho dữ liệu sqlite"
 
-#: src/namestore/plugin_rest_namestore.c:1093
+#: src/namestore/plugin_rest_namestore.c:1103
 #, fuzzy
 msgid "Namestore REST API initialized\n"
 msgstr "Lỗi sơ khởi lõi.\n"
@@ -5660,7 +5664,7 @@ msgstr ""
 msgid "gnunet-helper-nat-server generated malformed address `%s'\n"
 msgstr ""
 
-#: src/nat/gnunet-service-nat_helper.c:250
+#: src/nat/gnunet-service-nat_helper.c:249
 #, fuzzy, c-format
 msgid "Failed to start %s\n"
 msgstr "Lỗi bắt đầu thu thập.\n"
@@ -5669,7 +5673,7 @@ msgstr "Lỗi bắt đầu thu thập.\n"
 msgid "`external-ip' command not found\n"
 msgstr ""
 
-#: src/nat/gnunet-service-nat_mini.c:608
+#: src/nat/gnunet-service-nat_mini.c:607
 msgid "`upnpc' command not found\n"
 msgstr ""
 
@@ -5704,8 +5708,8 @@ msgstr ""
 msgid "Measure quality and performance of the NSE service."
 msgstr "Không thể truy cập đến dịch vụ"
 
-#: src/nse/gnunet-service-nse.c:1438
-#: src/revocation/gnunet-service-revocation.c:842 src/util/gnunet-scrypt.c:250
+#: src/nse/gnunet-service-nse.c:1443
+#: src/revocation/gnunet-service-revocation.c:834 src/util/gnunet-scrypt.c:257
 #, fuzzy
 msgid "Value is too large.\n"
 msgstr "Giá trị không nằm trong phạm vi được phép."
@@ -5780,7 +5784,7 @@ msgid "\tExpires: %s \t %s\n"
 msgstr ""
 
 #: src/peerinfo-tool/gnunet-peerinfo.c:292
-#: src/peerinfo-tool/plugin_rest_peerinfo.c:501
+#: src/peerinfo-tool/plugin_rest_peerinfo.c:523
 #, fuzzy, c-format
 msgid "Failure: Cannot convert address to string for peer `%s'\n"
 msgstr "Lỗi đóng kết đến cổng %s %d.\n"
@@ -5861,7 +5865,7 @@ msgstr "Đang nạp các truyền tải « %s »\n"
 msgid "Failed to load transport plugin for `%s'\n"
 msgstr "Không thể nạp phần bổ sung truyền tải « %s »\n"
 
-#: src/peerinfo-tool/plugin_rest_peerinfo.c:797
+#: src/peerinfo-tool/plugin_rest_peerinfo.c:809
 #, fuzzy
 msgid "Peerinfo REST API initialized\n"
 msgstr "Lỗi sơ khởi lõi.\n"
@@ -5976,97 +5980,101 @@ msgstr "Lỗi sơ khởi dịch vụ « %s ».\n"
 msgid "Daemon to run to perform IP protocol translation to GNUnet"
 msgstr ""
 
-#: src/reclaim/gnunet-reclaim.c:799
+#: src/reclaim/gnunet-reclaim.c:801
 #, fuzzy, c-format
 msgid "Ego is required\n"
 msgstr "Bị từ chối đặt tùy chọn « %s » trong phần « %s » thành « %s ».\n"
 
-#: src/reclaim/gnunet-reclaim.c:806
+#: src/reclaim/gnunet-reclaim.c:808
 #, c-format
 msgid "Attribute value missing!\n"
 msgstr ""
 
-#: src/reclaim/gnunet-reclaim.c:813
+#: src/reclaim/gnunet-reclaim.c:815
 #, fuzzy, c-format
 msgid "Requesting party key is required!\n"
 msgstr "đặt tên hiệu cần dùng (cần thiết)"
 
-#: src/reclaim/gnunet-reclaim.c:831
+#: src/reclaim/gnunet-reclaim.c:833
 msgid "Add an attribute NAME"
 msgstr ""
 
-#: src/reclaim/gnunet-reclaim.c:836
+#: src/reclaim/gnunet-reclaim.c:838
 msgid "Delete the attribute with ID"
 msgstr ""
 
-#: src/reclaim/gnunet-reclaim.c:841
+#: src/reclaim/gnunet-reclaim.c:843
 msgid "The attribute VALUE"
 msgstr ""
 
-#: src/reclaim/gnunet-reclaim.c:846
+#: src/reclaim/gnunet-reclaim.c:848
 #, fuzzy
 msgid "The EGO to use"
 msgstr "kích cỡ tin nhắn"
 
-#: src/reclaim/gnunet-reclaim.c:852
+#: src/reclaim/gnunet-reclaim.c:854
 msgid "Specify the relying party for issue"
 msgstr ""
 
-#: src/reclaim/gnunet-reclaim.c:856
+#: src/reclaim/gnunet-reclaim.c:858
 msgid "List attributes for EGO"
 msgstr ""
 
-#: src/reclaim/gnunet-reclaim.c:860
-msgid "List attestations for EGO"
+#: src/reclaim/gnunet-reclaim.c:862
+msgid "List credentials for EGO"
 msgstr ""
 
-#: src/reclaim/gnunet-reclaim.c:866
-msgid "Attestation to use for attribute"
+#: src/reclaim/gnunet-reclaim.c:868
+msgid "Credential to use for attribute"
 msgstr ""
 
-#: src/reclaim/gnunet-reclaim.c:871
-msgid "Attestation name"
+#: src/reclaim/gnunet-reclaim.c:873
+msgid "Credential name"
 msgstr ""
 
-#: src/reclaim/gnunet-reclaim.c:877
+#: src/reclaim/gnunet-reclaim.c:879
 msgid "Issue a ticket for a set of attributes separated by comma"
 msgstr ""
 
-#: src/reclaim/gnunet-reclaim.c:882
+#: src/reclaim/gnunet-reclaim.c:884
 msgid "Consume a ticket"
 msgstr ""
 
-#: src/reclaim/gnunet-reclaim.c:887
+#: src/reclaim/gnunet-reclaim.c:889
 msgid "Revoke a ticket"
 msgstr ""
 
-#: src/reclaim/gnunet-reclaim.c:892
+#: src/reclaim/gnunet-reclaim.c:894
 msgid "Type of attribute"
 msgstr ""
 
-#: src/reclaim/gnunet-reclaim.c:896
+#: src/reclaim/gnunet-reclaim.c:899
+msgid "Type of credential"
+msgstr ""
+
+#: src/reclaim/gnunet-reclaim.c:903
 msgid "List tickets of ego"
 msgstr ""
 
-#: src/reclaim/gnunet-reclaim.c:902
+#: src/reclaim/gnunet-reclaim.c:909
 msgid "Expiration interval of the attribute"
 msgstr ""
 
-#: src/reclaim/gnunet-reclaim.c:910
+#: src/reclaim/gnunet-reclaim.c:917
 msgid "re:claimID command line tool"
 msgstr ""
 
-#: src/reclaim/plugin_rest_openid_connect.c:2481
+#: src/reclaim/plugin_rest_openid_connect.c:2618
 #, fuzzy
 msgid "OpenID Connect REST API initialized\n"
 msgstr "Lỗi sơ khởi lõi.\n"
 
-#: src/reclaim/plugin_rest_reclaim.c:1476
+#: src/reclaim/plugin_rest_reclaim.c:1502
 #, fuzzy
 msgid "Identity Provider REST API initialized\n"
 msgstr "Lỗi sơ khởi lõi.\n"
 
-#: src/reclaim/reclaim_api.c:540
+#: src/reclaim/reclaim_api.c:545
 #, fuzzy
 msgid "failed to store record\n"
 msgstr "Lỗi bắt đầu thu thập.\n"
@@ -6160,17 +6168,17 @@ msgstr "« %s » không phải là một tập tin.\n"
 msgid "Search string `%s' is too long!\n"
 msgstr "« %s » không phải là một tập tin.\n"
 
-#: src/rest/gnunet-rest-server.c:1051
+#: src/rest/gnunet-rest-server.c:1266
 #, fuzzy
 msgid "GNUnet REST server"
 msgstr "Bản ghi lỗi GNUnet"
 
-#: src/rest/plugin_rest_config.c:402
+#: src/rest/plugin_rest_config.c:427
 #, fuzzy
 msgid "CONFIG REST API initialized\n"
 msgstr "Lỗi sơ khởi lõi.\n"
 
-#: src/rest/plugin_rest_copying.c:209
+#: src/rest/plugin_rest_copying.c:211
 #, fuzzy
 msgid "COPYING REST API initialized\n"
 msgstr "Lỗi sơ khởi lõi.\n"
@@ -6307,26 +6315,26 @@ msgstr "# các yêu cầu danh sách máy được nhận"
 msgid "# revocation messages received via set union"
 msgstr "# các thông báo PONG đã mật mã được nhận"
 
-#: src/revocation/gnunet-service-revocation.c:470
+#: src/revocation/gnunet-service-revocation.c:469
 #, c-format
 msgid "Error computing revocation set union with %s\n"
 msgstr ""
 
-#: src/revocation/gnunet-service-revocation.c:474
+#: src/revocation/gnunet-service-revocation.c:473
 #, fuzzy
 msgid "# revocation set unions failed"
 msgstr "# các khoá phiên chạy được chấp nhận"
 
-#: src/revocation/gnunet-service-revocation.c:486
+#: src/revocation/gnunet-service-revocation.c:481
 #, fuzzy
 msgid "# revocation set unions completed"
 msgstr "# các sự truyền PONG bị lỗi"
 
-#: src/revocation/gnunet-service-revocation.c:526
+#: src/revocation/gnunet-service-revocation.c:519
 msgid "SET service crashed, terminating revocation service\n"
 msgstr ""
 
-#: src/revocation/gnunet-service-revocation.c:881
+#: src/revocation/gnunet-service-revocation.c:871
 #, fuzzy
 msgid "Could not open revocation database file!"
 msgstr "« %s »: Không thể kết nối.\n"
@@ -6417,10 +6425,10 @@ msgstr ""
 msgid "Calculate the Vectorproduct with a GNUnet peer."
 msgstr ""
 
-#: src/scalarproduct/gnunet-service-scalarproduct_alice.c:1363
-#: src/scalarproduct/gnunet-service-scalarproduct_bob.c:1366
-#: src/scalarproduct/gnunet-service-scalarproduct-ecc_alice.c:1127
-#: src/scalarproduct/gnunet-service-scalarproduct-ecc_bob.c:1073
+#: src/scalarproduct/gnunet-service-scalarproduct_alice.c:1358
+#: src/scalarproduct/gnunet-service-scalarproduct_bob.c:1355
+#: src/scalarproduct/gnunet-service-scalarproduct-ecc_alice.c:1118
+#: src/scalarproduct/gnunet-service-scalarproduct-ecc_bob.c:1063
 #, fuzzy
 msgid "Connect to CADET failed\n"
 msgstr " Không kết nối được (lỗi ?)\n"
@@ -6445,53 +6453,64 @@ msgstr ""
 msgid "also profile decryption"
 msgstr ""
 
-#: src/set/gnunet-service-set.c:1916
+#: src/set/gnunet-service-set.c:1916 src/seti/gnunet-service-seti.c:2467
+#: src/setu/gnunet-service-setu.c:3635
 #, fuzzy
 msgid "Could not connect to CADET service\n"
 msgstr "Không thể kết nối tới %s:%u: %s\n"
 
 #: src/set/gnunet-set-ibf-profiler.c:268
+#: src/setu/gnunet-setu-ibf-profiler.c:268
 #, fuzzy
 msgid "number of element in set A-B"
 msgstr "số lần lặp lại"
 
 #: src/set/gnunet-set-ibf-profiler.c:274
+#: src/setu/gnunet-setu-ibf-profiler.c:274
 #, fuzzy
 msgid "number of element in set B-A"
 msgstr "số lần lặp lại"
 
 #: src/set/gnunet-set-ibf-profiler.c:281
+#: src/setu/gnunet-setu-ibf-profiler.c:281
 msgid "number of common elements in A and B"
 msgstr ""
 
 #: src/set/gnunet-set-ibf-profiler.c:287
+#: src/setu/gnunet-setu-ibf-profiler.c:287
 msgid "hash num"
 msgstr ""
 
 #: src/set/gnunet-set-ibf-profiler.c:293
+#: src/setu/gnunet-setu-ibf-profiler.c:293
 msgid "ibf size"
 msgstr ""
 
-#: src/set/gnunet-set-profiler.c:462
+#: src/set/gnunet-set-profiler.c:462 src/setu/gnunet-setu-profiler.c:453
 msgid "use byzantine mode"
 msgstr ""
 
-#: src/set/gnunet-set-profiler.c:468
+#: src/set/gnunet-set-profiler.c:468 src/setu/gnunet-setu-profiler.c:459
 msgid "force sending full set"
 msgstr ""
 
-#: src/set/gnunet-set-profiler.c:474
+#: src/set/gnunet-set-profiler.c:474 src/setu/gnunet-setu-profiler.c:465
 msgid "number delta operation"
 msgstr ""
 
-#: src/set/gnunet-set-profiler.c:486
+#: src/set/gnunet-set-profiler.c:486 src/setu/gnunet-setu-profiler.c:477
 msgid "operation to execute"
 msgstr ""
 
-#: src/set/gnunet-set-profiler.c:492
+#: src/set/gnunet-set-profiler.c:492 src/seti/gnunet-seti-profiler.c:462
+#: src/setu/gnunet-setu-profiler.c:483
 msgid "element size"
 msgstr ""
 
+#: src/seti/gnunet-seti-profiler.c:457
+msgid "return intersection instead of delta"
+msgstr ""
+
 #: src/sq/sq.c:54
 #, c-format
 msgid "Failure to bind %u-th SQL parameter\n"
@@ -6506,12 +6525,12 @@ msgstr ""
 msgid "Failed to reset sqlite statement with error: %s\n"
 msgstr "« %s » không giải quyết được phương pháp « %s », với lỗi: %s\n"
 
-#: src/statistics/gnunet-service-statistics.c:318
+#: src/statistics/gnunet-service-statistics.c:319
 #, fuzzy, c-format
 msgid "Wrote %llu bytes of statistics to `%s'\n"
 msgstr "Đã tải %llu byte xuống « %s ».\n"
 
-#: src/statistics/gnunet-service-statistics.c:983
+#: src/statistics/gnunet-service-statistics.c:984
 #, fuzzy, c-format
 msgid "Loading %llu bytes of statistics from `%s'\n"
 msgstr "Đã tải %llu byte xuống « %s ».\n"
@@ -6694,7 +6713,7 @@ msgid ""
 msgstr ""
 
 #: src/testbed/gnunet-daemon-testbed-underlay.c:234 src/testing/list-keys.c:47
-#: src/testing/testing.c:284 src/util/gnunet-ecc.c:318
+#: src/testing/testing.c:278 src/util/gnunet-ecc.c:318
 #, c-format
 msgid "Incorrect hostkey file format: %s\n"
 msgstr ""
@@ -6951,58 +6970,58 @@ msgstr ""
 msgid "list COUNT number of keys"
 msgstr ""
 
-#: src/testing/testing.c:267
+#: src/testing/testing.c:261
 #, c-format
 msgid "Hostkeys file not found: %s\n"
 msgstr ""
 
-#: src/testing/testing.c:721
+#: src/testing/testing.c:714
 #, fuzzy, c-format
 msgid "Key number %u does not exist\n"
 msgstr "đặt số trình nền cần khởi chạy"
 
-#: src/testing/testing.c:1195
+#: src/testing/testing.c:1188
 #, c-format
 msgid ""
 "You attempted to create a testbed with more than %u hosts.  Please "
 "precompute more hostkeys first.\n"
 msgstr ""
 
-#: src/testing/testing.c:1204
+#: src/testing/testing.c:1197
 #, fuzzy, c-format
 msgid "Failed to initialize hostkey for peer %u\n"
 msgstr "Lỗi sơ khởi dịch vụ « %s ».\n"
 
-#: src/testing/testing.c:1214
+#: src/testing/testing.c:1207
 msgid "PRIVATE_KEY option in PEER section missing in configuration\n"
 msgstr ""
 
-#: src/testing/testing.c:1227
+#: src/testing/testing.c:1220
 #, fuzzy
 msgid "Failed to create configuration for peer (not enough free ports?)\n"
 msgstr "Không thể truy cập đến thông tin về không gian tên.\n"
 
-#: src/testing/testing.c:1243
+#: src/testing/testing.c:1236
 #, fuzzy, c-format
 msgid "Cannot open hostkey file `%s': %s\n"
 msgstr "Không thể đọc danh sách bạn bè « %s »\n"
 
-#: src/testing/testing.c:1257
+#: src/testing/testing.c:1250
 #, fuzzy, c-format
 msgid "Failed to write hostkey file for peer %u: %s\n"
 msgstr "Lỗi tạo thư mục tạm thời."
 
-#: src/testing/testing.c:1285
+#: src/testing/testing.c:1278
 #, fuzzy, c-format
 msgid "Failed to write configuration file `%s' for peer %u: %s\n"
 msgstr "Không thể lưu tập tin cấu hình « %s »:"
 
-#: src/testing/testing.c:1392
+#: src/testing/testing.c:1384
 #, fuzzy, c-format
 msgid "Failed to start `%s': %s\n"
 msgstr "Lỗi chạy %s: %s %d\n"
 
-#: src/testing/testing.c:1691
+#: src/testing/testing.c:1683
 #, fuzzy, c-format
 msgid "Failed to load configuration from %s\n"
 msgstr "Không thể lưu tập tin cấu hình « %s »:"
@@ -7087,40 +7106,40 @@ msgstr "# các thông báo PONG đã mật mã được nhận"
 msgid "GNUnet topology control"
 msgstr ""
 
-#: src/transport/gnunet-communicator-tcp.c:2458
-#: src/transport/gnunet-communicator-udp.c:2825
-#: src/transport/gnunet-service-tng.c:10027
+#: src/transport/gnunet-communicator-tcp.c:3189
+#: src/transport/gnunet-communicator-udp.c:2826
+#: src/transport/gnunet-service-tng.c:10014
 #: src/transport/gnunet-service-transport.c:2624
 #, fuzzy
 msgid "Transport service is lacking key configuration settings. Exiting.\n"
 msgstr "Lưu cấu hình ngay bây giờ không?"
 
-#: src/transport/gnunet-communicator-tcp.c:2754
+#: src/transport/gnunet-communicator-tcp.c:3494
 msgid "GNUnet TCP communicator"
 msgstr ""
 
-#: src/transport/gnunet-communicator-udp.c:2897
+#: src/transport/gnunet-communicator-udp.c:2898
 msgid "GNUnet UDP communicator"
 msgstr ""
 
-#: src/transport/gnunet-communicator-unix.c:788
+#: src/transport/gnunet-communicator-unix.c:789
 #, fuzzy
 msgid ""
 "Maximum number of UNIX connections exceeded, dropping incoming message\n"
 msgstr "tăng sổ tối đa các kết nối TCP/IP"
 
-#: src/transport/gnunet-communicator-unix.c:1015
+#: src/transport/gnunet-communicator-unix.c:1016
 #, fuzzy
 msgid "UNIX communicator is lacking key configuration settings. Exiting.\n"
 msgstr "Lưu cấu hình ngay bây giờ không?"
 
-#: src/transport/gnunet-communicator-unix.c:1060
+#: src/transport/gnunet-communicator-unix.c:1061
 #: src/transport/plugin_transport_unix.c:1383
 #, fuzzy, c-format
 msgid "Cannot create path to `%s'\n"
 msgstr "Không thể tạo miền tên.\n"
 
-#: src/transport/gnunet-communicator-unix.c:1138
+#: src/transport/gnunet-communicator-unix.c:1139
 msgid "GNUnet UNIX domain socket communicator"
 msgstr ""
 
@@ -8221,7 +8240,7 @@ msgid "do daemonize (detach from terminal)"
 msgstr ""
 
 #: src/transport/tcp_service_legacy.c:1397
-#: src/transport/transport-testing2.c:1061 src/util/service.c:2072
+#: src/transport/transport-testing2.c:1116 src/util/service.c:2072
 #: src/util/service.c:2084
 #, fuzzy, c-format
 msgid "Malformed configuration file `%s', exit ...\n"
@@ -8264,7 +8283,7 @@ msgstr ""
 msgid "Invalid handle type while reading `%s'"
 msgstr "Đối số không hợp lệ cho « %s ».\n"
 
-#: src/util/bio.c:335 src/util/bio.c:838
+#: src/util/bio.c:335 src/util/bio.c:839
 msgid "string length"
 msgstr ""
 
@@ -8283,7 +8302,7 @@ msgstr ""
 msgid "String `%s' longer than allowed (%u > %u)"
 msgstr ""
 
-#: src/util/bio.c:398 src/util/bio.c:863 src/util/bio.c:880
+#: src/util/bio.c:398 src/util/bio.c:864 src/util/bio.c:881
 msgid "metadata length"
 msgstr ""
 
@@ -8297,25 +8316,25 @@ msgstr ""
 msgid "Failed to deserialize metadata `%s'"
 msgstr "Lỗi lấy thông kê về truyền tải.\n"
 
-#: src/util/bio.c:667
+#: src/util/bio.c:668
 msgid "Unable to flush buffer to file"
 msgstr ""
 
-#: src/util/bio.c:729 src/util/bio.c:750
+#: src/util/bio.c:730 src/util/bio.c:751
 #, fuzzy, c-format
 msgid "Error while writing `%s' to file: %s"
 msgstr "Gặp lỗi khi tải xuống: %s\n"
 
-#: src/util/bio.c:731
+#: src/util/bio.c:732
 msgid "No associated file"
 msgstr ""
 
-#: src/util/bio.c:815
+#: src/util/bio.c:816
 #, fuzzy, c-format
 msgid "Invalid handle type while writing `%s'"
 msgstr "Địa chỉ IP định dạng sai: %s\n"
 
-#: src/util/bio.c:875
+#: src/util/bio.c:876
 #, fuzzy, c-format
 msgid "Failed to serialize metadata `%s'"
 msgstr "Lỗi lấy thông kê về truyền tải.\n"
@@ -8808,15 +8827,15 @@ msgstr ""
 msgid "No handler known for subsystem `%s'\n"
 msgstr ""
 
-#: src/util/gnunet-qr.c:358
+#: src/util/gnunet-qr.c:357
 msgid "use video-device DEVICE (default: /dev/video0"
 msgstr ""
 
-#: src/util/gnunet-qr.c:363
+#: src/util/gnunet-qr.c:362
 msgid "do not show preview windows"
 msgstr ""
 
-#: src/util/gnunet-qr.c:373
+#: src/util/gnunet-qr.c:372
 msgid "Scan a QR code using a video device and import the uri read"
 msgstr ""
 
@@ -8828,28 +8847,28 @@ msgstr ""
 msgid "Use build-in GNUnet stub resolver"
 msgstr ""
 
-#: src/util/gnunet-scrypt.c:222
+#: src/util/gnunet-scrypt.c:229
 #, c-format
 msgid "Loading hostkey from `%s' failed.\n"
 msgstr ""
 
-#: src/util/gnunet-scrypt.c:288
+#: src/util/gnunet-scrypt.c:295
 msgid "number of bits to require for the proof of work"
 msgstr ""
 
-#: src/util/gnunet-scrypt.c:294
+#: src/util/gnunet-scrypt.c:301
 msgid "file with private key, otherwise default is used"
 msgstr ""
 
-#: src/util/gnunet-scrypt.c:300
+#: src/util/gnunet-scrypt.c:307
 msgid "file with proof of work, otherwise default is used"
 msgstr ""
 
-#: src/util/gnunet-scrypt.c:306
+#: src/util/gnunet-scrypt.c:313
 msgid "time to wait between calculations"
 msgstr ""
 
-#: src/util/gnunet-scrypt.c:319
+#: src/util/gnunet-scrypt.c:326
 #, fuzzy
 msgid "Manipulate GNUnet proof of work files"
 msgstr "cập nhật một giá trị trong tập tin cấu hình"
@@ -8863,7 +8882,7 @@ msgstr ""
 msgid "No URI specified on command line\n"
 msgstr ""
 
-#: src/util/gnunet-uri.c:179
+#: src/util/gnunet-uri.c:178
 msgid "Perform default-actions for GNUnet URIs"
 msgstr ""
 
@@ -8877,7 +8896,7 @@ msgstr "Gặp lỗi khi tạo người dùng"
 msgid "Failed to parse inbound message from helper `%s'\n"
 msgstr "Lỗi đọc danh sách bạn bè từ « %s »\n"
 
-#: src/util/helper.c:600
+#: src/util/helper.c:602
 #, fuzzy, c-format
 msgid "Error writing to `%s': %s\n"
 msgstr "Gặp lỗi khi tạo người dùng"
@@ -9005,119 +9024,119 @@ msgstr ""
 msgid "Attempting to proxy service `%s' to invalid port %d or hostname.\n"
 msgstr ""
 
-#: src/util/strings.c:178
+#: src/util/strings.c:179
 msgid "b"
 msgstr "b"
 
-#: src/util/strings.c:502
+#: src/util/strings.c:503
 #, c-format
 msgid "Character sets requested were `%s'->`%s'\n"
 msgstr ""
 
-#: src/util/strings.c:636
+#: src/util/strings.c:637
 msgid "Failed to expand `$HOME': environment variable `HOME' not set"
 msgstr ""
 "Lỗi mở rộng biến môi trường « $HOME »: chưa đặt biến môi trường « HOME »"
 
-#: src/util/strings.c:705
+#: src/util/strings.c:706
 msgid "µs"
 msgstr ""
 
-#: src/util/strings.c:709
+#: src/util/strings.c:710
 msgid "forever"
 msgstr ""
 
-#: src/util/strings.c:711
+#: src/util/strings.c:712
 msgid "0 ms"
 msgstr ""
 
-#: src/util/strings.c:715
+#: src/util/strings.c:716
 msgid "ms"
 msgstr "mg"
 
-#: src/util/strings.c:719
+#: src/util/strings.c:720
 msgid "s"
 msgstr "g"
 
-#: src/util/strings.c:723
+#: src/util/strings.c:724
 msgid "m"
 msgstr "p"
 
-#: src/util/strings.c:727
+#: src/util/strings.c:728
 msgid "h"
 msgstr "g"
 
-#: src/util/strings.c:733
+#: src/util/strings.c:734
 #, fuzzy
 msgid "day"
 msgstr " ngày"
 
-#: src/util/strings.c:735
+#: src/util/strings.c:736
 #, fuzzy
 msgid "days"
 msgstr " ngày"
 
-#: src/util/strings.c:763
+#: src/util/strings.c:764
 msgid "end of time"
 msgstr ""
 
-#: src/util/strings.c:1239
+#: src/util/strings.c:1240
 msgid "IPv6 address did not start with `['\n"
 msgstr ""
 
-#: src/util/strings.c:1247
+#: src/util/strings.c:1248
 msgid "IPv6 address did contain ':' to separate port number\n"
 msgstr ""
 
-#: src/util/strings.c:1254
+#: src/util/strings.c:1255
 msgid "IPv6 address did contain ']' before ':' to separate port number\n"
 msgstr ""
 
-#: src/util/strings.c:1262
+#: src/util/strings.c:1263
 msgid "IPv6 address did contain a valid port number after the last ':'\n"
 msgstr ""
 
-#: src/util/strings.c:1271
+#: src/util/strings.c:1272
 #, fuzzy, c-format
 msgid "Invalid IPv6 address `%s': %s\n"
 msgstr "Mức ưu tiên tiến trình không hợp lê « %s ».\n"
 
-#: src/util/strings.c:1498 src/util/strings.c:1509
+#: src/util/strings.c:1499 src/util/strings.c:1510
 msgid "Port not in range\n"
 msgstr ""
 
-#: src/util/strings.c:1518
+#: src/util/strings.c:1519
 #, fuzzy, c-format
 msgid "Malformed port policy `%s'\n"
 msgstr "Lỗi bắt đầu thu thập.\n"
 
-#: src/util/strings.c:1601 src/util/strings.c:1630 src/util/strings.c:1677
-#: src/util/strings.c:1697
+#: src/util/strings.c:1602 src/util/strings.c:1631 src/util/strings.c:1678
+#: src/util/strings.c:1698
 #, c-format
 msgid "Invalid format for IP: `%s'\n"
 msgstr "Địa chỉ IP định dạng sai: %s\n"
 
-#: src/util/strings.c:1655
+#: src/util/strings.c:1656
 #, c-format
 msgid "Invalid network notation ('/%d' is not legal in IPv4 CIDR)."
 msgstr "Ký hiệu mạng sai (« /%d » không hợp lệ trong CIDR IPv4)."
 
-#: src/util/strings.c:1706
+#: src/util/strings.c:1707
 #, fuzzy, c-format
 msgid "Invalid format: `%s'\n"
 msgstr "Địa chỉ IP định dạng sai: %s\n"
 
-#: src/util/strings.c:1759
+#: src/util/strings.c:1760
 #, c-format
 msgid "Invalid network notation (does not end with ';': `%s')\n"
 msgstr "Ký hiệu mạng sai (không kết thúc với « ; »: « %s »)\n"
 
-#: src/util/strings.c:1809
+#: src/util/strings.c:1810
 #, fuzzy, c-format
 msgid "Wrong format `%s' for netmask\n"
 msgstr "Mặt nạ mạng có định dạng sai « %s »: %s\n"
 
-#: src/util/strings.c:1840
+#: src/util/strings.c:1841
 #, fuzzy, c-format
 msgid "Wrong format `%s' for network\n"
 msgstr "Mạng có định dạng sai « %s »: %s\n"
diff --git a/po/zh_CN.po b/po/zh_CN.po
index 8012ee2c04bd6b86d1da16a5b0e5c3b7fbd6f45c..dec62e27f7fefd3d5503fddf6c63236fb71e68c7 100644
--- a/po/zh_CN.po
+++ b/po/zh_CN.po
@@ -7,7 +7,7 @@ msgid ""
 msgstr ""
 "Project-Id-Version: gnunet-0.8.1\n"
 "Report-Msgid-Bugs-To: gnunet-developers@mail.gnu.org\n"
-"POT-Creation-Date: 2020-07-12 17:55+0200\n"
+"POT-Creation-Date: 2020-09-06 10:07+0200\n"
 "PO-Revision-Date: 2011-07-09 12:12+0800\n"
 "Last-Translator: Wylmer Wang <wantinghard@gmail.com>\n"
 "Language-Team: Chinese (simplified) <i18n-zh@googlegroups.com>\n"
@@ -16,12 +16,12 @@ msgstr ""
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
 
-#: src/abd/gnunet-abd.c:397 src/namestore/gnunet-namestore.c:1302
+#: src/abd/gnunet-abd.c:397 src/namestore/gnunet-namestore.c:1303
 #, c-format
 msgid "Ego `%s' not known to identity service\n"
 msgstr ""
 
-#: src/abd/gnunet-abd.c:413 src/abd/gnunet-abd.c:896
+#: src/abd/gnunet-abd.c:413 src/abd/gnunet-abd.c:901
 #, fuzzy, c-format
 msgid "Issuer public key `%s' is not well-formed\n"
 msgstr "“%s”的参数无效。\n"
@@ -33,107 +33,107 @@ msgstr "“%s”的参数无效。\n"
 msgid "Failed to connect to namestore\n"
 msgstr "初始化“%s”服务失败。\n"
 
-#: src/abd/gnunet-abd.c:835 src/abd/gnunet-abd.c:886
+#: src/abd/gnunet-abd.c:840 src/abd/gnunet-abd.c:891
 #, fuzzy, c-format
 msgid "Issuer public key not well-formed\n"
 msgstr "“%s”的参数无效。\n"
 
-#: src/abd/gnunet-abd.c:844 src/abd/gnunet-abd.c:905
+#: src/abd/gnunet-abd.c:849 src/abd/gnunet-abd.c:910
 #, fuzzy, c-format
 msgid "Failed to connect to ABD\n"
 msgstr "初始化“%s”服务失败。\n"
 
-#: src/abd/gnunet-abd.c:850
+#: src/abd/gnunet-abd.c:855
 #, c-format
 msgid "You must provide issuer the attribute\n"
 msgstr ""
 
-#: src/abd/gnunet-abd.c:857
+#: src/abd/gnunet-abd.c:862
 #, c-format
 msgid "ego required\n"
 msgstr ""
 
-#: src/abd/gnunet-abd.c:867
+#: src/abd/gnunet-abd.c:872
 #, c-format
 msgid "Subject public key needed\n"
 msgstr ""
 
-#: src/abd/gnunet-abd.c:876
+#: src/abd/gnunet-abd.c:881
 #, fuzzy, c-format
 msgid "Subject public key `%s' is not well-formed\n"
 msgstr "“%s”的参数无效。\n"
 
-#: src/abd/gnunet-abd.c:911
+#: src/abd/gnunet-abd.c:916
 #, c-format
 msgid "You must provide issuer and subject attributes\n"
 msgstr ""
 
-#: src/abd/gnunet-abd.c:970
+#: src/abd/gnunet-abd.c:975
 #, c-format
 msgid "Please specify name to lookup, subject key and issuer key!\n"
 msgstr ""
 
-#: src/abd/gnunet-abd.c:991
+#: src/abd/gnunet-abd.c:996
 msgid "verify credential against attribute"
 msgstr ""
 
-#: src/abd/gnunet-abd.c:998
+#: src/abd/gnunet-abd.c:1003
 msgid ""
 "The public key of the subject to lookup thecredential for, or for issuer "
 "side storage: subject and its attributes"
 msgstr ""
 
-#: src/abd/gnunet-abd.c:1005
+#: src/abd/gnunet-abd.c:1010
 msgid "The private, signed delegate presented by the subject"
 msgstr ""
 
-#: src/abd/gnunet-abd.c:1012
+#: src/abd/gnunet-abd.c:1017
 msgid "The public key of the authority to verify the credential against"
 msgstr ""
 
-#: src/abd/gnunet-abd.c:1017
+#: src/abd/gnunet-abd.c:1022
 #, fuzzy
 msgid "The ego/zone name to use"
 msgstr "消息尺寸"
 
-#: src/abd/gnunet-abd.c:1023
+#: src/abd/gnunet-abd.c:1028
 msgid "The issuer attribute to verify against or to issue"
 msgstr ""
 
-#: src/abd/gnunet-abd.c:1029
+#: src/abd/gnunet-abd.c:1034
 msgid ""
 "The time to live for the credential.e.g. 5m, 6h, \"1990-12-30 12:00:00\""
 msgstr ""
 
-#: src/abd/gnunet-abd.c:1034
+#: src/abd/gnunet-abd.c:1039
 msgid "collect credentials"
 msgstr ""
 
-#: src/abd/gnunet-abd.c:1039
+#: src/abd/gnunet-abd.c:1044
 msgid "Create and issue a credential issuer side."
 msgstr ""
 
-#: src/abd/gnunet-abd.c:1044
+#: src/abd/gnunet-abd.c:1049
 msgid "Issue a credential subject side."
 msgstr ""
 
-#: src/abd/gnunet-abd.c:1049
+#: src/abd/gnunet-abd.c:1054
 msgid "Create, sign and return a credential subject side."
 msgstr ""
 
-#: src/abd/gnunet-abd.c:1056
+#: src/abd/gnunet-abd.c:1061
 msgid "Import signed credentials that should be issued to a zone/ego"
 msgstr ""
 
-#: src/abd/gnunet-abd.c:1060
+#: src/abd/gnunet-abd.c:1065
 msgid "Create private record entry."
 msgstr ""
 
-#: src/abd/gnunet-abd.c:1066 src/abd/gnunet-abd.c:1072
+#: src/abd/gnunet-abd.c:1071 src/abd/gnunet-abd.c:1077
 msgid "Indicates that the collect/verify process is done via forward search."
 msgstr ""
 
-#: src/abd/gnunet-abd.c:1085
+#: src/abd/gnunet-abd.c:1090
 #, fuzzy
 msgid "GNUnet abd resolver tool"
 msgstr "GNUnet 错误日志"
@@ -427,65 +427,65 @@ msgstr "打开日志文件“%s”失败:%s\n"
 msgid "Failed to find %saddress for `%s'.\n"
 msgstr "找不到接口“%s”的一个 IP 地址。\n"
 
-#: src/arm/gnunet-service-arm.c:933
+#: src/arm/gnunet-service-arm.c:951
 #, fuzzy, c-format
 msgid "Failed to start service `%s'\n"
 msgstr "解析配置文件“%s”失败\n"
 
-#: src/arm/gnunet-service-arm.c:944
+#: src/arm/gnunet-service-arm.c:962
 #, c-format
 msgid "Starting service `%s'\n"
 msgstr ""
 
-#: src/arm/gnunet-service-arm.c:1044
+#: src/arm/gnunet-service-arm.c:1062
 #, fuzzy, c-format
 msgid "Unable to create socket for service `%s': %s\n"
 msgstr "无法创建用户账户:"
 
-#: src/arm/gnunet-service-arm.c:1075
+#: src/arm/gnunet-service-arm.c:1093
 #, c-format
 msgid "Unable to bind listening socket for service `%s' to address `%s': %s\n"
 msgstr ""
 
-#: src/arm/gnunet-service-arm.c:1106
+#: src/arm/gnunet-service-arm.c:1124
 #, c-format
 msgid "ARM now monitors connections to service `%s' at `%s'\n"
 msgstr ""
 
-#: src/arm/gnunet-service-arm.c:1254
+#: src/arm/gnunet-service-arm.c:1272
 #, c-format
 msgid "Preparing to stop `%s'\n"
 msgstr ""
 
-#: src/arm/gnunet-service-arm.c:1586
+#: src/arm/gnunet-service-arm.c:1604
 #, c-format
 msgid "Restarting service `%s'.\n"
 msgstr ""
 
-#: src/arm/gnunet-service-arm.c:1737
+#: src/arm/gnunet-service-arm.c:1755
 msgid "exit"
 msgstr ""
 
-#: src/arm/gnunet-service-arm.c:1742
+#: src/arm/gnunet-service-arm.c:1760
 msgid "signal"
 msgstr ""
 
-#: src/arm/gnunet-service-arm.c:1747
+#: src/arm/gnunet-service-arm.c:1765
 #, fuzzy
 msgid "unknown"
 msgstr "未知错误"
 
-#: src/arm/gnunet-service-arm.c:1753
+#: src/arm/gnunet-service-arm.c:1771
 #, fuzzy, c-format
 msgid "Service `%s' took %s to terminate\n"
 msgstr "服务已删除。\n"
 
-#: src/arm/gnunet-service-arm.c:1780
+#: src/arm/gnunet-service-arm.c:1798
 #, c-format
 msgid "Service `%s' terminated normally, will restart at any time\n"
 msgstr ""
 
-#: src/arm/gnunet-service-arm.c:1797
+#: src/arm/gnunet-service-arm.c:1815
 #, c-format
 msgid "Service `%s' terminated with status %s/%d, will restart in %s\n"
 msgstr ""
@@ -819,7 +819,10 @@ msgstr ""
 
 #: src/consensus/gnunet-consensus-profiler.c:543
 #: src/set/gnunet-set-profiler.c:451 src/set/gnunet-set-profiler.c:457
-#: src/set/gnunet-set-profiler.c:480
+#: src/set/gnunet-set-profiler.c:480 src/seti/gnunet-seti-profiler.c:441
+#: src/seti/gnunet-seti-profiler.c:446 src/seti/gnunet-seti-profiler.c:451
+#: src/setu/gnunet-setu-profiler.c:442 src/setu/gnunet-setu-profiler.c:448
+#: src/setu/gnunet-setu-profiler.c:471
 #, fuzzy
 msgid "number of values"
 msgstr "迭代次数"
@@ -833,7 +836,8 @@ msgid "delay until consensus starts"
 msgstr ""
 
 #: src/consensus/gnunet-consensus-profiler.c:563
-#: src/set/gnunet-set-profiler.c:498
+#: src/set/gnunet-set-profiler.c:498 src/seti/gnunet-seti-profiler.c:467
+#: src/setu/gnunet-setu-profiler.c:489
 msgid "write statistics to file"
 msgstr ""
 
@@ -1375,137 +1379,137 @@ msgstr "立即保存配置?"
 msgid "Core service of `%s' ready.\n"
 msgstr "服务已删除。\n"
 
-#: src/core/gnunet-service-core_kx.c:625
+#: src/core/gnunet-service-core_kx.c:512
 msgid "# bytes encrypted"
 msgstr ""
 
-#: src/core/gnunet-service-core_kx.c:683
+#: src/core/gnunet-service-core_kx.c:570
 msgid "# bytes decrypted"
 msgstr ""
 
-#: src/core/gnunet-service-core_kx.c:780
+#: src/core/gnunet-service-core_kx.c:667
 msgid "# PAYLOAD dropped (out of order)"
 msgstr ""
 
-#: src/core/gnunet-service-core_kx.c:832
+#: src/core/gnunet-service-core_kx.c:719
 msgid "# key exchanges initiated"
 msgstr ""
 
-#: src/core/gnunet-service-core_kx.c:888
+#: src/core/gnunet-service-core_kx.c:775
 msgid "# key exchanges stopped"
 msgstr ""
 
-#: src/core/gnunet-service-core_kx.c:920
+#: src/core/gnunet-service-core_kx.c:807
 #, fuzzy
 msgid "# PING messages transmitted"
 msgstr "消息尺寸"
 
-#: src/core/gnunet-service-core_kx.c:979
+#: src/core/gnunet-service-core_kx.c:866
 msgid "# old ephemeral keys ignored"
 msgstr ""
 
-#: src/core/gnunet-service-core_kx.c:993
+#: src/core/gnunet-service-core_kx.c:880
 msgid "# duplicate ephemeral keys ignored"
 msgstr ""
 
-#: src/core/gnunet-service-core_kx.c:1028
+#: src/core/gnunet-service-core_kx.c:915
 msgid "# EPHEMERAL_KEYs rejected (bad signature)"
 msgstr ""
 
-#: src/core/gnunet-service-core_kx.c:1046
+#: src/core/gnunet-service-core_kx.c:933
 #, c-format
 msgid ""
 "EPHEMERAL_KEY from peer `%s' rejected as its validity range does not match "
 "our system time (%llu not in [%llu,%llu]).\n"
 msgstr ""
 
-#: src/core/gnunet-service-core_kx.c:1053
+#: src/core/gnunet-service-core_kx.c:940
 msgid "# EPHEMERAL_KEY messages rejected due to time"
 msgstr ""
 
-#: src/core/gnunet-service-core_kx.c:1071
+#: src/core/gnunet-service-core_kx.c:958
 #, fuzzy
 msgid "# valid ephemeral keys received"
 msgstr "保存配置失败。"
 
-#: src/core/gnunet-service-core_kx.c:1180
+#: src/core/gnunet-service-core_kx.c:1067
 #: src/transport/gnunet-service-transport_validation.c:1133
 msgid "# PING messages received"
 msgstr ""
 
-#: src/core/gnunet-service-core_kx.c:1190
+#: src/core/gnunet-service-core_kx.c:1077
 msgid "# PING messages dropped (out of order)"
 msgstr ""
 
-#: src/core/gnunet-service-core_kx.c:1239
+#: src/core/gnunet-service-core_kx.c:1126
 msgid "# PONG messages created"
 msgstr ""
 
-#: src/core/gnunet-service-core_kx.c:1264
+#: src/core/gnunet-service-core_kx.c:1151
 msgid "# sessions terminated by timeout"
 msgstr ""
 
-#: src/core/gnunet-service-core_kx.c:1277
+#: src/core/gnunet-service-core_kx.c:1164
 msgid "# keepalive messages sent"
 msgstr ""
 
-#: src/core/gnunet-service-core_kx.c:1334
+#: src/core/gnunet-service-core_kx.c:1221
 #: src/transport/gnunet-service-transport_validation.c:1476
 msgid "# PONG messages received"
 msgstr ""
 
-#: src/core/gnunet-service-core_kx.c:1342
+#: src/core/gnunet-service-core_kx.c:1229
 msgid "# PONG messages dropped (connection down)"
 msgstr ""
 
-#: src/core/gnunet-service-core_kx.c:1350
+#: src/core/gnunet-service-core_kx.c:1237
 msgid "# PONG messages dropped (out of order)"
 msgstr ""
 
-#: src/core/gnunet-service-core_kx.c:1389
+#: src/core/gnunet-service-core_kx.c:1276
 msgid "# PONG messages decrypted"
 msgstr ""
 
-#: src/core/gnunet-service-core_kx.c:1429
+#: src/core/gnunet-service-core_kx.c:1316
 msgid "# session keys confirmed via PONG"
 msgstr ""
 
-#: src/core/gnunet-service-core_kx.c:1441
+#: src/core/gnunet-service-core_kx.c:1328
 msgid "# timeouts prevented via PONG"
 msgstr ""
 
-#: src/core/gnunet-service-core_kx.c:1450
+#: src/core/gnunet-service-core_kx.c:1337
 msgid "# rekey operations confirmed via PONG"
 msgstr ""
 
-#: src/core/gnunet-service-core_kx.c:1626
+#: src/core/gnunet-service-core_kx.c:1513
 msgid "# DATA message dropped (out of order)"
 msgstr ""
 
-#: src/core/gnunet-service-core_kx.c:1637
+#: src/core/gnunet-service-core_kx.c:1524
 #, c-format
 msgid ""
 "Session to peer `%s' went down due to key expiration (should not happen)\n"
 msgstr ""
 
-#: src/core/gnunet-service-core_kx.c:1641
+#: src/core/gnunet-service-core_kx.c:1528
 msgid "# sessions terminated by key expiration"
 msgstr ""
 
-#: src/core/gnunet-service-core_kx.c:1719
-#: src/core/gnunet-service-core_kx.c:1746
+#: src/core/gnunet-service-core_kx.c:1606
+#: src/core/gnunet-service-core_kx.c:1633
 msgid "# bytes dropped (duplicates)"
 msgstr ""
 
-#: src/core/gnunet-service-core_kx.c:1732
+#: src/core/gnunet-service-core_kx.c:1619
 msgid "# bytes dropped (out of sequence)"
 msgstr ""
 
-#: src/core/gnunet-service-core_kx.c:1777
+#: src/core/gnunet-service-core_kx.c:1664
 msgid "# bytes dropped (ancient message)"
 msgstr ""
 
-#: src/core/gnunet-service-core_kx.c:1786
+#: src/core/gnunet-service-core_kx.c:1673
 msgid "# bytes of payload decrypted"
 msgstr ""
 
@@ -3063,18 +3067,18 @@ msgstr ""
 msgid "Failed to load state: %s\n"
 msgstr "运行 %s失败:%s %d\n"
 
-#: src/fs/gnunet-auto-share.c:286 src/fs/gnunet-auto-share.c:295
-#: src/fs/gnunet-auto-share.c:303
+#: src/fs/gnunet-auto-share.c:287 src/fs/gnunet-auto-share.c:296
+#: src/fs/gnunet-auto-share.c:304
 #, fuzzy, c-format
 msgid "Failed to save state to file %s\n"
 msgstr "解析配置文件“%s”失败\n"
 
-#: src/fs/gnunet-auto-share.c:400
+#: src/fs/gnunet-auto-share.c:401
 #, c-format
 msgid "Publication of `%s' done\n"
 msgstr ""
 
-#: src/fs/gnunet-auto-share.c:479
+#: src/fs/gnunet-auto-share.c:480
 #, c-format
 msgid "Publishing `%s'\n"
 msgstr ""
@@ -3874,39 +3878,39 @@ msgstr ""
 msgid "GNUnet HTTP server to create business cards"
 msgstr ""
 
-#: src/gns/gnunet-dns2gns.c:239
+#: src/gns/gnunet-dns2gns.c:241
 #, fuzzy
 msgid "Failed to pack DNS response into UDP packet!\n"
 msgstr "打开日志文件“%s”失败:%s\n"
 
-#: src/gns/gnunet-dns2gns.c:442
+#: src/gns/gnunet-dns2gns.c:444
 #, c-format
 msgid "Cannot parse DNS request from %s\n"
 msgstr ""
 
-#: src/gns/gnunet-dns2gns.c:458
+#: src/gns/gnunet-dns2gns.c:460
 #, c-format
 msgid "Received malformed DNS request from %s\n"
 msgstr ""
 
-#: src/gns/gnunet-dns2gns.c:466
+#: src/gns/gnunet-dns2gns.c:468
 #, c-format
 msgid "Received unsupported DNS request from %s\n"
 msgstr ""
 
-#: src/gns/gnunet-dns2gns.c:627
+#: src/gns/gnunet-dns2gns.c:629
 msgid "No DNS server specified!\n"
 msgstr ""
 
-#: src/gns/gnunet-dns2gns.c:776
+#: src/gns/gnunet-dns2gns.c:778
 msgid "IP of recursive DNS resolver to use (required)"
 msgstr ""
 
-#: src/gns/gnunet-dns2gns.c:782
+#: src/gns/gnunet-dns2gns.c:784
 msgid "UDP port to listen on for inbound DNS requests; default: 2853"
 msgstr ""
 
-#: src/gns/gnunet-dns2gns.c:799
+#: src/gns/gnunet-dns2gns.c:801
 msgid "GNUnet DNS-to-GNS proxy (a DNS server)"
 msgstr ""
 
@@ -4045,7 +4049,7 @@ msgstr "无法保存配置文件“%s”:"
 msgid "Failed to start HTTPS server for `%s'\n"
 msgstr "初始化“%s”服务失败。\n"
 
-#: src/gns/gnunet-gns-proxy.c:2922 src/rest/gnunet-rest-server.c:713
+#: src/gns/gnunet-gns-proxy.c:2922 src/rest/gnunet-rest-server.c:917
 #, fuzzy
 msgid "Failed to pass client to MHD\n"
 msgstr "初始化“%s”服务失败。\n"
@@ -4201,7 +4205,7 @@ msgstr "解析配置文件“%s”失败\n"
 msgid "Unable to parse BOX record string `%s'\n"
 msgstr "解析配置文件“%s”失败\n"
 
-#: src/gns/plugin_rest_gns.c:445
+#: src/gns/plugin_rest_gns.c:447
 msgid "Gns REST API initialized\n"
 msgstr ""
 
@@ -4397,7 +4401,7 @@ msgid "# valid HELLOs downloaded from hostlist servers"
 msgstr ""
 
 #: src/hostlist/gnunet-daemon-hostlist_client.c:677
-#: src/hostlist/gnunet-daemon-hostlist_client.c:1459
+#: src/hostlist/gnunet-daemon-hostlist_client.c:1460
 msgid "# advertised hostlist URIs"
 msgstr ""
 
@@ -4448,7 +4452,7 @@ msgid "# hostlist downloads initiated"
 msgstr ""
 
 #: src/hostlist/gnunet-daemon-hostlist_client.c:1144
-#: src/hostlist/gnunet-daemon-hostlist_client.c:1726
+#: src/hostlist/gnunet-daemon-hostlist_client.c:1728
 msgid "# milliseconds between hostlist downloads"
 msgstr ""
 
@@ -4477,50 +4481,50 @@ msgstr ""
 msgid "Could not open file `%s' for reading to load hostlists: %s\n"
 msgstr "无法解析“%s”来确定已方的 IP 地址:%s\n"
 
-#: src/hostlist/gnunet-daemon-hostlist_client.c:1452
+#: src/hostlist/gnunet-daemon-hostlist_client.c:1453
 #, c-format
 msgid "%u hostlist URIs loaded from file\n"
 msgstr ""
 
-#: src/hostlist/gnunet-daemon-hostlist_client.c:1455
+#: src/hostlist/gnunet-daemon-hostlist_client.c:1456
 msgid "# hostlist URIs read from file"
 msgstr ""
 
-#: src/hostlist/gnunet-daemon-hostlist_client.c:1506
+#: src/hostlist/gnunet-daemon-hostlist_client.c:1507
 #, fuzzy, c-format
 msgid "Could not open file `%s' for writing to save hostlists: %s\n"
 msgstr "无法解析“%s”来确定已方的 IP 地址:%s\n"
 
-#: src/hostlist/gnunet-daemon-hostlist_client.c:1513
+#: src/hostlist/gnunet-daemon-hostlist_client.c:1514
 #, c-format
 msgid "Writing %u hostlist URIs to `%s'\n"
 msgstr ""
 
-#: src/hostlist/gnunet-daemon-hostlist_client.c:1545
-#: src/hostlist/gnunet-daemon-hostlist_client.c:1564
+#: src/hostlist/gnunet-daemon-hostlist_client.c:1547
+#: src/hostlist/gnunet-daemon-hostlist_client.c:1566
 #, c-format
 msgid "Error writing hostlist URIs to file `%s'\n"
 msgstr ""
 
-#: src/hostlist/gnunet-daemon-hostlist_client.c:1558
+#: src/hostlist/gnunet-daemon-hostlist_client.c:1560
 msgid "# hostlist URIs written to file"
 msgstr ""
 
-#: src/hostlist/gnunet-daemon-hostlist_client.c:1655
+#: src/hostlist/gnunet-daemon-hostlist_client.c:1657
 #: src/transport/plugin_transport_http_client.c:2301
 #, c-format
 msgid "Invalid proxy type: `%s', disabling proxy! Check configuration!\n"
 msgstr ""
 
-#: src/hostlist/gnunet-daemon-hostlist_client.c:1684
+#: src/hostlist/gnunet-daemon-hostlist_client.c:1686
 msgid "Learning is enabled on this peer\n"
 msgstr ""
 
-#: src/hostlist/gnunet-daemon-hostlist_client.c:1697
+#: src/hostlist/gnunet-daemon-hostlist_client.c:1699
 msgid "Learning is not enabled on this peer\n"
 msgstr ""
 
-#: src/hostlist/gnunet-daemon-hostlist_client.c:1711
+#: src/hostlist/gnunet-daemon-hostlist_client.c:1713
 #, c-format
 msgid ""
 "Since learning is not enabled on this peer, hostlist file `%s' was removed\n"
@@ -4644,48 +4648,48 @@ msgstr "发送消息失败。\n"
 msgid "Failed to set default ego: %s\n"
 msgstr "发送消息失败。\n"
 
-#: src/identity/gnunet-identity.c:445
+#: src/identity/gnunet-identity.c:446
 msgid "create ego NAME"
 msgstr ""
 
-#: src/identity/gnunet-identity.c:450
+#: src/identity/gnunet-identity.c:451
 msgid "delete ego NAME "
 msgstr ""
 
-#: src/identity/gnunet-identity.c:455
+#: src/identity/gnunet-identity.c:457
 msgid ""
 "set the private key for the identity to PRIVATE_KEY (use together with -C)"
 msgstr ""
 
-#: src/identity/gnunet-identity.c:459
+#: src/identity/gnunet-identity.c:461
 msgid "display all egos"
 msgstr ""
 
-#: src/identity/gnunet-identity.c:463
+#: src/identity/gnunet-identity.c:465
 msgid "reduce output"
 msgstr ""
 
-#: src/identity/gnunet-identity.c:470
+#: src/identity/gnunet-identity.c:472
 msgid ""
 "set default identity to NAME for a subsystem SUBSYSTEM (use together with -"
 "s) or restrict results to NAME (use together with -d)"
 msgstr ""
 
-#: src/identity/gnunet-identity.c:474
+#: src/identity/gnunet-identity.c:476
 msgid "run in monitor mode egos"
 msgstr ""
 
-#: src/identity/gnunet-identity.c:478
+#: src/identity/gnunet-identity.c:480
 #, fuzzy
 msgid "display private keys as well"
 msgstr "显示一个文件的散列值"
 
-#: src/identity/gnunet-identity.c:485
+#: src/identity/gnunet-identity.c:487
 msgid ""
 "set default identity to EGO for a subsystem SUBSYSTEM (use together with -e)"
 msgstr ""
 
-#: src/identity/gnunet-identity.c:500
+#: src/identity/gnunet-identity.c:502
 msgid "Maintain egos"
 msgstr ""
 
@@ -4736,7 +4740,7 @@ msgstr "解析配置文件“%s”失败\n"
 msgid "Failed to create directory `%s' for storing egos\n"
 msgstr "解析配置文件“%s”失败\n"
 
-#: src/identity/plugin_rest_identity.c:1406
+#: src/identity/plugin_rest_identity.c:1384
 msgid "Identity REST API initialized\n"
 msgstr ""
 
@@ -4785,7 +4789,7 @@ msgstr "“%s”的参数无效。\n"
 msgid "You must specify a name\n"
 msgstr "您必须指定一个接收方!\n"
 
-#: src/namecache/gnunet-namecache.c:214 src/namestore/gnunet-namestore.c:1639
+#: src/namecache/gnunet-namecache.c:214 src/namestore/gnunet-namestore.c:1640
 msgid "name of the record to add/delete/display"
 msgstr ""
 
@@ -4793,7 +4797,7 @@ msgstr ""
 msgid "specifies the public key of the zone to look in"
 msgstr ""
 
-#: src/namecache/gnunet-namecache.c:233 src/namestore/gnunet-namestore.c:1700
+#: src/namecache/gnunet-namecache.c:233 src/namestore/gnunet-namestore.c:1701
 #, fuzzy
 msgid "GNUnet zone manipulation tool"
 msgstr "GNUnet 配置"
@@ -4902,10 +4906,10 @@ msgstr "打开日志文件“%s”失败:%s\n"
 msgid "No options given\n"
 msgstr ""
 
-#: src/namestore/gnunet-namestore.c:1014 src/namestore/gnunet-namestore.c:1065
-#: src/namestore/gnunet-namestore.c:1075 src/namestore/gnunet-namestore.c:1104
-#: src/namestore/gnunet-namestore.c:1125 src/namestore/gnunet-namestore.c:1152
-#: src/namestore/gnunet-namestore.c:1228
+#: src/namestore/gnunet-namestore.c:1014 src/namestore/gnunet-namestore.c:1066
+#: src/namestore/gnunet-namestore.c:1076 src/namestore/gnunet-namestore.c:1105
+#: src/namestore/gnunet-namestore.c:1126 src/namestore/gnunet-namestore.c:1153
+#: src/namestore/gnunet-namestore.c:1229
 #, fuzzy, c-format
 msgid "Missing option `%s' for operation `%s'\n"
 msgstr "配置文件“%s”已写入。\n"
@@ -4919,53 +4923,53 @@ msgstr ""
 msgid "Invalid nick `%s'\n"
 msgstr "无效条目。\n"
 
-#: src/namestore/gnunet-namestore.c:1067 src/namestore/gnunet-namestore.c:1077
-#: src/namestore/gnunet-namestore.c:1106 src/namestore/gnunet-namestore.c:1127
-#: src/namestore/gnunet-namestore.c:1230
+#: src/namestore/gnunet-namestore.c:1068 src/namestore/gnunet-namestore.c:1078
+#: src/namestore/gnunet-namestore.c:1107 src/namestore/gnunet-namestore.c:1128
+#: src/namestore/gnunet-namestore.c:1231
 msgid "add"
 msgstr ""
 
-#: src/namestore/gnunet-namestore.c:1085
+#: src/namestore/gnunet-namestore.c:1086
 #, fuzzy, c-format
 msgid "Unsupported type `%s'\n"
 msgstr "未知的命令“%s”。\n"
 
-#: src/namestore/gnunet-namestore.c:1095
+#: src/namestore/gnunet-namestore.c:1096
 #, c-format
 msgid "For DNS record types `SRV', `TLSA' and `OPENPGPKEY'"
 msgstr ""
 
-#: src/namestore/gnunet-namestore.c:1115
+#: src/namestore/gnunet-namestore.c:1116
 #, c-format
 msgid "Value `%s' invalid for record type `%s'\n"
 msgstr ""
 
-#: src/namestore/gnunet-namestore.c:1134 src/namestore/gnunet-namestore.c:1237
+#: src/namestore/gnunet-namestore.c:1135 src/namestore/gnunet-namestore.c:1238
 #, fuzzy, c-format
 msgid "Invalid time format `%s'\n"
 msgstr "IP 格式无效:“%s”\n"
 
-#: src/namestore/gnunet-namestore.c:1154
+#: src/namestore/gnunet-namestore.c:1155
 msgid "del"
 msgstr ""
 
-#: src/namestore/gnunet-namestore.c:1197
+#: src/namestore/gnunet-namestore.c:1198
 #, fuzzy, c-format
 msgid "Invalid public key for reverse lookup `%s'\n"
 msgstr "“%s”的参数无效。\n"
 
-#: src/namestore/gnunet-namestore.c:1220
+#: src/namestore/gnunet-namestore.c:1221
 #: src/peerinfo-tool/gnunet-peerinfo.c:736
 #, fuzzy, c-format
 msgid "Invalid URI `%s'\n"
 msgstr "无效条目。\n"
 
-#: src/namestore/gnunet-namestore.c:1290
+#: src/namestore/gnunet-namestore.c:1291
 #, c-format
 msgid "Label `%s' contains `.' which is not allowed\n"
 msgstr ""
 
-#: src/namestore/gnunet-namestore.c:1340
+#: src/namestore/gnunet-namestore.c:1341
 #, c-format
 msgid ""
 "No default identity configured for `namestore' subsystem\n"
@@ -4973,102 +4977,102 @@ msgid ""
 "Run gnunet-identity -d to get a list of choices for $NAME\n"
 msgstr ""
 
-#: src/namestore/gnunet-namestore.c:1405
+#: src/namestore/gnunet-namestore.c:1406
 #, c-format
 msgid "Superfluous command line arguments (starting with `%s') ignored\n"
 msgstr ""
 
-#: src/namestore/gnunet-namestore.c:1434
+#: src/namestore/gnunet-namestore.c:1435
 #, fuzzy, c-format
 msgid "Cannot connect to identity service\n"
 msgstr "无法连接到 %s:%u:%s\n"
 
-#: src/namestore/gnunet-namestore.c:1481
+#: src/namestore/gnunet-namestore.c:1482
 msgid "Empty record line argument is not allowed.\n"
 msgstr ""
 
-#: src/namestore/gnunet-namestore.c:1493
+#: src/namestore/gnunet-namestore.c:1494
 #, c-format
 msgid "Invalid expiration time `%s' (must be without unit)\n"
 msgstr ""
 
-#: src/namestore/gnunet-namestore.c:1505 src/namestore/gnunet-namestore.c:1521
-#: src/namestore/gnunet-namestore.c:1538
+#: src/namestore/gnunet-namestore.c:1506 src/namestore/gnunet-namestore.c:1522
+#: src/namestore/gnunet-namestore.c:1539
 #, fuzzy, c-format
 msgid "Missing entries in record line `%s'.\n"
 msgstr "解析配置文件“%s”失败\n"
 
-#: src/namestore/gnunet-namestore.c:1513
+#: src/namestore/gnunet-namestore.c:1514
 #, fuzzy, c-format
 msgid "Unknown record type `%s'\n"
 msgstr "未知的命令“%s”。\n"
 
-#: src/namestore/gnunet-namestore.c:1551
+#: src/namestore/gnunet-namestore.c:1552
 #, fuzzy, c-format
 msgid "Invalid record data for type %s: `%s'.\n"
 msgstr "IP 格式无效:“%s”\n"
 
-#: src/namestore/gnunet-namestore.c:1608
+#: src/namestore/gnunet-namestore.c:1609
 msgid "add record"
 msgstr ""
 
-#: src/namestore/gnunet-namestore.c:1611
+#: src/namestore/gnunet-namestore.c:1612
 msgid "delete record"
 msgstr ""
 
-#: src/namestore/gnunet-namestore.c:1615
+#: src/namestore/gnunet-namestore.c:1616
 msgid "display records"
 msgstr ""
 
-#: src/namestore/gnunet-namestore.c:1622
+#: src/namestore/gnunet-namestore.c:1623
 msgid ""
 "expiration time for record to use (for adding only), \"never\" is possible"
 msgstr ""
 
-#: src/namestore/gnunet-namestore.c:1628
+#: src/namestore/gnunet-namestore.c:1629
 #, fuzzy
 msgid "set the desired nick name for the zone"
 msgstr "无法获取有关用户“%s”的信息:%s\n"
 
-#: src/namestore/gnunet-namestore.c:1633
+#: src/namestore/gnunet-namestore.c:1634
 #, fuzzy
 msgid "monitor changes in the namestore"
 msgstr "初始化“%s”服务失败。\n"
 
-#: src/namestore/gnunet-namestore.c:1645
+#: src/namestore/gnunet-namestore.c:1646
 #, fuzzy
 msgid "determine our name for the given PKEY"
 msgstr "无法获取有关用户“%s”的信息:%s\n"
 
-#: src/namestore/gnunet-namestore.c:1652
+#: src/namestore/gnunet-namestore.c:1653
 msgid ""
 "set record set to values given by (possibly multiple) RECORDLINES; can be "
 "specified multiple times"
 msgstr ""
 
-#: src/namestore/gnunet-namestore.c:1658
+#: src/namestore/gnunet-namestore.c:1659
 msgid "type of the record to add/delete/display"
 msgstr ""
 
-#: src/namestore/gnunet-namestore.c:1663
+#: src/namestore/gnunet-namestore.c:1664
 msgid "URI to import into our zone"
 msgstr ""
 
-#: src/namestore/gnunet-namestore.c:1669
+#: src/namestore/gnunet-namestore.c:1670
 msgid "value of the record to add/delete"
 msgstr ""
 
-#: src/namestore/gnunet-namestore.c:1673
+#: src/namestore/gnunet-namestore.c:1674
 msgid "create or list public record"
 msgstr ""
 
-#: src/namestore/gnunet-namestore.c:1679
+#: src/namestore/gnunet-namestore.c:1680
 msgid ""
 "create shadow record (only valid if all other records of the same type have "
 "expired"
 msgstr ""
 
-#: src/namestore/gnunet-namestore.c:1685
+#: src/namestore/gnunet-namestore.c:1686
 msgid "name of the ego controlling the zone"
 msgstr ""
 
@@ -5168,7 +5172,7 @@ msgstr ""
 msgid "Flat file database running\n"
 msgstr "sqlite 数据仓库"
 
-#: src/namestore/plugin_rest_namestore.c:1093
+#: src/namestore/plugin_rest_namestore.c:1103
 msgid "Namestore REST API initialized\n"
 msgstr ""
 
@@ -5438,7 +5442,7 @@ msgstr ""
 msgid "gnunet-helper-nat-server generated malformed address `%s'\n"
 msgstr ""
 
-#: src/nat/gnunet-service-nat_helper.c:250
+#: src/nat/gnunet-service-nat_helper.c:249
 #, fuzzy, c-format
 msgid "Failed to start %s\n"
 msgstr "运行 %s失败:%s %d\n"
@@ -5447,7 +5451,7 @@ msgstr "运行 %s失败:%s %d\n"
 msgid "`external-ip' command not found\n"
 msgstr ""
 
-#: src/nat/gnunet-service-nat_mini.c:608
+#: src/nat/gnunet-service-nat_mini.c:607
 msgid "`upnpc' command not found\n"
 msgstr ""
 
@@ -5480,8 +5484,8 @@ msgstr ""
 msgid "Measure quality and performance of the NSE service."
 msgstr "无法访问该服务"
 
-#: src/nse/gnunet-service-nse.c:1438
-#: src/revocation/gnunet-service-revocation.c:842 src/util/gnunet-scrypt.c:250
+#: src/nse/gnunet-service-nse.c:1443
+#: src/revocation/gnunet-service-revocation.c:834 src/util/gnunet-scrypt.c:257
 #, fuzzy
 msgid "Value is too large.\n"
 msgstr "值不在合法范围内。"
@@ -5551,7 +5555,7 @@ msgid "\tExpires: %s \t %s\n"
 msgstr ""
 
 #: src/peerinfo-tool/gnunet-peerinfo.c:292
-#: src/peerinfo-tool/plugin_rest_peerinfo.c:501
+#: src/peerinfo-tool/plugin_rest_peerinfo.c:523
 #, fuzzy, c-format
 msgid "Failure: Cannot convert address to string for peer `%s'\n"
 msgstr "找不到接口“%s”的一个 IP 地址。\n"
@@ -5632,7 +5636,7 @@ msgstr ""
 msgid "Failed to load transport plugin for `%s'\n"
 msgstr "解析配置文件“%s”失败\n"
 
-#: src/peerinfo-tool/plugin_rest_peerinfo.c:797
+#: src/peerinfo-tool/plugin_rest_peerinfo.c:809
 msgid "Peerinfo REST API initialized\n"
 msgstr ""
 
@@ -5738,95 +5742,99 @@ msgstr "初始化“%s”服务失败。\n"
 msgid "Daemon to run to perform IP protocol translation to GNUnet"
 msgstr ""
 
-#: src/reclaim/gnunet-reclaim.c:799
+#: src/reclaim/gnunet-reclaim.c:801
 #, fuzzy, c-format
 msgid "Ego is required\n"
 msgstr "%s:选项“%s”有歧义\n"
 
-#: src/reclaim/gnunet-reclaim.c:806
+#: src/reclaim/gnunet-reclaim.c:808
 #, c-format
 msgid "Attribute value missing!\n"
 msgstr ""
 
-#: src/reclaim/gnunet-reclaim.c:813
+#: src/reclaim/gnunet-reclaim.c:815
 #, fuzzy, c-format
 msgid "Requesting party key is required!\n"
 msgstr "设置要使用的昵称(必须)"
 
-#: src/reclaim/gnunet-reclaim.c:831
+#: src/reclaim/gnunet-reclaim.c:833
 msgid "Add an attribute NAME"
 msgstr ""
 
-#: src/reclaim/gnunet-reclaim.c:836
+#: src/reclaim/gnunet-reclaim.c:838
 msgid "Delete the attribute with ID"
 msgstr ""
 
-#: src/reclaim/gnunet-reclaim.c:841
+#: src/reclaim/gnunet-reclaim.c:843
 msgid "The attribute VALUE"
 msgstr ""
 
-#: src/reclaim/gnunet-reclaim.c:846
+#: src/reclaim/gnunet-reclaim.c:848
 #, fuzzy
 msgid "The EGO to use"
 msgstr "消息尺寸"
 
-#: src/reclaim/gnunet-reclaim.c:852
+#: src/reclaim/gnunet-reclaim.c:854
 msgid "Specify the relying party for issue"
 msgstr ""
 
-#: src/reclaim/gnunet-reclaim.c:856
+#: src/reclaim/gnunet-reclaim.c:858
 msgid "List attributes for EGO"
 msgstr ""
 
-#: src/reclaim/gnunet-reclaim.c:860
-msgid "List attestations for EGO"
+#: src/reclaim/gnunet-reclaim.c:862
+msgid "List credentials for EGO"
 msgstr ""
 
-#: src/reclaim/gnunet-reclaim.c:866
-msgid "Attestation to use for attribute"
+#: src/reclaim/gnunet-reclaim.c:868
+msgid "Credential to use for attribute"
 msgstr ""
 
-#: src/reclaim/gnunet-reclaim.c:871
-msgid "Attestation name"
+#: src/reclaim/gnunet-reclaim.c:873
+msgid "Credential name"
 msgstr ""
 
-#: src/reclaim/gnunet-reclaim.c:877
+#: src/reclaim/gnunet-reclaim.c:879
 msgid "Issue a ticket for a set of attributes separated by comma"
 msgstr ""
 
-#: src/reclaim/gnunet-reclaim.c:882
+#: src/reclaim/gnunet-reclaim.c:884
 msgid "Consume a ticket"
 msgstr ""
 
-#: src/reclaim/gnunet-reclaim.c:887
+#: src/reclaim/gnunet-reclaim.c:889
 msgid "Revoke a ticket"
 msgstr ""
 
-#: src/reclaim/gnunet-reclaim.c:892
+#: src/reclaim/gnunet-reclaim.c:894
 msgid "Type of attribute"
 msgstr ""
 
-#: src/reclaim/gnunet-reclaim.c:896
+#: src/reclaim/gnunet-reclaim.c:899
+msgid "Type of credential"
+msgstr ""
+
+#: src/reclaim/gnunet-reclaim.c:903
 msgid "List tickets of ego"
 msgstr ""
 
-#: src/reclaim/gnunet-reclaim.c:902
+#: src/reclaim/gnunet-reclaim.c:909
 msgid "Expiration interval of the attribute"
 msgstr ""
 
-#: src/reclaim/gnunet-reclaim.c:910
+#: src/reclaim/gnunet-reclaim.c:917
 msgid "re:claimID command line tool"
 msgstr ""
 
-#: src/reclaim/plugin_rest_openid_connect.c:2481
+#: src/reclaim/plugin_rest_openid_connect.c:2618
 msgid "OpenID Connect REST API initialized\n"
 msgstr ""
 
-#: src/reclaim/plugin_rest_reclaim.c:1476
+#: src/reclaim/plugin_rest_reclaim.c:1502
 msgid "Identity Provider REST API initialized\n"
 msgstr ""
 
-#: src/reclaim/reclaim_api.c:540
+#: src/reclaim/reclaim_api.c:545
 #, fuzzy
 msgid "failed to store record\n"
 msgstr "运行 %s失败:%s %d\n"
@@ -5919,16 +5927,16 @@ msgstr "服务已删除。\n"
 msgid "Search string `%s' is too long!\n"
 msgstr "服务已删除。\n"
 
-#: src/rest/gnunet-rest-server.c:1051
+#: src/rest/gnunet-rest-server.c:1266
 #, fuzzy
 msgid "GNUnet REST server"
 msgstr "GNUnet 错误日志"
 
-#: src/rest/plugin_rest_config.c:402
+#: src/rest/plugin_rest_config.c:427
 msgid "CONFIG REST API initialized\n"
 msgstr ""
 
-#: src/rest/plugin_rest_copying.c:209
+#: src/rest/plugin_rest_copying.c:211
 msgid "COPYING REST API initialized\n"
 msgstr ""
 
@@ -6061,27 +6069,27 @@ msgstr ""
 msgid "# revocation messages received via set union"
 msgstr ""
 
-#: src/revocation/gnunet-service-revocation.c:470
+#: src/revocation/gnunet-service-revocation.c:469
 #, c-format
 msgid "Error computing revocation set union with %s\n"
 msgstr ""
 
-#: src/revocation/gnunet-service-revocation.c:474
+#: src/revocation/gnunet-service-revocation.c:473
 #, fuzzy
 msgid "# revocation set unions failed"
 msgstr ""
 "\n"
 "按任意键继续\n"
 
-#: src/revocation/gnunet-service-revocation.c:486
+#: src/revocation/gnunet-service-revocation.c:481
 msgid "# revocation set unions completed"
 msgstr ""
 
-#: src/revocation/gnunet-service-revocation.c:526
+#: src/revocation/gnunet-service-revocation.c:519
 msgid "SET service crashed, terminating revocation service\n"
 msgstr ""
 
-#: src/revocation/gnunet-service-revocation.c:881
+#: src/revocation/gnunet-service-revocation.c:871
 #, fuzzy
 msgid "Could not open revocation database file!"
 msgstr "无法连接到 %s:%u:%s\n"
@@ -6171,10 +6179,10 @@ msgstr ""
 msgid "Calculate the Vectorproduct with a GNUnet peer."
 msgstr ""
 
-#: src/scalarproduct/gnunet-service-scalarproduct_alice.c:1363
-#: src/scalarproduct/gnunet-service-scalarproduct_bob.c:1366
-#: src/scalarproduct/gnunet-service-scalarproduct-ecc_alice.c:1127
-#: src/scalarproduct/gnunet-service-scalarproduct-ecc_bob.c:1073
+#: src/scalarproduct/gnunet-service-scalarproduct_alice.c:1358
+#: src/scalarproduct/gnunet-service-scalarproduct_bob.c:1355
+#: src/scalarproduct/gnunet-service-scalarproduct-ecc_alice.c:1118
+#: src/scalarproduct/gnunet-service-scalarproduct-ecc_bob.c:1063
 #, fuzzy
 msgid "Connect to CADET failed\n"
 msgstr "“%s”已连接到“%s”。\n"
@@ -6199,53 +6207,64 @@ msgstr ""
 msgid "also profile decryption"
 msgstr ""
 
-#: src/set/gnunet-service-set.c:1916
+#: src/set/gnunet-service-set.c:1916 src/seti/gnunet-service-seti.c:2467
+#: src/setu/gnunet-service-setu.c:3635
 #, fuzzy
 msgid "Could not connect to CADET service\n"
 msgstr "无法连接到 %s:%u:%s\n"
 
 #: src/set/gnunet-set-ibf-profiler.c:268
+#: src/setu/gnunet-setu-ibf-profiler.c:268
 #, fuzzy
 msgid "number of element in set A-B"
 msgstr "迭代次数"
 
 #: src/set/gnunet-set-ibf-profiler.c:274
+#: src/setu/gnunet-setu-ibf-profiler.c:274
 #, fuzzy
 msgid "number of element in set B-A"
 msgstr "迭代次数"
 
 #: src/set/gnunet-set-ibf-profiler.c:281
+#: src/setu/gnunet-setu-ibf-profiler.c:281
 msgid "number of common elements in A and B"
 msgstr ""
 
 #: src/set/gnunet-set-ibf-profiler.c:287
+#: src/setu/gnunet-setu-ibf-profiler.c:287
 msgid "hash num"
 msgstr ""
 
 #: src/set/gnunet-set-ibf-profiler.c:293
+#: src/setu/gnunet-setu-ibf-profiler.c:293
 msgid "ibf size"
 msgstr ""
 
-#: src/set/gnunet-set-profiler.c:462
+#: src/set/gnunet-set-profiler.c:462 src/setu/gnunet-setu-profiler.c:453
 msgid "use byzantine mode"
 msgstr ""
 
-#: src/set/gnunet-set-profiler.c:468
+#: src/set/gnunet-set-profiler.c:468 src/setu/gnunet-setu-profiler.c:459
 msgid "force sending full set"
 msgstr ""
 
-#: src/set/gnunet-set-profiler.c:474
+#: src/set/gnunet-set-profiler.c:474 src/setu/gnunet-setu-profiler.c:465
 msgid "number delta operation"
 msgstr ""
 
-#: src/set/gnunet-set-profiler.c:486
+#: src/set/gnunet-set-profiler.c:486 src/setu/gnunet-setu-profiler.c:477
 msgid "operation to execute"
 msgstr ""
 
-#: src/set/gnunet-set-profiler.c:492
+#: src/set/gnunet-set-profiler.c:492 src/seti/gnunet-seti-profiler.c:462
+#: src/setu/gnunet-setu-profiler.c:483
 msgid "element size"
 msgstr ""
 
+#: src/seti/gnunet-seti-profiler.c:457
+msgid "return intersection instead of delta"
+msgstr ""
+
 #: src/sq/sq.c:54
 #, c-format
 msgid "Failure to bind %u-th SQL parameter\n"
@@ -6260,12 +6279,12 @@ msgstr ""
 msgid "Failed to reset sqlite statement with error: %s\n"
 msgstr "解析配置文件“%s”失败\n"
 
-#: src/statistics/gnunet-service-statistics.c:318
+#: src/statistics/gnunet-service-statistics.c:319
 #, c-format
 msgid "Wrote %llu bytes of statistics to `%s'\n"
 msgstr ""
 
-#: src/statistics/gnunet-service-statistics.c:983
+#: src/statistics/gnunet-service-statistics.c:984
 #, c-format
 msgid "Loading %llu bytes of statistics from `%s'\n"
 msgstr ""
@@ -6448,7 +6467,7 @@ msgid ""
 msgstr ""
 
 #: src/testbed/gnunet-daemon-testbed-underlay.c:234 src/testing/list-keys.c:47
-#: src/testing/testing.c:284 src/util/gnunet-ecc.c:318
+#: src/testing/testing.c:278 src/util/gnunet-ecc.c:318
 #, c-format
 msgid "Incorrect hostkey file format: %s\n"
 msgstr ""
@@ -6704,58 +6723,58 @@ msgstr ""
 msgid "list COUNT number of keys"
 msgstr ""
 
-#: src/testing/testing.c:267
+#: src/testing/testing.c:261
 #, c-format
 msgid "Hostkeys file not found: %s\n"
 msgstr ""
 
-#: src/testing/testing.c:721
+#: src/testing/testing.c:714
 #, c-format
 msgid "Key number %u does not exist\n"
 msgstr ""
 
-#: src/testing/testing.c:1195
+#: src/testing/testing.c:1188
 #, c-format
 msgid ""
 "You attempted to create a testbed with more than %u hosts.  Please "
 "precompute more hostkeys first.\n"
 msgstr ""
 
-#: src/testing/testing.c:1204
+#: src/testing/testing.c:1197
 #, fuzzy, c-format
 msgid "Failed to initialize hostkey for peer %u\n"
 msgstr "初始化“%s”服务失败。\n"
 
-#: src/testing/testing.c:1214
+#: src/testing/testing.c:1207
 msgid "PRIVATE_KEY option in PEER section missing in configuration\n"
 msgstr ""
 
-#: src/testing/testing.c:1227
+#: src/testing/testing.c:1220
 #, fuzzy
 msgid "Failed to create configuration for peer (not enough free ports?)\n"
 msgstr "解析配置文件“%s”失败\n"
 
-#: src/testing/testing.c:1243
+#: src/testing/testing.c:1236
 #, fuzzy, c-format
 msgid "Cannot open hostkey file `%s': %s\n"
 msgstr "找不到接口“%s”的一个 IP 地址。\n"
 
-#: src/testing/testing.c:1257
+#: src/testing/testing.c:1250
 #, fuzzy, c-format
 msgid "Failed to write hostkey file for peer %u: %s\n"
 msgstr "发送消息失败。\n"
 
-#: src/testing/testing.c:1285
+#: src/testing/testing.c:1278
 #, fuzzy, c-format
 msgid "Failed to write configuration file `%s' for peer %u: %s\n"
 msgstr "解析配置文件“%s”失败\n"
 
-#: src/testing/testing.c:1392
+#: src/testing/testing.c:1384
 #, fuzzy, c-format
 msgid "Failed to start `%s': %s\n"
 msgstr "运行 %s失败:%s %d\n"
 
-#: src/testing/testing.c:1691
+#: src/testing/testing.c:1683
 #, fuzzy, c-format
 msgid "Failed to load configuration from %s\n"
 msgstr "解析配置文件“%s”失败\n"
@@ -6834,40 +6853,40 @@ msgstr ""
 msgid "GNUnet topology control"
 msgstr ""
 
-#: src/transport/gnunet-communicator-tcp.c:2458
-#: src/transport/gnunet-communicator-udp.c:2825
-#: src/transport/gnunet-service-tng.c:10027
+#: src/transport/gnunet-communicator-tcp.c:3189
+#: src/transport/gnunet-communicator-udp.c:2826
+#: src/transport/gnunet-service-tng.c:10014
 #: src/transport/gnunet-service-transport.c:2624
 #, fuzzy
 msgid "Transport service is lacking key configuration settings. Exiting.\n"
 msgstr "立即保存配置?"
 
-#: src/transport/gnunet-communicator-tcp.c:2754
+#: src/transport/gnunet-communicator-tcp.c:3494
 msgid "GNUnet TCP communicator"
 msgstr ""
 
-#: src/transport/gnunet-communicator-udp.c:2897
+#: src/transport/gnunet-communicator-udp.c:2898
 msgid "GNUnet UDP communicator"
 msgstr ""
 
-#: src/transport/gnunet-communicator-unix.c:788
+#: src/transport/gnunet-communicator-unix.c:789
 #, fuzzy
 msgid ""
 "Maximum number of UNIX connections exceeded, dropping incoming message\n"
 msgstr "增加 TCP/IP 的最大连接数"
 
-#: src/transport/gnunet-communicator-unix.c:1015
+#: src/transport/gnunet-communicator-unix.c:1016
 #, fuzzy
 msgid "UNIX communicator is lacking key configuration settings. Exiting.\n"
 msgstr "立即保存配置?"
 
-#: src/transport/gnunet-communicator-unix.c:1060
+#: src/transport/gnunet-communicator-unix.c:1061
 #: src/transport/plugin_transport_unix.c:1383
 #, fuzzy, c-format
 msgid "Cannot create path to `%s'\n"
 msgstr "发送消息失败。\n"
 
-#: src/transport/gnunet-communicator-unix.c:1138
+#: src/transport/gnunet-communicator-unix.c:1139
 msgid "GNUnet UNIX domain socket communicator"
 msgstr ""
 
@@ -7915,7 +7934,7 @@ msgid "do daemonize (detach from terminal)"
 msgstr ""
 
 #: src/transport/tcp_service_legacy.c:1397
-#: src/transport/transport-testing2.c:1061 src/util/service.c:2072
+#: src/transport/transport-testing2.c:1116 src/util/service.c:2072
 #: src/util/service.c:2084
 #, fuzzy, c-format
 msgid "Malformed configuration file `%s', exit ...\n"
@@ -7958,7 +7977,7 @@ msgstr ""
 msgid "Invalid handle type while reading `%s'"
 msgstr "“%s”的参数无效。\n"
 
-#: src/util/bio.c:335 src/util/bio.c:838
+#: src/util/bio.c:335 src/util/bio.c:839
 msgid "string length"
 msgstr ""
 
@@ -7977,7 +7996,7 @@ msgstr ""
 msgid "String `%s' longer than allowed (%u > %u)"
 msgstr ""
 
-#: src/util/bio.c:398 src/util/bio.c:863 src/util/bio.c:880
+#: src/util/bio.c:398 src/util/bio.c:864 src/util/bio.c:881
 msgid "metadata length"
 msgstr ""
 
@@ -7991,25 +8010,25 @@ msgstr ""
 msgid "Failed to deserialize metadata `%s'"
 msgstr "发送消息失败。\n"
 
-#: src/util/bio.c:667
+#: src/util/bio.c:668
 msgid "Unable to flush buffer to file"
 msgstr ""
 
-#: src/util/bio.c:729 src/util/bio.c:750
+#: src/util/bio.c:730 src/util/bio.c:751
 #, fuzzy, c-format
 msgid "Error while writing `%s' to file: %s"
 msgstr "解析 dscl 输出时出错。\n"
 
-#: src/util/bio.c:731
+#: src/util/bio.c:732
 msgid "No associated file"
 msgstr ""
 
-#: src/util/bio.c:815
+#: src/util/bio.c:816
 #, fuzzy, c-format
 msgid "Invalid handle type while writing `%s'"
 msgstr "IP 格式无效:“%s”\n"
 
-#: src/util/bio.c:875
+#: src/util/bio.c:876
 #, fuzzy, c-format
 msgid "Failed to serialize metadata `%s'"
 msgstr "发送消息失败。\n"
@@ -8494,15 +8513,15 @@ msgstr ""
 msgid "No handler known for subsystem `%s'\n"
 msgstr ""
 
-#: src/util/gnunet-qr.c:358
+#: src/util/gnunet-qr.c:357
 msgid "use video-device DEVICE (default: /dev/video0"
 msgstr ""
 
-#: src/util/gnunet-qr.c:363
+#: src/util/gnunet-qr.c:362
 msgid "do not show preview windows"
 msgstr ""
 
-#: src/util/gnunet-qr.c:373
+#: src/util/gnunet-qr.c:372
 msgid "Scan a QR code using a video device and import the uri read"
 msgstr ""
 
@@ -8514,28 +8533,28 @@ msgstr ""
 msgid "Use build-in GNUnet stub resolver"
 msgstr ""
 
-#: src/util/gnunet-scrypt.c:222
+#: src/util/gnunet-scrypt.c:229
 #, c-format
 msgid "Loading hostkey from `%s' failed.\n"
 msgstr ""
 
-#: src/util/gnunet-scrypt.c:288
+#: src/util/gnunet-scrypt.c:295
 msgid "number of bits to require for the proof of work"
 msgstr ""
 
-#: src/util/gnunet-scrypt.c:294
+#: src/util/gnunet-scrypt.c:301
 msgid "file with private key, otherwise default is used"
 msgstr ""
 
-#: src/util/gnunet-scrypt.c:300
+#: src/util/gnunet-scrypt.c:307
 msgid "file with proof of work, otherwise default is used"
 msgstr ""
 
-#: src/util/gnunet-scrypt.c:306
+#: src/util/gnunet-scrypt.c:313
 msgid "time to wait between calculations"
 msgstr ""
 
-#: src/util/gnunet-scrypt.c:319
+#: src/util/gnunet-scrypt.c:326
 #, fuzzy
 msgid "Manipulate GNUnet proof of work files"
 msgstr "更改配置文件中的一个值"
@@ -8549,7 +8568,7 @@ msgstr ""
 msgid "No URI specified on command line\n"
 msgstr ""
 
-#: src/util/gnunet-uri.c:179
+#: src/util/gnunet-uri.c:178
 msgid "Perform default-actions for GNUnet URIs"
 msgstr ""
 
@@ -8563,7 +8582,7 @@ msgstr "创建用户出错"
 msgid "Failed to parse inbound message from helper `%s'\n"
 msgstr "打开日志文件“%s”失败:%s\n"
 
-#: src/util/helper.c:600
+#: src/util/helper.c:602
 #, fuzzy, c-format
 msgid "Error writing to `%s': %s\n"
 msgstr "创建用户出错"
@@ -8691,118 +8710,118 @@ msgstr ""
 msgid "Attempting to proxy service `%s' to invalid port %d or hostname.\n"
 msgstr ""
 
-#: src/util/strings.c:178
+#: src/util/strings.c:179
 msgid "b"
 msgstr "b"
 
-#: src/util/strings.c:502
+#: src/util/strings.c:503
 #, c-format
 msgid "Character sets requested were `%s'->`%s'\n"
 msgstr ""
 
-#: src/util/strings.c:636
+#: src/util/strings.c:637
 msgid "Failed to expand `$HOME': environment variable `HOME' not set"
 msgstr "扩展“$HOME”失败:没有设置环境变量“HOME”"
 
-#: src/util/strings.c:705
+#: src/util/strings.c:706
 msgid "µs"
 msgstr ""
 
-#: src/util/strings.c:709
+#: src/util/strings.c:710
 msgid "forever"
 msgstr ""
 
-#: src/util/strings.c:711
+#: src/util/strings.c:712
 msgid "0 ms"
 msgstr ""
 
-#: src/util/strings.c:715
+#: src/util/strings.c:716
 msgid "ms"
 msgstr "毫秒"
 
-#: src/util/strings.c:719
+#: src/util/strings.c:720
 msgid "s"
 msgstr "秒"
 
-#: src/util/strings.c:723
+#: src/util/strings.c:724
 msgid "m"
 msgstr "分"
 
-#: src/util/strings.c:727
+#: src/util/strings.c:728
 msgid "h"
 msgstr "æ—¶"
 
-#: src/util/strings.c:733
+#: src/util/strings.c:734
 #, fuzzy
 msgid "day"
 msgstr " 天"
 
-#: src/util/strings.c:735
+#: src/util/strings.c:736
 #, fuzzy
 msgid "days"
 msgstr " 天"
 
-#: src/util/strings.c:763
+#: src/util/strings.c:764
 msgid "end of time"
 msgstr ""
 
-#: src/util/strings.c:1239
+#: src/util/strings.c:1240
 msgid "IPv6 address did not start with `['\n"
 msgstr ""
 
-#: src/util/strings.c:1247
+#: src/util/strings.c:1248
 msgid "IPv6 address did contain ':' to separate port number\n"
 msgstr ""
 
-#: src/util/strings.c:1254
+#: src/util/strings.c:1255
 msgid "IPv6 address did contain ']' before ':' to separate port number\n"
 msgstr ""
 
-#: src/util/strings.c:1262
+#: src/util/strings.c:1263
 msgid "IPv6 address did contain a valid port number after the last ':'\n"
 msgstr ""
 
-#: src/util/strings.c:1271
+#: src/util/strings.c:1272
 #, fuzzy, c-format
 msgid "Invalid IPv6 address `%s': %s\n"
 msgstr "无效的进程优先级“%s”\n"
 
-#: src/util/strings.c:1498 src/util/strings.c:1509
+#: src/util/strings.c:1499 src/util/strings.c:1510
 msgid "Port not in range\n"
 msgstr ""
 
-#: src/util/strings.c:1518
+#: src/util/strings.c:1519
 #, fuzzy, c-format
 msgid "Malformed port policy `%s'\n"
 msgstr "解析配置文件“%s”失败\n"
 
-#: src/util/strings.c:1601 src/util/strings.c:1630 src/util/strings.c:1677
-#: src/util/strings.c:1697
+#: src/util/strings.c:1602 src/util/strings.c:1631 src/util/strings.c:1678
+#: src/util/strings.c:1698
 #, c-format
 msgid "Invalid format for IP: `%s'\n"
 msgstr "IP 格式无效:“%s”\n"
 
-#: src/util/strings.c:1655
+#: src/util/strings.c:1656
 #, c-format
 msgid "Invalid network notation ('/%d' is not legal in IPv4 CIDR)."
 msgstr "网络表示法无效(“/%d” 在 IPv4 CIDR 中是非法的)。"
 
-#: src/util/strings.c:1706
+#: src/util/strings.c:1707
 #, fuzzy, c-format
 msgid "Invalid format: `%s'\n"
 msgstr "IP 格式无效:“%s”\n"
 
-#: src/util/strings.c:1759
+#: src/util/strings.c:1760
 #, c-format
 msgid "Invalid network notation (does not end with ';': `%s')\n"
 msgstr "无效的网络表示法(没有以“;”结尾:“%s”)\n"
 
-#: src/util/strings.c:1809
+#: src/util/strings.c:1810
 #, c-format
 msgid "Wrong format `%s' for netmask\n"
 msgstr "网络掩码的格式“%s”错误\n"
 
-#: src/util/strings.c:1840
+#: src/util/strings.c:1841
 #, c-format
 msgid "Wrong format `%s' for network\n"
 msgstr "网络的格式“%s”错误\n"
diff --git a/src/Makefile.am b/src/Makefile.am
index 446b1aa2a35e27ca99507c15029c9b92609cdc57..234a633892fcf93cebebbb69a7f7fc81e5b9992f 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -89,6 +89,8 @@ SUBDIRS = \
   namestore \
   cadet \
   set \
+  seti \
+  setu \
   consensus \
   scalarproduct \
   revocation \
diff --git a/src/abd/.gitignore b/src/abd/.gitignore
new file mode 100644
index 0000000000000000000000000000000000000000..ee1eb783774f4997638e8efb0a3eb5394357260d
--- /dev/null
+++ b/src/abd/.gitignore
@@ -0,0 +1,2 @@
+gnunet-abd
+gnunet-service-abd
diff --git a/src/abd/gnunet-abd.c b/src/abd/gnunet-abd.c
index 963d9207a4ac58c6e8936cf92268cec17701aacc..ff7dd09c569b9d79b24ba45307d4d65d287785ca 100644
--- a/src/abd/gnunet-abd.c
+++ b/src/abd/gnunet-abd.c
@@ -513,8 +513,8 @@ get_existing_record (void *cls,
                      const struct GNUNET_GNSRECORD_Data *rd)
 {
   struct GNUNET_GNSRECORD_Data *rde;
-  struct GNUNET_GNSRECORD_Data* rdn =
-    GNUNET_malloc(sizeof(*rdn)*(rd_count + 1));
+  struct GNUNET_GNSRECORD_Data*rdn =
+    GNUNET_malloc (sizeof(*rdn) * (rd_count + 1));
 
   memset (rdn, 0, sizeof (struct GNUNET_GNSRECORD_Data));
   GNUNET_memcpy (&rdn[1], rd,
@@ -541,7 +541,7 @@ get_existing_record (void *cls,
                                            rde,
                                            &add_continuation,
                                            &add_qe);
-  GNUNET_free(rdn);
+  GNUNET_free (rdn);
   return;
 }
 
@@ -604,13 +604,18 @@ store_cb (void *cls, struct GNUNET_IDENTITY_Ego *ego)
     if (GNUNET_OK !=
         GNUNET_GNSRECORD_string_to_value (type, subject, &data, &data_size))
     {
-      if(typestring == NULL) {
-        fputs("No value for unknown record type\n", stderr);
-      } else if(subject == NULL) {
-        fprintf(stderr,
-                "No value for record type`%s'\n",
-                typestring);
-      } else {
+      if (typestring == NULL)
+      {
+        fputs ("No value for unknown record type\n", stderr);
+      }
+      else if (subject == NULL)
+      {
+        fprintf (stderr,
+                 "No value for record type`%s'\n",
+                 typestring);
+      }
+      else
+      {
         fprintf (stderr,
                  "Value `%s' invalid for record type `%s'\n",
                  subject,
@@ -927,8 +932,8 @@ run (void *cls,
     int i;
     while (NULL != (tok = strtok (NULL, ",")))
       count++;
-    struct GNUNET_ABD_Delegate* delegates =
-      GNUNET_malloc(sizeof(*delegates)*count);
+    struct GNUNET_ABD_Delegate*delegates =
+      GNUNET_malloc (sizeof(*delegates) * count);
     struct GNUNET_ABD_Delegate *dele;
     GNUNET_free (tmp);
     tmp = GNUNET_strdup (subject_delegate);
@@ -961,7 +966,7 @@ run (void *cls,
       delegates[i].issuer_attribute = NULL;
     }
     GNUNET_free (tmp);
-    GNUNET_free(delegates);
+    GNUNET_free (delegates);
   }
   else
   {
diff --git a/src/abd/plugin_gnsrecord_abd.c b/src/abd/plugin_gnsrecord_abd.c
index 850fa9a45ed46e7e403fd36843eecd327286cb95..272872e247b61c3836bcc9e41d238a11549e5aa3 100644
--- a/src/abd/plugin_gnsrecord_abd.c
+++ b/src/abd/plugin_gnsrecord_abd.c
@@ -235,7 +235,8 @@ abd_string_to_value (void *cls,
                                            (char *) &sets[1]);
       for (i = 0; i < entries; i++)
       {
-        if (0 != set[i].subject_attribute_len) {
+        if (0 != set[i].subject_attribute_len)
+        {
           GNUNET_free_nz ((char *) set[i].subject_attribute);
           set[i].subject_attribute = NULL;
         }
diff --git a/src/abd/test_abd_bi_and.sh b/src/abd/test_abd_bi_and.sh
new file mode 100755
index 0000000000000000000000000000000000000000..b32313636cc4193689826f39442ff11f4d65d422
--- /dev/null
+++ b/src/abd/test_abd_bi_and.sh
@@ -0,0 +1,98 @@
+#!/usr/bin/env bash
+trap "gnunet-arm -e -c test_abd_lookup.conf" SIGINT
+
+LOCATION=$(which gnunet-config)
+if [ -z $LOCATION ]
+then
+  LOCATION="gnunet-config"
+fi
+$LOCATION --version 1> /dev/null
+if test $? != 0
+then
+	echo "GNUnet command line tools cannot be found, check environmental variables PATH and GNUNET_PREFIX"
+	exit 77
+fi
+
+rm -rf `gnunet-config -c test_abd_lookup.conf -s PATHS -o GNUNET_HOME -f`
+
+
+
+
+which timeout > /dev/null 2>&1 && DO_TIMEOUT="timeout 10"
+gnunet-arm -s -c test_abd_lookup.conf
+
+gnunet-identity -C a -c test_abd_lookup.conf
+gnunet-identity -C b -c test_abd_lookup.conf
+gnunet-identity -C c -c test_abd_lookup.conf
+gnunet-identity -C d -c test_abd_lookup.conf
+gnunet-identity -C e -c test_abd_lookup.conf
+gnunet-identity -C f -c test_abd_lookup.conf
+gnunet-identity -C g -c test_abd_lookup.conf
+gnunet-identity -C h -c test_abd_lookup.conf
+AKEY=$(gnunet-identity -d -c test_abd_lookup.conf | grep a | awk '{print $3}')
+BKEY=$(gnunet-identity -d -c test_abd_lookup.conf | grep b | awk '{print $3}')
+CKEY=$(gnunet-identity -d -c test_abd_lookup.conf | grep c | awk '{print $3}')
+DKEY=$(gnunet-identity -d -c test_abd_lookup.conf | grep d | awk '{print $3}')
+EKEY=$(gnunet-identity -d -c test_abd_lookup.conf | grep e | awk '{print $3}')
+FKEY=$(gnunet-identity -d -c test_abd_lookup.conf | grep f | awk '{print $3}')
+GKEY=$(gnunet-identity -d -c test_abd_lookup.conf | grep g | awk '{print $3}')
+HKEY=$(gnunet-identity -d -c test_abd_lookup.conf | grep h | awk '{print $3}')
+gnunet-identity -d
+
+#   (1) (A.a) <- B.b
+#   (2) (B.b) <- C.c AND G.g
+#   (3) C.c <- (D.D)
+#   (4) D.d <- (E.e)
+#   (5) E.e <- (F) priv
+#   (6) (G.g) <- H.h 
+#   (7) H.h <- (F) priv
+
+# BIDIRECTIONAL
+gnunet-abd --createIssuerSide --ego=a --attribute="a" --subject="$BKEY b" --ttl=5m -c test_abd_lookup.conf
+gnunet-namestore -D -z a
+gnunet-abd --createIssuerSide --ego=b --attribute="b" --subject="$CKEY c, $GKEY g" --ttl=5m -c test_abd_lookup.conf
+gnunet-namestore -D -z b
+gnunet-abd --createIssuerSide --ego=g --attribute="g" --subject="$HKEY h" --ttl=5m -c test_abd_lookup.conf
+gnunet-namestore -D -z b
+
+SIGNED=`$DO_TIMEOUT gnunet-abd --signSubjectSide --ego=c --attribute="c" --subject="$DKEY d" --ttl="2019-12-12 10:00:00"`
+gnunet-abd --createSubjectSide --ego=d --import="$SIGNED"
+gnunet-namestore -D -z d
+SIGNED=`$DO_TIMEOUT gnunet-abd --signSubjectSide --ego=d --attribute="d" --subject="$EKEY e" --ttl="2019-12-12 10:00:00"`
+gnunet-abd --createSubjectSide --ego=e --import="$SIGNED"
+gnunet-namestore -D -z e
+SIGNED=`$DO_TIMEOUT gnunet-abd --signSubjectSide --ego=e --attribute="e" --subject="$FKEY" --ttl="2019-12-12 10:00:00"`
+gnunet-abd --createSubjectSide --ego=f --import="$SIGNED" --private
+gnunet-namestore -D -z f
+SIGNED=`$DO_TIMEOUT gnunet-abd --signSubjectSide --ego=h --attribute="h" --subject="$FKEY" --ttl="2019-12-12 10:00:00"`
+gnunet-abd --createSubjectSide --ego=f --import="$SIGNED" --private
+gnunet-namestore -D -z h
+
+# Starting to resolve
+echo "+++ Starting to Resolve +++"
+
+DELS=`$DO_TIMEOUT gnunet-abd --collect --issuer=$AKEY --attribute="a" --ego=f --forward --backward -c test_abd_lookup.conf | paste -d, -s - -`
+echo $DELS
+echo gnunet-abd --verify --issuer=$AKEY --attribute="a" --subject=$FKEY --delegate=\'$DELS\' --forward --backward -c test_abd_lookup.conf
+gnunet-abd --verify --issuer=$AKEY --attribute="a" --subject=$FKEY --delegate="$DELS" --forward --backward -c test_abd_lookup.conf
+
+RES=$?
+
+# Cleanup properly
+gnunet-namestore -z a -d -n "a" -t ATTR -c test_abd_lookup.conf
+gnunet-namestore -z b -d -n "b" -t ATTR -c test_abd_lookup.conf
+gnunet-namestore -z g -d -n "g" -t ATTR -c test_abd_lookup.conf
+gnunet-namestore -z d -d -n "@" -t DEL -c test_abd_lookup.conf
+gnunet-namestore -z e -d -n "@" -t DEL -c test_abd_lookup.conf
+gnunet-namestore -z f -d -n "@" -t DEL -c test_abd_lookup.conf
+
+gnunet-arm -e -c test_abd_lookup.conf
+
+if [ "$RES" == 0 ]
+then
+  exit 0
+else
+  echo "FAIL: Failed to verify credential."
+  exit 1
+fi
+
diff --git a/src/abd/test_abd_bi_and2.sh b/src/abd/test_abd_bi_and2.sh
new file mode 100755
index 0000000000000000000000000000000000000000..8d1601ef4004386fbf424fc52412587248dfe7fa
--- /dev/null
+++ b/src/abd/test_abd_bi_and2.sh
@@ -0,0 +1,94 @@
+#!/usr/bin/env bash
+trap "gnunet-arm -e -c test_abd_lookup.conf" SIGINT
+
+LOCATION=$(which gnunet-config)
+if [ -z $LOCATION ]
+then
+  LOCATION="gnunet-config"
+fi
+$LOCATION --version 1> /dev/null
+if test $? != 0
+then
+	echo "GNUnet command line tools cannot be found, check environmental variables PATH and GNUNET_PREFIX"
+	exit 77
+fi
+
+rm -rf `gnunet-config -c test_abd_lookup.conf -s PATHS -o GNUNET_HOME -f`
+
+
+
+
+which timeout > /dev/null 2>&1 && DO_TIMEOUT="timeout 10"
+gnunet-arm -s -c test_abd_lookup.conf
+
+gnunet-identity -C a -c test_abd_lookup.conf
+gnunet-identity -C b -c test_abd_lookup.conf
+gnunet-identity -C c -c test_abd_lookup.conf
+gnunet-identity -C d -c test_abd_lookup.conf
+gnunet-identity -C e -c test_abd_lookup.conf
+gnunet-identity -C f -c test_abd_lookup.conf
+gnunet-identity -C g -c test_abd_lookup.conf
+gnunet-identity -C h -c test_abd_lookup.conf
+AKEY=$(gnunet-identity -d -c test_abd_lookup.conf | grep a | awk '{print $3}')
+BKEY=$(gnunet-identity -d -c test_abd_lookup.conf | grep b | awk '{print $3}')
+CKEY=$(gnunet-identity -d -c test_abd_lookup.conf | grep c | awk '{print $3}')
+DKEY=$(gnunet-identity -d -c test_abd_lookup.conf | grep d | awk '{print $3}')
+EKEY=$(gnunet-identity -d -c test_abd_lookup.conf | grep e | awk '{print $3}')
+FKEY=$(gnunet-identity -d -c test_abd_lookup.conf | grep f | awk '{print $3}')
+GKEY=$(gnunet-identity -d -c test_abd_lookup.conf | grep g | awk '{print $3}')
+HKEY=$(gnunet-identity -d -c test_abd_lookup.conf | grep h | awk '{print $3}')
+gnunet-identity -d
+
+#   (1) (A.a) <- B.b
+#   (2) (B.b) <- C.c AND G.g
+#   (3) C.c <- (D.D)
+#   (4) D.d <- (E.e)
+#   (5) E.e <- (F) priv
+#   (6) G.g <- (F) priv
+
+# BIDIRECTIONAL
+gnunet-abd --createIssuerSide --ego=a --attribute="a" --subject="$BKEY b" --ttl=5m -c test_abd_lookup.conf
+gnunet-namestore -D -z a
+gnunet-abd --createIssuerSide --ego=b --attribute="b" --subject="$CKEY c, $GKEY g" --ttl=5m -c test_abd_lookup.conf
+gnunet-namestore -D -z b
+
+SIGNED=`$DO_TIMEOUT gnunet-abd --signSubjectSide --ego=c --attribute="c" --subject="$DKEY d" --ttl="2019-12-12 10:00:00"`
+gnunet-abd --createSubjectSide --ego=d --import="$SIGNED"
+gnunet-namestore -D -z d
+SIGNED=`$DO_TIMEOUT gnunet-abd --signSubjectSide --ego=d --attribute="d" --subject="$EKEY e" --ttl="2019-12-12 10:00:00"`
+gnunet-abd --createSubjectSide --ego=e --import="$SIGNED"
+gnunet-namestore -D -z e
+SIGNED=`$DO_TIMEOUT gnunet-abd --signSubjectSide --ego=e --attribute="e" --subject="$FKEY" --ttl="2019-12-12 10:00:00"`
+gnunet-abd --createSubjectSide --ego=f --import="$SIGNED" --private
+gnunet-namestore -D -z f
+SIGNED=`$DO_TIMEOUT gnunet-abd --signSubjectSide --ego=g --attribute="g" --subject="$FKEY" --ttl="2019-12-12 10:00:00"`
+gnunet-abd --createSubjectSide --ego=f --import="$SIGNED" --private
+gnunet-namestore -D -z h
+
+# Starting to resolve
+echo "+++ Starting to Resolve +++"
+
+DELS=`$DO_TIMEOUT gnunet-abd --collect --issuer=$AKEY --attribute="a" --ego=f -c test_abd_lookup.conf | paste -d, -s - -`
+echo $DELS
+echo gnunet-abd --verify --issuer=$AKEY --attribute="a" --subject=$FKEY --delegate=\'$DELS\' -c test_abd_lookup.conf
+gnunet-abd --verify --issuer=$AKEY --attribute="a" --subject=$FKEY --delegate="$DELS" -c test_abd_lookup.conf
+
+RES=$?
+
+# Cleanup properly
+gnunet-namestore -z a -d -n "a" -t ATTR -c test_abd_lookup.conf
+gnunet-namestore -z b -d -n "b" -t ATTR -c test_abd_lookup.conf
+gnunet-namestore -z d -d -n "@" -t DEL -c test_abd_lookup.conf
+gnunet-namestore -z e -d -n "@" -t DEL -c test_abd_lookup.conf
+gnunet-namestore -z f -d -n "@" -t DEL -c test_abd_lookup.conf
+
+gnunet-arm -e -c test_abd_lookup.conf
+
+if [ "$RES" == 0 ]
+then
+  exit 0
+else
+  echo "FAIL: Failed to verify credential."
+  exit 1
+fi
+
diff --git a/src/abd/test_abd_bi_and3.sh b/src/abd/test_abd_bi_and3.sh
new file mode 100755
index 0000000000000000000000000000000000000000..cde2a020bb0e2a4f0e70059138681abf6d4f0320
--- /dev/null
+++ b/src/abd/test_abd_bi_and3.sh
@@ -0,0 +1,96 @@
+#!/usr/bin/env bash
+trap "gnunet-arm -e -c test_abd_lookup.conf" SIGINT
+
+LOCATION=$(which gnunet-config)
+if [ -z $LOCATION ]
+then
+  LOCATION="gnunet-config"
+fi
+$LOCATION --version 1> /dev/null
+if test $? != 0
+then
+	echo "GNUnet command line tools cannot be found, check environmental variables PATH and GNUNET_PREFIX"
+	exit 77
+fi
+
+rm -rf `gnunet-config -c test_abd_lookup.conf -s PATHS -o GNUNET_HOME -f`
+
+
+
+which timeout > /dev/null 2>&1 && DO_TIMEOUT="timeout 10"
+gnunet-arm -s -c test_abd_lookup.conf
+
+gnunet-identity -C a -c test_abd_lookup.conf
+gnunet-identity -C b -c test_abd_lookup.conf
+gnunet-identity -C c -c test_abd_lookup.conf
+gnunet-identity -C d -c test_abd_lookup.conf
+gnunet-identity -C e -c test_abd_lookup.conf
+gnunet-identity -C f -c test_abd_lookup.conf
+gnunet-identity -C g -c test_abd_lookup.conf
+gnunet-identity -C h -c test_abd_lookup.conf
+AKEY=$(gnunet-identity -d -c test_abd_lookup.conf | grep a | awk '{print $3}')
+BKEY=$(gnunet-identity -d -c test_abd_lookup.conf | grep b | awk '{print $3}')
+CKEY=$(gnunet-identity -d -c test_abd_lookup.conf | grep c | awk '{print $3}')
+DKEY=$(gnunet-identity -d -c test_abd_lookup.conf | grep d | awk '{print $3}')
+EKEY=$(gnunet-identity -d -c test_abd_lookup.conf | grep e | awk '{print $3}')
+FKEY=$(gnunet-identity -d -c test_abd_lookup.conf | grep f | awk '{print $3}')
+GKEY=$(gnunet-identity -d -c test_abd_lookup.conf | grep g | awk '{print $3}')
+HKEY=$(gnunet-identity -d -c test_abd_lookup.conf | grep h | awk '{print $3}')
+gnunet-identity -d
+
+#   (1) (A.a) <- B.b
+#   (2) (B.b) <- C.c AND G.g
+#   (3) C.c <- (D.d)
+#   (4) D.d <- (E.e)
+#   (5) E.e <- (F) priv
+#   (6) G.g <- (H.h)
+#   (7) H.h <- (F) priv
+
+# BIDIRECTIONAL
+gnunet-abd --createIssuerSide --ego=a --attribute="a" --subject="$BKEY b" --ttl=5m -c test_abd_lookup.conf
+gnunet-namestore -D -z a
+gnunet-abd --createIssuerSide --ego=b --attribute="b" --subject="$CKEY c, $GKEY g" --ttl=5m -c test_abd_lookup.conf
+gnunet-namestore -D -z b
+
+SIGNED=`$DO_TIMEOUT gnunet-abd --signSubjectSide --ego=c --attribute="c" --subject="$DKEY d" --ttl="2019-12-12 10:00:00"`
+gnunet-abd --createSubjectSide --ego=d --import="$SIGNED"
+gnunet-namestore -D -z d
+SIGNED=`$DO_TIMEOUT gnunet-abd --signSubjectSide --ego=d --attribute="d" --subject="$EKEY e" --ttl="2019-12-12 10:00:00"`
+gnunet-abd --createSubjectSide --ego=e --import="$SIGNED"
+gnunet-namestore -D -z e
+SIGNED=`$DO_TIMEOUT gnunet-abd --signSubjectSide --ego=g --attribute="g" --subject="$HKEY h" --ttl="2019-12-12 10:00:00"`
+gnunet-abd --createSubjectSide --ego=h --import="$SIGNED"
+gnunet-namestore -D -z h
+SIGNED=`$DO_TIMEOUT gnunet-abd --signSubjectSide --ego=e --attribute="e" --subject="$FKEY" --ttl="2019-12-12 10:00:00"`
+gnunet-abd --createSubjectSide --ego=f --import="$SIGNED" --private
+SIGNED=`$DO_TIMEOUT gnunet-abd --signSubjectSide --ego=h --attribute="h" --subject="$FKEY" --ttl="2019-12-12 10:00:00"`
+gnunet-abd --createSubjectSide --ego=f --import="$SIGNED" --private
+gnunet-namestore -D -z f
+
+# Starting to resolve
+echo "+++ Starting to Resolve +++"
+
+DELS=`$DO_TIMEOUT gnunet-abd --collect --issuer=$AKEY --attribute="a" --ego=f -c test_abd_lookup.conf | paste -d, -s - -`
+echo $DELS
+echo gnunet-abd --verify --issuer=$AKEY --attribute="a" --subject=$FKEY --delegate=\'$DELS\' -c test_abd_lookup.conf
+gnunet-abd --verify --issuer=$AKEY --attribute="a" --subject=$FKEY --delegate="$DELS" -c test_abd_lookup.conf
+
+RES=$?
+
+# Cleanup properly
+gnunet-namestore -z a -d -n "a" -t ATTR -c test_abd_lookup.conf
+gnunet-namestore -z b -d -n "b" -t ATTR -c test_abd_lookup.conf
+gnunet-namestore -z d -d -n "@" -t DEL -c test_abd_lookup.conf
+gnunet-namestore -z e -d -n "@" -t DEL -c test_abd_lookup.conf
+gnunet-namestore -z f -d -n "@" -t DEL -c test_abd_lookup.conf
+gnunet-namestore -z h -d -n "@" -t DEL -c test_abd_lookup.conf
+
+gnunet-arm -e -c test_abd_lookup.conf
+
+if [ "$RES" == 0 ]
+then
+  exit 0
+else
+  echo "FAIL: Failed to verify credential."
+  exit 1
+fi
diff --git a/src/abd/test_abd_bi_and4.sh b/src/abd/test_abd_bi_and4.sh
new file mode 100755
index 0000000000000000000000000000000000000000..e8cd6efd655a330aa9ea4b2b310797c09c9b120f
--- /dev/null
+++ b/src/abd/test_abd_bi_and4.sh
@@ -0,0 +1,83 @@
+#!/usr/bin/env bash
+trap "gnunet-arm -e -c test_abd_lookup.conf" SIGINT
+
+LOCATION=$(which gnunet-config)
+if [ -z $LOCATION ]
+then
+  LOCATION="gnunet-config"
+fi
+$LOCATION --version 1> /dev/null
+if test $? != 0
+then
+	echo "GNUnet command line tools cannot be found, check environmental variables PATH and GNUNET_PREFIX"
+	exit 77
+fi
+
+rm -rf `gnunet-config -c test_abd_lookup.conf -s PATHS -o GNUNET_HOME -f`
+
+
+
+
+which timeout > /dev/null 2>&1 && DO_TIMEOUT="timeout 10"
+gnunet-arm -s -c test_abd_lookup.conf
+
+gnunet-identity -C a -c test_abd_lookup.conf
+gnunet-identity -C b -c test_abd_lookup.conf
+gnunet-identity -C c -c test_abd_lookup.conf
+gnunet-identity -C d -c test_abd_lookup.conf
+gnunet-identity -C e -c test_abd_lookup.conf
+gnunet-identity -C f -c test_abd_lookup.conf
+gnunet-identity -C g -c test_abd_lookup.conf
+gnunet-identity -C h -c test_abd_lookup.conf
+AKEY=$(gnunet-identity -d -c test_abd_lookup.conf | grep a | awk '{print $3}')
+BKEY=$(gnunet-identity -d -c test_abd_lookup.conf | grep b | awk '{print $3}')
+CKEY=$(gnunet-identity -d -c test_abd_lookup.conf | grep c | awk '{print $3}')
+DKEY=$(gnunet-identity -d -c test_abd_lookup.conf | grep d | awk '{print $3}')
+EKEY=$(gnunet-identity -d -c test_abd_lookup.conf | grep e | awk '{print $3}')
+FKEY=$(gnunet-identity -d -c test_abd_lookup.conf | grep f | awk '{print $3}')
+GKEY=$(gnunet-identity -d -c test_abd_lookup.conf | grep g | awk '{print $3}')
+HKEY=$(gnunet-identity -d -c test_abd_lookup.conf | grep h | awk '{print $3}')
+gnunet-identity -d
+
+#   (1) (A.a) <- B.b
+#   (2) (B.b) <- C.c AND G.g
+#   (3) C.c <- (F) priv
+#   (4) G.g <- (F) priv
+
+# BIDIRECTIONAL
+gnunet-abd --createIssuerSide --ego=a --attribute="a" --subject="$BKEY b" --ttl=5m -c test_abd_lookup.conf
+gnunet-namestore -D -z a
+gnunet-abd --createIssuerSide --ego=b --attribute="b" --subject="$CKEY c, $GKEY g" --ttl=5m -c test_abd_lookup.conf
+gnunet-namestore -D -z b
+
+SIGNED=`$DO_TIMEOUT gnunet-abd --signSubjectSide --ego=g --attribute="g" --subject="$FKEY" --ttl="2019-12-12 10:00:00"`
+gnunet-abd --createSubjectSide --ego=f --import="$SIGNED" --private
+SIGNED=`$DO_TIMEOUT gnunet-abd --signSubjectSide --ego=c --attribute="c" --subject="$FKEY" --ttl="2019-12-12 10:00:00"`
+gnunet-abd --createSubjectSide --ego=f --import="$SIGNED" --private
+gnunet-namestore -D -z f
+
+# Starting to resolve
+echo "+++ Starting to Resolve +++"
+
+DELS=`$DO_TIMEOUT gnunet-abd --collect --issuer=$AKEY --attribute="a" --ego=f --backward -c test_abd_lookup.conf | paste -d, -s - -`
+echo $DELS
+echo gnunet-abd --verify --issuer=$AKEY --attribute="a" --subject=$FKEY --delegate=\'$DELS\'  --backward -c test_abd_lookup.conf
+gnunet-abd --verify --issuer=$AKEY --attribute="a" --subject=$FKEY --delegate="$DELS"  --backward -c test_abd_lookup.conf
+
+RES=$?
+
+# Cleanup properly
+gnunet-namestore -z a -d -n "a" -t ATTR -c test_abd_lookup.conf
+gnunet-namestore -z b -d -n "b" -t ATTR -c test_abd_lookup.conf
+gnunet-namestore -z f -d -n "@" -t DEL -c test_abd_lookup.conf
+
+gnunet-arm -e -c test_abd_lookup.conf
+
+if [ "$RES" == 0 ]
+then
+  exit 0
+else
+  echo "FAIL: Failed to verify credential."
+  exit 1
+fi
+
diff --git a/src/abd/test_abd_bi_bw.sh b/src/abd/test_abd_bi_bw.sh
new file mode 100755
index 0000000000000000000000000000000000000000..6b0e5172211114e036e4ab9b9d555832eb9cb1cf
--- /dev/null
+++ b/src/abd/test_abd_bi_bw.sh
@@ -0,0 +1,87 @@
+#!/usr/bin/env bash
+trap "gnunet-arm -e -c test_abd_lookup.conf" SIGINT
+
+LOCATION=$(which gnunet-config)
+if [ -z $LOCATION ]
+then
+  LOCATION="gnunet-config"
+fi
+$LOCATION --version 1> /dev/null
+if test $? != 0
+then
+	echo "GNUnet command line tools cannot be found, check environmental variables PATH and GNUNET_PREFIX"
+	exit 77
+fi
+
+rm -rf `gnunet-config -c test_abd_lookup.conf -s PATHS -o GNUNET_HOME -f`
+
+
+
+
+which timeout > /dev/null 2>&1 && DO_TIMEOUT="timeout 10"
+gnunet-arm -s -c test_abd_lookup.conf
+
+gnunet-identity -C a -c test_abd_lookup.conf
+gnunet-identity -C b -c test_abd_lookup.conf
+gnunet-identity -C c -c test_abd_lookup.conf
+gnunet-identity -C d -c test_abd_lookup.conf
+gnunet-identity -C e -c test_abd_lookup.conf
+gnunet-identity -C f -c test_abd_lookup.conf
+gnunet-identity -C g -c test_abd_lookup.conf
+AKEY=$(gnunet-identity -d -c test_abd_lookup.conf | grep a | awk '{print $3}')
+BKEY=$(gnunet-identity -d -c test_abd_lookup.conf | grep b | awk '{print $3}')
+CKEY=$(gnunet-identity -d -c test_abd_lookup.conf | grep c | awk '{print $3}')
+DKEY=$(gnunet-identity -d -c test_abd_lookup.conf | grep d | awk '{print $3}')
+EKEY=$(gnunet-identity -d -c test_abd_lookup.conf | grep e | awk '{print $3}')
+FKEY=$(gnunet-identity -d -c test_abd_lookup.conf | grep f | awk '{print $3}')
+GKEY=$(gnunet-identity -d -c test_abd_lookup.conf | grep g | awk '{print $3}')
+gnunet-identity -d
+
+#   (1) (A.a) <- B.b
+#   (2) (B.b) <- C.c
+#   (3) C.c <- (D.D)
+#   (4) D.d <- (E.e)
+#   (5) E.e <- (F)
+
+# BIDIRECTIONAL
+gnunet-abd --createIssuerSide --ego=a --attribute="a" --subject="$BKEY b" --ttl=5m -c test_abd_lookup.conf
+gnunet-namestore -D -z a
+gnunet-abd --createIssuerSide --ego=b --attribute="b" --subject="$CKEY c" --ttl=5m -c test_abd_lookup.conf
+gnunet-namestore -D -z b
+
+SIGNED=`$DO_TIMEOUT gnunet-abd --signSubjectSide --ego=c --attribute="c" --subject="$DKEY d" --ttl="2019-12-12 10:00:00"`
+gnunet-abd --createSubjectSide --ego=d --import="$SIGNED"
+gnunet-namestore -D -z d
+SIGNED=`$DO_TIMEOUT gnunet-abd --signSubjectSide --ego=d --attribute="d" --subject="$EKEY e" --ttl="2019-12-12 10:00:00"`
+gnunet-abd --createSubjectSide --ego=e --import="$SIGNED"
+gnunet-namestore -D -z e
+SIGNED=`$DO_TIMEOUT gnunet-abd --signSubjectSide --ego=e --attribute="e" --subject="$FKEY" --ttl="2019-12-12 10:00:00"`
+gnunet-abd --createSubjectSide --ego=f --import="$SIGNED" --private
+gnunet-namestore -D -z f
+
+# Starting to resolve
+echo "+++ Starting to Resolve +++"
+
+DELS=`$DO_TIMEOUT gnunet-abd --collect --issuer=$AKEY --attribute="a" --ego=f --forward --backward -c test_abd_lookup.conf | paste -d, -s - -`
+echo $DELS
+echo gnunet-abd --verify --issuer=$AKEY --attribute="a" --subject=$FKEY --delegate=\'$DELS\' --forward --backward -c test_abd_lookup.conf
+gnunet-abd --verify --issuer=$AKEY --attribute="a" --subject=$FKEY --delegate="$DELS" --forward --backward -c test_abd_lookup.conf
+
+RES=$?
+
+# Cleanup properly
+gnunet-namestore -z a -d -n "a" -t ATTR -c test_abd_lookup.conf
+gnunet-namestore -z b -d -n "b" -t ATTR -c test_abd_lookup.conf
+gnunet-namestore -z d -d -n "@" -t DEL -c test_abd_lookup.conf
+gnunet-namestore -z e -d -n "@" -t DEL -c test_abd_lookup.conf
+gnunet-namestore -z f -d -n "@" -t DEL -c test_abd_lookup.conf
+
+gnunet-arm -e -c test_abd_lookup.conf
+
+if [ "$RES" == 0 ]
+then
+  exit 0
+else
+  echo "FAIL: Failed to verify credential."
+  exit 1
+fi
diff --git a/src/abd/test_abd_bi_bw_link.sh b/src/abd/test_abd_bi_bw_link.sh
new file mode 100755
index 0000000000000000000000000000000000000000..f60f78827d75be273908705e92013761ac4981a4
--- /dev/null
+++ b/src/abd/test_abd_bi_bw_link.sh
@@ -0,0 +1,92 @@
+#!/usr/bin/env bash
+trap "gnunet-arm -e -c test_abd_lookup.conf" SIGINT
+
+LOCATION=$(which gnunet-config)
+if [ -z $LOCATION ]
+then
+  LOCATION="gnunet-config"
+fi
+$LOCATION --version 1> /dev/null
+if test $? != 0
+then
+	echo "GNUnet command line tools cannot be found, check environmental variables PATH and GNUNET_PREFIX"
+	exit 77
+fi
+
+rm -rf `gnunet-config -c test_abd_lookup.conf -s PATHS -o GNUNET_HOME -f`
+
+
+
+
+which timeout > /dev/null 2>&1 && DO_TIMEOUT="timeout 10"
+gnunet-arm -s -c test_abd_lookup.conf
+
+gnunet-identity -C a -c test_abd_lookup.conf
+gnunet-identity -C b -c test_abd_lookup.conf
+gnunet-identity -C c -c test_abd_lookup.conf
+gnunet-identity -C d -c test_abd_lookup.conf
+gnunet-identity -C e -c test_abd_lookup.conf
+gnunet-identity -C f -c test_abd_lookup.conf
+gnunet-identity -C g -c test_abd_lookup.conf
+AKEY=$(gnunet-identity -d -c test_abd_lookup.conf | grep a | awk '{print $3}')
+BKEY=$(gnunet-identity -d -c test_abd_lookup.conf | grep b | awk '{print $3}')
+CKEY=$(gnunet-identity -d -c test_abd_lookup.conf | grep c | awk '{print $3}')
+DKEY=$(gnunet-identity -d -c test_abd_lookup.conf | grep d | awk '{print $3}')
+EKEY=$(gnunet-identity -d -c test_abd_lookup.conf | grep e | awk '{print $3}')
+FKEY=$(gnunet-identity -d -c test_abd_lookup.conf | grep f | awk '{print $3}')
+GKEY=$(gnunet-identity -d -c test_abd_lookup.conf | grep g | awk '{print $3}')
+gnunet-identity -d
+
+#   (1) (A.a) <- B.b
+#   (2) (B.b) <- G.g.c
+#   (3) (G.g) <- C
+#   (3) C.c <- (D.D)
+#   (4) D.d <- (E.e)
+#   (5) E.e <- (F)
+
+# BIDIRECTIONAL
+gnunet-abd --createIssuerSide --ego=a --attribute="a" --subject="$BKEY b" --ttl=5m -c test_abd_lookup.conf
+gnunet-namestore -D -z a
+gnunet-abd --createIssuerSide --ego=b --attribute="b" --subject="$GKEY g.c" --ttl=5m -c test_abd_lookup.conf
+gnunet-namestore -D -z b
+gnunet-abd --createIssuerSide --ego=g --attribute="g" --subject="$CKEY" --ttl=5m -c test_abd_lookup.conf
+gnunet-namestore -D -z b
+
+SIGNED=`$DO_TIMEOUT gnunet-abd --signSubjectSide --ego=c --attribute="c" --subject="$DKEY d" --ttl="2019-12-12 10:00:00"`
+gnunet-abd --createSubjectSide --ego=d --import="$SIGNED"
+gnunet-namestore -D -z d
+SIGNED=`$DO_TIMEOUT gnunet-abd --signSubjectSide --ego=d --attribute="d" --subject="$EKEY e" --ttl="2019-12-12 10:00:00"`
+gnunet-abd --createSubjectSide --ego=e --import="$SIGNED"
+gnunet-namestore -D -z e
+SIGNED=`$DO_TIMEOUT gnunet-abd --signSubjectSide --ego=e --attribute="e" --subject="$FKEY" --ttl="2019-12-12 10:00:00"`
+gnunet-abd --createSubjectSide --ego=f --import="$SIGNED" --private
+gnunet-namestore -D -z f
+
+# Starting to resolve
+echo "+++ Starting to Resolve +++"
+
+DELS=`$DO_TIMEOUT gnunet-abd --collect --issuer=$AKEY --attribute="a" --ego=f --forward --backward -c test_abd_lookup.conf | paste -d, -s - -`
+echo $DELS
+echo gnunet-abd --verify --issuer=$AKEY --attribute="a" --subject=$FKEY --delegate=\'$DELS\' --forward --backward -c test_abd_lookup.conf
+gnunet-abd --verify --issuer=$AKEY --attribute="a" --subject=$FKEY --delegate="$DELS" --forward --backward -c test_abd_lookup.conf
+
+RES=$?
+
+# Cleanup properly
+gnunet-namestore -z a -d -n "a" -t ATTR -c test_abd_lookup.conf
+gnunet-namestore -z b -d -n "b" -t ATTR -c test_abd_lookup.conf
+gnunet-namestore -z g -d -n "g" -t ATTR -c test_abd_lookup.conf
+gnunet-namestore -z d -d -n "@" -t DEL -c test_abd_lookup.conf
+gnunet-namestore -z e -d -n "@" -t DEL -c test_abd_lookup.conf
+gnunet-namestore -z f -d -n "@" -t DEL -c test_abd_lookup.conf
+
+gnunet-arm -e -c test_abd_lookup.conf
+
+if [ "$RES" == 0 ]
+then
+  exit 0
+else
+  echo "FAIL: Failed to verify credential."
+  exit 1
+fi
+
diff --git a/src/abd/test_abd_bi_bw_link2.sh b/src/abd/test_abd_bi_bw_link2.sh
new file mode 100755
index 0000000000000000000000000000000000000000..b0fb49b8e3b7afba9045b41e78df43dec051f1db
--- /dev/null
+++ b/src/abd/test_abd_bi_bw_link2.sh
@@ -0,0 +1,93 @@
+#!/usr/bin/env bash
+trap "gnunet-arm -e -c test_abd_lookup.conf" SIGINT
+
+LOCATION=$(which gnunet-config)
+if [ -z $LOCATION ]
+then
+  LOCATION="gnunet-config"
+fi
+$LOCATION --version 1> /dev/null
+if test $? != 0
+then
+	echo "GNUnet command line tools cannot be found, check environmental variables PATH and GNUNET_PREFIX"
+	exit 77
+fi
+
+rm -rf `gnunet-config -c test_abd_lookup.conf -s PATHS -o GNUNET_HOME -f`
+
+
+
+
+which timeout > /dev/null 2>&1 && DO_TIMEOUT="timeout 10"
+gnunet-arm -s -c test_abd_lookup.conf
+
+gnunet-identity -C a -c test_abd_lookup.conf
+gnunet-identity -C b -c test_abd_lookup.conf
+gnunet-identity -C c -c test_abd_lookup.conf
+gnunet-identity -C d -c test_abd_lookup.conf
+gnunet-identity -C e -c test_abd_lookup.conf
+gnunet-identity -C f -c test_abd_lookup.conf
+gnunet-identity -C g -c test_abd_lookup.conf
+AKEY=$(gnunet-identity -d -c test_abd_lookup.conf | grep a | awk '{print $3}')
+BKEY=$(gnunet-identity -d -c test_abd_lookup.conf | grep b | awk '{print $3}')
+CKEY=$(gnunet-identity -d -c test_abd_lookup.conf | grep c | awk '{print $3}')
+DKEY=$(gnunet-identity -d -c test_abd_lookup.conf | grep d | awk '{print $3}')
+EKEY=$(gnunet-identity -d -c test_abd_lookup.conf | grep e | awk '{print $3}')
+FKEY=$(gnunet-identity -d -c test_abd_lookup.conf | grep f | awk '{print $3}')
+GKEY=$(gnunet-identity -d -c test_abd_lookup.conf | grep g | awk '{print $3}')
+gnunet-identity -d
+
+#   (1) (A.a) <- B.b
+#   (2) (B.b) <- G.g.c
+#   (3) G.g <- (C)
+#   (3) C.c <- (D.d)
+#   (4) D.d <- (E.e)
+#   (5) E.e <- (F)
+
+# BIDIRECTIONAL
+gnunet-abd --createIssuerSide --ego=a --attribute="a" --subject="$BKEY b" --ttl=5m -c test_abd_lookup.conf
+gnunet-namestore -D -z a
+gnunet-abd --createIssuerSide --ego=b --attribute="b" --subject="$GKEY g.c" --ttl=5m -c test_abd_lookup.conf
+gnunet-namestore -D -z b
+
+SIGNED=`$DO_TIMEOUT gnunet-abd --signSubjectSide --ego=g --attribute="g" --subject="$CKEY" --ttl="2019-12-12 10:00:00"`
+gnunet-abd --createSubjectSide --ego=c --import="$SIGNED"
+gnunet-namestore -D -z c
+SIGNED=`$DO_TIMEOUT gnunet-abd --signSubjectSide --ego=c --attribute="c" --subject="$DKEY d" --ttl="2019-12-12 10:00:00"`
+gnunet-abd --createSubjectSide --ego=d --import="$SIGNED"
+gnunet-namestore -D -z d
+SIGNED=`$DO_TIMEOUT gnunet-abd --signSubjectSide --ego=d --attribute="d" --subject="$EKEY e" --ttl="2019-12-12 10:00:00"`
+gnunet-abd --createSubjectSide --ego=e --import="$SIGNED"
+gnunet-namestore -D -z e
+SIGNED=`$DO_TIMEOUT gnunet-abd --signSubjectSide --ego=e --attribute="e" --subject="$FKEY" --ttl="2019-12-12 10:00:00"`
+gnunet-abd --createSubjectSide --ego=f --import="$SIGNED" --private
+gnunet-namestore -D -z f
+
+# Starting to resolve
+echo "+++ Starting to Resolve +++"
+
+DELS=`$DO_TIMEOUT gnunet-abd --collect --issuer=$AKEY --attribute="a" --ego=f --forward --backward -c test_abd_lookup.conf | paste -d, -s - -`
+echo $DELS
+echo gnunet-abd --verify --issuer=$AKEY --attribute="a" --subject=$FKEY --delegate=\'$DELS\' --forward --backward -c test_abd_lookup.conf
+gnunet-abd --verify --issuer=$AKEY --attribute="a" --subject=$FKEY --delegate="$DELS" --forward --backward -c test_abd_lookup.conf
+
+RES=$?
+
+# Cleanup properly
+gnunet-namestore -z a -d -n "a" -t ATTR -c test_abd_lookup.conf
+gnunet-namestore -z b -d -n "b" -t ATTR -c test_abd_lookup.conf
+gnunet-namestore -z c -d -n "@" -t DEL -c test_abd_lookup.conf
+gnunet-namestore -z d -d -n "@" -t DEL -c test_abd_lookup.conf
+gnunet-namestore -z e -d -n "@" -t DEL -c test_abd_lookup.conf
+gnunet-namestore -z f -d -n "@" -t DEL -c test_abd_lookup.conf
+
+gnunet-arm -e -c test_abd_lookup.conf
+
+if [ "$RES" == 0 ]
+then
+  exit 0
+else
+  echo "FAIL: Failed to verify credential."
+  exit 1
+fi
+
diff --git a/src/abd/test_abd_bi_fw.sh b/src/abd/test_abd_bi_fw.sh
new file mode 100755
index 0000000000000000000000000000000000000000..75a940fbe366ad302059d3fb2d90adf2944bb41f
--- /dev/null
+++ b/src/abd/test_abd_bi_fw.sh
@@ -0,0 +1,92 @@
+#!/usr/bin/env bash
+trap "gnunet-arm -e -c test_abd_lookup.conf" SIGINT
+
+LOCATION=$(which gnunet-config)
+if [ -z $LOCATION ]
+then
+  LOCATION="gnunet-config"
+fi
+$LOCATION --version 1> /dev/null
+if test $? != 0
+then
+	echo "GNUnet command line tools cannot be found, check environmental variables PATH and GNUNET_PREFIX"
+	exit 77
+fi
+
+rm -rf `gnunet-config -c test_abd_lookup.conf -s PATHS -o GNUNET_HOME -f`
+
+
+
+
+which timeout > /dev/null 2>&1 && DO_TIMEOUT="timeout 10"
+gnunet-arm -s -c test_abd_lookup.conf
+
+gnunet-identity -C a -c test_abd_lookup.conf
+gnunet-identity -C b -c test_abd_lookup.conf
+gnunet-identity -C c -c test_abd_lookup.conf
+gnunet-identity -C d -c test_abd_lookup.conf
+gnunet-identity -C e -c test_abd_lookup.conf
+gnunet-identity -C f -c test_abd_lookup.conf
+gnunet-identity -C g -c test_abd_lookup.conf
+AKEY=$(gnunet-identity -d -c test_abd_lookup.conf | grep a | awk '{print $3}')
+BKEY=$(gnunet-identity -d -c test_abd_lookup.conf | grep b | awk '{print $3}')
+CKEY=$(gnunet-identity -d -c test_abd_lookup.conf | grep c | awk '{print $3}')
+DKEY=$(gnunet-identity -d -c test_abd_lookup.conf | grep d | awk '{print $3}')
+EKEY=$(gnunet-identity -d -c test_abd_lookup.conf | grep e | awk '{print $3}')
+FKEY=$(gnunet-identity -d -c test_abd_lookup.conf | grep f | awk '{print $3}')
+GKEY=$(gnunet-identity -d -c test_abd_lookup.conf | grep g | awk '{print $3}')
+gnunet-identity -d
+
+#   (1) (A.a) <- B.b
+#   (2) (B.b) <- C.c
+#   (3) C.c <- (D.D)
+#   (4) D.d <- (E.e)
+#   (5) E.e <- (F.f)
+#   (6) F.f <- (G)
+
+# BIDIRECTIONAL
+gnunet-abd --createIssuerSide --ego=a --attribute="a" --subject="$BKEY b" --ttl=5m -c test_abd_lookup.conf
+gnunet-namestore -D -z a
+gnunet-abd --createIssuerSide --ego=b --attribute="b" --subject="$CKEY c" --ttl=5m -c test_abd_lookup.conf
+gnunet-namestore -D -z b
+
+SIGNED=`$DO_TIMEOUT gnunet-abd --signSubjectSide --ego=c --attribute="c" --subject="$DKEY d" --ttl="2019-12-12 10:00:00"`
+gnunet-abd --createSubjectSide --ego=d --import="$SIGNED"
+gnunet-namestore -D -z d
+SIGNED=`$DO_TIMEOUT gnunet-abd --signSubjectSide --ego=d --attribute="d" --subject="$EKEY e" --ttl="2019-12-12 10:00:00"`
+gnunet-abd --createSubjectSide --ego=e --import="$SIGNED"
+gnunet-namestore -D -z e
+SIGNED=`$DO_TIMEOUT gnunet-abd --signSubjectSide --ego=e --attribute="e" --subject="$FKEY f" --ttl="2019-12-12 10:00:00"`
+gnunet-abd --createSubjectSide --ego=f --import="$SIGNED" 
+gnunet-namestore -D -z f
+SIGNED=`$DO_TIMEOUT gnunet-abd --signSubjectSide --ego=f --attribute="f" --subject="$GKEY" --ttl="2019-12-12 10:00:00"`
+gnunet-abd --createSubjectSide --ego=g --import="$SIGNED" --private
+gnunet-namestore -D -z g
+
+# Starting to resolve
+echo "+++ Starting to Resolve +++"
+
+DELS=`$DO_TIMEOUT gnunet-abd --collect --issuer=$AKEY --attribute="a" --ego=g --forward --backward -c test_abd_lookup.conf | paste -d, -s - -`
+echo $DELS
+echo gnunet-abd --verify --issuer=$AKEY --attribute="a" --subject=$GKEY --delegate=\'$DELS\' --forward --backward -c test_abd_lookup.conf
+gnunet-abd --verify --issuer=$AKEY --attribute="a" --subject=$GKEY --delegate="$DELS" --forward --backward -c test_abd_lookup.conf
+
+RES=$?
+
+# Cleanup properly
+gnunet-namestore -z a -d -n "a" -t ATTR -c test_abd_lookup.conf
+gnunet-namestore -z b -d -n "b" -t ATTR -c test_abd_lookup.conf
+gnunet-namestore -z d -d -n "@" -t DEL -c test_abd_lookup.conf
+gnunet-namestore -z e -d -n "@" -t DEL -c test_abd_lookup.conf
+gnunet-namestore -z f -d -n "@" -t DEL -c test_abd_lookup.conf
+gnunet-namestore -z g -d -n "@" -t DEL -c test_abd_lookup.conf
+
+gnunet-arm -e -c test_abd_lookup.conf
+
+if [ "$RES" == 0 ]
+then
+  exit 0
+else
+  echo "FAIL: Failed to verify credential."
+  exit 1
+fi
diff --git a/src/abd/test_abd_issue.sh b/src/abd/test_abd_issue.sh
new file mode 100755
index 0000000000000000000000000000000000000000..8076aa92123207744372ed330360848d1801c706
--- /dev/null
+++ b/src/abd/test_abd_issue.sh
@@ -0,0 +1,46 @@
+#!/usr/bin/env bash
+trap "gnunet-arm -e -c test_abd_lookup.conf" SIGINT
+
+LOCATION=$(which gnunet-config)
+if [ -z $LOCATION ]
+then
+  LOCATION="gnunet-config"
+fi
+$LOCATION --version 1> /dev/null
+if test $? != 0
+then
+	echo "GNUnet command line tools cannot be found, check environmental variables PATH and GNUNET_PREFIX"
+	exit 77
+fi
+
+rm -rf `gnunet-config -c test_abd_lookup.conf -s PATHS -o GNUNET_HOME -f`
+
+#  (1) PKEY1.user -> PKEY2.resu.user
+#  (2) PKEY2.resu -> PKEY3
+#  (3) PKEY3.user -> PKEY4
+
+
+which timeout > /dev/null 2>&1 && DO_TIMEOUT="timeout 30"
+
+TEST_ATTR="test"
+gnunet-arm -s -c test_abd_lookup.conf
+gnunet-identity -C testissuer -c test_abd_lookup.conf
+gnunet-identity -C testsubject -c test_abd_lookup.conf
+SUBJECT_KEY=$(gnunet-identity -d -c test_abd_lookup.conf | grep testsubject | awk '{print $3}')
+ISSUER_KEY=$(gnunet-identity -d -c test_abd_lookup.conf | grep testissuer | awk '{print $3}')
+
+# Get abd and store it with subject (3)
+SIGNED=`$DO_TIMEOUT gnunet-abd --signSubjectSide --ego=testissuer --attribute=$TEST_ATTR --subject=$SUBJECT_KEY --ttl="2019-12-12 10:00:00" -c test_abd_lookup.conf`
+
+STATUS=$?
+
+if test $? != 0
+then
+  echo "Error issuing..."
+  exit 1
+fi
+#Try import
+$DO_TIMEOUT gnunet-abd --createSubjectSide --ego=testsubject --import="$SIGNED" --private -c test_abd_lookup.conf
+RES=$?
+gnunet-arm -e -c test_abd_lookup.conf
+exit $RES
diff --git a/src/abd/test_abd_own.sh b/src/abd/test_abd_own.sh
new file mode 100755
index 0000000000000000000000000000000000000000..f4780ea9028240c6e5bfd33f70a3efba5e3cc681
--- /dev/null
+++ b/src/abd/test_abd_own.sh
@@ -0,0 +1,140 @@
+#!/usr/bin/env bash
+trap "gnunet-arm -e -c test_abd_lookup.conf" SIGINT
+
+LOCATION=$(which gnunet-config)
+if [ -z $LOCATION ]
+then
+  LOCATION="gnunet-config"
+fi
+$LOCATION --version 1> /dev/null
+if test $? != 0
+then
+	echo "GNUnet command line tools cannot be found, check environmental variables PATH and GNUNET_PREFIX"
+	exit 77
+fi
+
+rm -rf `gnunet-config -c test_abd_lookup.conf -s PATHS -o GNUNET_HOME -f`
+
+
+
+which timeout > /dev/null 2>&1 && DO_TIMEOUT="timeout 10"
+gnunet-arm -s -c test_abd_lookup.conf
+
+gnunet-identity -C a -c test_abd_lookup.conf
+gnunet-identity -C d -c test_abd_lookup.conf
+gnunet-identity -C e -c test_abd_lookup.conf
+gnunet-identity -C f -c test_abd_lookup.conf
+gnunet-identity -C g -c test_abd_lookup.conf
+AKEY=$(gnunet-identity -d -c test_abd_lookup.conf | grep a | awk '{print $3}')
+DKEY=$(gnunet-identity -d -c test_abd_lookup.conf | grep d | awk '{print $3}')
+EKEY=$(gnunet-identity -d -c test_abd_lookup.conf | grep e | awk '{print $3}')
+FKEY=$(gnunet-identity -d -c test_abd_lookup.conf | grep f | awk '{print $3}')
+GKEY=$(gnunet-identity -d -c test_abd_lookup.conf | grep g | awk '{print $3}')
+
+############################################################################################
+#   (1) EPub.discount <- EOrg.preferred
+#   (2) EOrg.preferred <- StateU.student
+#   (3) StateU.student <- RegistrarB.student
+#   (4) RegistrarB.student <- Alice
+
+gnunet-identity -C epub -c test_abd_lookup.conf
+gnunet-identity -C eorg -c test_abd_lookup.conf
+gnunet-identity -C stateu -c test_abd_lookup.conf
+gnunet-identity -C registrarb -c test_abd_lookup.conf
+gnunet-identity -C alice -c test_abd_lookup.conf
+
+EPUB_KEY=$(gnunet-identity -d -c test_abd_lookup.conf | grep epub | awk '{print $3}')
+EORG_KEY=$(gnunet-identity -d -c test_abd_lookup.conf | grep eorg | awk '{print $3}')
+STATEU_KEY=$(gnunet-identity -d -c test_abd_lookup.conf | grep stateu | awk '{print $3}')
+REGISTRARB_KEY=$(gnunet-identity -d -c test_abd_lookup.conf | grep registrarb | awk '{print $3}')
+ALICE_KEY=$(gnunet-identity -d -c test_abd_lookup.conf | grep alice | awk '{print $3}')
+
+
+DISC_ATTR="discount"
+PREF_ATTR="preferred"
+STATE_STUD_ATTR="student"
+REG_STUD_ATTR="student"
+END_ATTR="end"
+
+gnunet-identity -d
+
+# FORWARD, subject side stored (different constallations)
+SIGNED=`$DO_TIMEOUT gnunet-abd --signSubjectSide --ego=a --attribute="a" --subject="$AKEY b.c" --ttl="2019-12-12 10:00:00"`
+gnunet-abd --createSubjectSide --ego=a --import="$SIGNED"
+gnunet-namestore -D -z a
+
+SIGNED=`$DO_TIMEOUT gnunet-abd --signSubjectSide --ego=a --attribute="b" --subject="$DKEY d" --ttl="2019-12-12 10:00:00"`
+gnunet-abd --createSubjectSide --ego=d --import="$SIGNED"
+gnunet-namestore -D -z d
+
+SIGNED=`$DO_TIMEOUT gnunet-abd --signSubjectSide --ego=d --attribute="d" --subject="$EKEY" --ttl="2019-12-12 10:00:00"`
+gnunet-abd --createSubjectSide --ego=e --import="$SIGNED"
+gnunet-namestore -D -z e
+
+SIGNED=`$DO_TIMEOUT gnunet-abd --signSubjectSide --ego=e --attribute="c" --subject="$FKEY c" --ttl="2019-12-12 10:00:00"`
+gnunet-abd --createSubjectSide --ego=f --import="$SIGNED"
+SIGNED=`$DO_TIMEOUT gnunet-abd --signSubjectSide --ego=e --attribute="k" --subject="$FKEY c.k" --ttl="2019-12-12 10:00:00"`
+gnunet-abd --createSubjectSide --ego=f --import="$SIGNED"
+gnunet-namestore -D -z f
+
+SIGNED=`$DO_TIMEOUT gnunet-abd --signSubjectSide --ego=f --attribute="c" --subject="$GKEY" --ttl="2019-12-12 10:00:00"`
+gnunet-abd --createSubjectSide --ego=g --import="$SIGNED" --private
+SIGNED=`$DO_TIMEOUT gnunet-abd --signSubjectSide --ego=a --attribute="c" --subject="$GKEY" --ttl="2019-12-12 10:00:00"`
+gnunet-abd --createSubjectSide --ego=g --import="$SIGNED" --private
+SIGNED=`$DO_TIMEOUT gnunet-abd --signSubjectSide --ego=d --attribute="h.o" --subject="$GKEY" --ttl="2019-12-12 10:00:00"`
+gnunet-abd --createSubjectSide --ego=g --import="$SIGNED"
+gnunet-namestore -D -z g
+
+
+# BACKWARD, issuer side stored
+# (1) EPub assigns the attribute "discount" to all entities that have been assigned "preferred" by EOrg
+gnunet-abd --createIssuerSide --ego=epub --attribute=$DISC_ATTR --subject="$EORG_KEY $PREF_ATTR" --ttl=5m -c test_abd_lookup.conf
+
+# (2) EOrg assigns the attribute "preferred" to all entities that have been assigned "student" by StateU
+gnunet-abd --createIssuerSide --ego=eorg --attribute=$PREF_ATTR --subject="$STATEU_KEY $STATE_STUD_ATTR" --ttl=5m -c test_abd_lookup.conf
+
+# (3) StateU assigns the attribute "student" to all entities that have been asssigned "student" by RegistrarB
+gnunet-abd --createIssuerSide --ego=stateu --attribute=$STATE_STUD_ATTR --subject="$REGISTRARB_KEY $REG_STUD_ATTR" --ttl=5m -c test_abd_lookup.conf
+
+# (4) RegistrarB issues Alice the credential "student"
+SIGNED=`$DO_TIMEOUT gnunet-abd --signSubjectSide --ego=registrarb --attribute="$REG_STUD_ATTR" --subject="$ALICE_KEY" --ttl="2019-12-12 10:00:00"`
+gnunet-abd --createSubjectSide --ego=alice --import="$SIGNED" --private
+
+# Starting to resolve
+echo "+++ Starting to Resolve +++"
+
+# FORWARD
+#DELS=`$DO_TIMEOUT gnunet-abd --collect --issuer=$AKEY --attribute="a" --ego=g --forward -c test_abd_lookup.conf | paste -d, -s - -`
+#echo $DELS
+#echo gnunet-abd --verify --issuer=$AKEY --attribute="a" --subject=$GKEY --delegate=\'$DELS\' --forward -c test_abd_lookup.conf
+#RES_DELS=`gnunet-abd --verify --issuer=$AKEY --attribute="a" --subject=$GKEY --delegate="$DELS" --forward -c test_abd_lookup.conf`
+
+# BACKWARD
+DELS=`$DO_TIMEOUT gnunet-abd --collect --issuer=$EPUB_KEY --attribute=$DISC_ATTR --ego=alice --backward -c test_abd_lookup.conf | paste -d, -s - -`
+echo $DELS
+echo gnunet-abd --verify --issuer=$EPUB_KEY --attribute=$DISC_ATTR --subject=$ALICE_KEY --delegate=\'$DELS\' --backward -c test_abd_lookup.conf
+gnunet-abd --verify --issuer=$EPUB_KEY --attribute=$DISC_ATTR --subject=$ALICE_KEY --delegate="$DELS" --backward -c test_abd_lookup.conf
+
+RES=$?
+
+# Cleanup properly
+gnunet-namestore -z epub -d -n $DISC_ATTR -t ATTR -c test_abd_lookup.conf
+gnunet-namestore -z eorg -d -n $PREF_ATTR -t ATTR -c test_abd_lookup.conf
+gnunet-namestore -z stateu -d -n $STATE_STUD_ATTR -t ATTR -c test_abd_lookup.conf
+#gnunet-namestore -z a -d -n "@" -t DEL -c test_abd_lookup.conf
+#gnunet-namestore -z d -d -n "@" -t DEL -c test_abd_lookup.conf
+#gnunet-namestore -z e -d -n "@" -t DEL -c test_abd_lookup.conf
+#gnunet-namestore -z f -d -n "@" -t DEL -c test_abd_lookup.conf
+#gnunet-namestore -z g -d -n "@" -t DEL -c test_abd_lookup.conf
+
+
+gnunet-arm -e -c test_abd_lookup.conf
+
+if [ "$RES" == 0 ]
+then
+  exit 0
+else
+  echo "FAIL: Failed to verify credential."
+  exit 1
+fi
+
diff --git a/src/abd/test_abd_verify.sh b/src/abd/test_abd_verify.sh
new file mode 100755
index 0000000000000000000000000000000000000000..9ece91c62cd86fa7659d856bbe2a7dcb4757f643
--- /dev/null
+++ b/src/abd/test_abd_verify.sh
@@ -0,0 +1,87 @@
+#!/usr/bin/env bash
+trap "gnunet-arm -e -c test_abd_lookup.conf" SIGINT
+
+LOCATION=$(which gnunet-config)
+if [ -z $LOCATION ]
+then
+  LOCATION="gnunet-config"
+fi
+$LOCATION --version 1> /dev/null
+if test $? != 0
+then
+	echo "GNUnet command line tools cannot be found, check environmental variables PATH and GNUNET_PREFIX"
+	exit 77
+fi
+
+rm -rf `gnunet-config -c test_abd_lookup.conf -s PATHS -o GNUNET_HOME -f`
+
+#  (1) Service.user -> GNU.project.member
+#  (2) GNU.project -> GNUnet
+#  (3) GNUnet.member -> GNUnet.developer
+#  (4) GNUnet.member -> GNUnet.user
+#  (5) GNUnet.developer -> Alice
+
+
+which timeout > /dev/null 2>&1 && DO_TIMEOUT="timeout 30"
+gnunet-arm -s -c test_abd_lookup.conf
+gnunet-identity -C service -c test_abd_lookup.conf
+gnunet-identity -C alice -c test_abd_lookup.conf
+gnunet-identity -C gnu -c test_abd_lookup.conf
+gnunet-identity -C gnunet -c test_abd_lookup.conf
+
+GNU_KEY=$(gnunet-identity -d -c test_abd_lookup.conf | grep gnu | grep -v gnunet | awk '{print $3}')
+ALICE_KEY=$(gnunet-identity -d -c test_abd_lookup.conf | grep alice | awk '{print $3}')
+GNUNET_KEY=$(gnunet-identity -d -c test_abd_lookup.conf | grep gnunet | awk '{print $3}')
+SERVICE_KEY=$(gnunet-identity -d -c test_abd_lookup.conf | grep service | awk '{print $3}')
+
+USER_ATTR="user"
+GNU_PROJECT_ATTR="project"
+MEMBER_ATTR="member"
+DEVELOPER_ATTR="developer"
+DEV_ATTR="developer"
+TEST_CREDENTIAL="mygnunetcreds"
+
+gnunet-identity -d
+
+# (1) A service assigns the attribute "user" to all entities that have been assigned "member" by entities that werde assigned "project" from GNU
+gnunet-abd --createIssuerSide --ego=service --attribute="$USER_ATTR" --subject="$GNU_KEY $GNU_PROJECT_ATTR.$MEMBER_ATTR" --ttl="2019-12-12 10:00:00" -c test_abd_lookup.conf
+gnunet-namestore -D -z service
+
+# (2) GNU recognized GNUnet as a GNU project and delegates the "project" attribute
+gnunet-abd --createIssuerSide --ego=gnu --attribute="$GNU_PROJECT_ATTR" --subject="$GNUNET_KEY" --ttl="2019-12-12 10:00:00" -c test_abd_lookup.conf
+gnunet-namestore -D -z gnu
+
+# (3+4) GNUnet assigns the attribute "member" to all entities gnunet has also assigned "developer" or "user"
+gnunet-abd --createIssuerSide --ego=gnunet --attribute="$MEMBER_ATTR" --subject="$GNUNET_KEY $DEVELOPER_ATTR" --ttl="2019-12-12 10:00:00" -c test_abd_lookup.conf
+gnunet-abd --createIssuerSide --ego=gnunet --attribute="$MEMBER_ATTR" --subject="$GNUNET_KEY $USER_ATTR" --ttl="2019-12-12 10:00:00" -c test_abd_lookup.conf
+gnunet-namestore -D -z gnunet
+
+# (5) GNUnet signes the delegate and Alice stores it
+SIGNED=`$DO_TIMEOUT gnunet-abd --signSubjectSide --ego=gnunet --attribute=$DEV_ATTR --subject=$ALICE_KEY --ttl="2019-12-12 10:00:00"`
+gnunet-abd --createSubjectSide --ego=alice --import="$SIGNED" --private
+gnunet-namestore -D -z alice
+
+# Starting to resolve
+echo "+++ Starting to Resolve +++"
+
+DELS=`$DO_TIMEOUT gnunet-abd --collect --issuer=$SERVICE_KEY --attribute=$USER_ATTR --ego=alice --backward -c test_abd_lookup.conf | paste -d, -s - -`
+echo $DELS
+echo gnunet-abd --verify --issuer=$SERVICE_KEY --attribute=$USER_ATTR --subject=$ALICE_KEY --delegate=\'$DELS\' --backward -c test_abd_lookup.conf
+gnunet-abd --verify --issuer=$SERVICE_KEY --attribute=$USER_ATTR --subject=$ALICE_KEY --delegate="$DELS" --backward -c test_abd_lookup.conf
+
+RES=$?
+
+# Cleanup properly
+gnunet-namestore -z alice -d -n "@" -t DEL -c test_abd_lookup.conf
+gnunet-namestore -z gnu -d -n $GNU_PROJECT_ATTR -t ATTR -c test_abd_lookup.conf
+gnunet-namestore -z gnunet -d -n $MEMBER_ATTR -t ATTR -c test_abd_lookup.conf
+gnunet-namestore -z service -d -n $USER_ATTR -t ATTR -c test_abd_lookup.conf
+gnunet-arm -e -c test_abd_lookup.conf
+
+if [ "$RES" == 0 ]
+then
+  exit 0
+else
+  echo "FAIL: Failed to verify credential."
+  exit 1
+fi
diff --git a/src/abd/test_abd_verify_and.sh b/src/abd/test_abd_verify_and.sh
new file mode 100755
index 0000000000000000000000000000000000000000..c6287055e00811703505344a72c3ed3f2b6bf844
--- /dev/null
+++ b/src/abd/test_abd_verify_and.sh
@@ -0,0 +1,86 @@
+#!/usr/bin/env bash
+trap "gnunet-arm -e -c test_abd_lookup.conf" SIGINT
+
+LOCATION=$(which gnunet-config)
+if [ -z $LOCATION ]
+then
+  LOCATION="gnunet-config"
+fi
+$LOCATION --version 1> /dev/null
+if test $? != 0
+then
+	echo "GNUnet command line tools cannot be found, check environmental variables PATH and GNUNET_PREFIX"
+	exit 77
+fi
+
+rm -rf `gnunet-config -c test_abd_lookup.conf -s PATHS -o GNUNET_HOME -f`
+
+#  (1) Service.user -> GNU.project.member
+#  (2) GNU.project -> GNUnet
+#  (3) GNUnet.member -> GNUnet.developer AND GNUnet.user
+#  (4) GNUnet.developer -> Alice
+
+
+which timeout > /dev/null 2>&1 && DO_TIMEOUT="timeout 30"
+gnunet-arm -s -c test_abd_lookup.conf
+gnunet-identity -C service -c test_abd_lookup.conf
+gnunet-identity -C alice -c test_abd_lookup.conf
+gnunet-identity -C gnu -c test_abd_lookup.conf
+gnunet-identity -C gnunet -c test_abd_lookup.conf
+
+GNU_KEY=$(gnunet-identity -d -c test_abd_lookup.conf | grep gnu | grep -v gnunet | awk '{print $3}')
+ALICE_KEY=$(gnunet-identity -d -c test_abd_lookup.conf | grep alice | awk '{print $3}')
+GNUNET_KEY=$(gnunet-identity -d -c test_abd_lookup.conf | grep gnunet | awk '{print $3}')
+SERVICE_KEY=$(gnunet-identity -d -c test_abd_lookup.conf | grep service | awk '{print $3}')
+
+USER_ATTR="user"
+GNU_PROJECT_ATTR="project"
+MEMBER_ATTR="member"
+DEVELOPER_ATTR="developer"
+DEV_ATTR="developer"
+
+gnunet-identity -d
+
+# (1) A service assigns the attribute "user" to all entities that have been assigned "member" by entities that werde assigned "project" from GNU
+gnunet-abd --createIssuerSide --ego=service --attribute="$USER_ATTR" --subject="$GNU_KEY $GNU_PROJECT_ATTR.$MEMBER_ATTR" --ttl="2019-12-12 10:00:00" -c test_abd_lookup.conf
+gnunet-namestore -D -z service
+
+# (2) GNU recognized GNUnet as a GNU project and delegates the "project" attribute
+gnunet-abd --createIssuerSide --ego=gnu --attribute="$GNU_PROJECT_ATTR" --subject="$GNUNET_KEY" --ttl="2019-12-12 10:00:00" -c test_abd_lookup.conf
+gnunet-namestore -D -z gnu
+
+# (3+4) GNUnet assigns the attribute "member" to all entities gnunet has also assigned "developer" or "user"
+gnunet-abd --createIssuerSide --ego=gnunet --attribute="$MEMBER_ATTR" --subject="$GNUNET_KEY $DEVELOPER_ATTR, $GNUNET_KEY $USER_ATTR" --ttl="2019-12-12 10:00:00" -c test_abd_lookup.conf
+gnunet-namestore -D -z gnunet
+
+# (5) GNUnet signes the delegates and Alice stores it
+SIGNED=`$DO_TIMEOUT gnunet-abd --signSubjectSide --ego=gnunet --attribute=$DEV_ATTR --subject=$ALICE_KEY --ttl="2019-12-12 10:00:00"`
+gnunet-abd --createSubjectSide --ego=alice --import="$SIGNED" --private
+SIGNED=`$DO_TIMEOUT gnunet-abd --signSubjectSide --ego=gnunet --attribute=$USER_ATTR --subject=$ALICE_KEY --ttl="2019-12-12 10:00:00"`
+gnunet-abd --createSubjectSide --ego=alice --import="$SIGNED" --private
+gnunet-namestore -D -z alice
+
+# Starting to resolve
+echo "+++ Starting to Resolve +++"
+
+DELS=`$DO_TIMEOUT gnunet-abd --collect --issuer=$SERVICE_KEY --attribute=$USER_ATTR --ego=alice --backward -c test_abd_lookup.conf | paste -d, -s - -`
+echo $DELS
+echo gnunet-abd --verify --issuer=$SERVICE_KEY --attribute=$USER_ATTR --subject=$ALICE_KEY --delegate=\'$DELS\' --backward -c test_abd_lookup.conf
+gnunet-abd --verify --issuer=$SERVICE_KEY --attribute=$USER_ATTR --subject=$ALICE_KEY --delegate="$DELS" --backward -c test_abd_lookup.conf
+
+RES=$?
+
+# Cleanup properly
+gnunet-namestore -z alice -d -n "@" -t DEL -c test_abd_lookup.conf
+gnunet-namestore -z gnu -d -n $GNU_PROJECT_ATTR -t ATTR -c test_abd_lookup.conf
+gnunet-namestore -z gnunet -d -n $MEMBER_ATTR -t ATTR -c test_abd_lookup.conf
+gnunet-namestore -z service -d -n $USER_ATTR -t ATTR -c test_abd_lookup.conf
+gnunet-arm -e -c test_abd_lookup.conf
+
+if [ "$RES" == 0 ]
+then
+  exit 0
+else
+  echo "FAIL: Failed to verify credentials."
+  exit 1
+fi
diff --git a/src/abd/test_abd_verify_simple.sh b/src/abd/test_abd_verify_simple.sh
new file mode 100755
index 0000000000000000000000000000000000000000..e917f87937d5fc0f064383fc1fa144bb91284d7b
--- /dev/null
+++ b/src/abd/test_abd_verify_simple.sh
@@ -0,0 +1,56 @@
+#!/usr/bin/env bash
+trap "gnunet-arm -e -c test_abd_lookup.conf" SIGINT
+
+LOCATION=$(which gnunet-config)
+if [ -z $LOCATION ]
+then
+  LOCATION="gnunet-config"
+fi
+$LOCATION --version 1> /dev/null
+if test $? != 0
+then
+	echo "GNUnet command line tools cannot be found, check environmental variables PATH and GNUNET_PREFIX"
+	exit 77
+fi
+
+rm -rf `gnunet-config -c test_abd_lookup.conf -s PATHS -o GNUNET_HOME -f`
+
+#  (1) Issuer.user -> Subject
+
+
+which timeout > /dev/null 2>&1 && DO_TIMEOUT="timeout 30"
+gnunet-arm -s -c test_abd_lookup.conf
+gnunet-identity -C testissuer -c test_abd_lookup.conf
+gnunet-identity -C testsubject -c test_abd_lookup.conf
+
+TEST_ATTR="user"
+SUBJECT_KEY=$(gnunet-identity -d -c test_abd_lookup.conf | grep testsubject | awk '{print $3}')
+ISSUER_KEY=$(gnunet-identity -d -c test_abd_lookup.conf | grep testissuer | awk '{print $3}')
+
+gnunet-identity -d
+
+# Create delegate (1)
+SIGNED=`$DO_TIMEOUT gnunet-abd --signSubjectSide --ego=testissuer --attribute=$TEST_ATTR --subject=$SUBJECT_KEY --ttl="2019-12-12 10:00:00" -c test_abd_lookup.conf`
+gnunet-abd --createSubjectSide --ego=testsubject --import="$SIGNED" --private
+gnunet-namestore -D -z testsubject
+
+# Starting to resolve
+echo "+++ Starting to Resolve +++"
+
+DELS=`$DO_TIMEOUT gnunet-abd --collect --issuer=$ISSUER_KEY --attribute=$TEST_ATTR --ego=testsubject -c test_abd_lookup.conf | paste -d, -s - -`
+echo $DELS
+gnunet-abd --verify --issuer=$ISSUER_KEY --attribute=$TEST_ATTR --subject=$SUBJECT_KEY --delegate="$DELS" -c test_abd_lookup.conf
+
+RES=$?
+
+# Cleanup properly
+gnunet-namestore -z testsubject -d -n "@" -t DEL -c test_abd_lookup.conf
+gnunet-arm -e -c test_abd_lookup.conf
+
+if [ "$RES" == 0 ]
+then
+  exit 0
+else
+  echo "FAIL: Failed to verify credential."
+  exit 1
+fi
\ No newline at end of file
diff --git a/src/arm/.gitignore b/src/arm/.gitignore
new file mode 100644
index 0000000000000000000000000000000000000000..859c6e393e6302ecdd7fb61de2cbeeba83676f72
--- /dev/null
+++ b/src/arm/.gitignore
@@ -0,0 +1,7 @@
+mockup-service
+gnunet-arm
+gnunet-service-arm
+test_arm_api
+test_exponential_backoff
+test_gnunet_arm.py
+test_gnunet_service_arm
diff --git a/src/arm/arm_api.c b/src/arm/arm_api.c
index cd5f44565a6853f0839d8c1fef332714beef477d..899b6f152e83633d4dc79f38307c56904f46a0a3 100644
--- a/src/arm/arm_api.c
+++ b/src/arm/arm_api.c
@@ -729,8 +729,7 @@ start_arm_service (struct GNUNET_ARM_Handle *h,
     /* Means we are ONLY running locally */
     /* we're clearly running a test, don't daemonize */
     if (NULL == config)
-      proc = GNUNET_OS_start_process_s (GNUNET_NO,
-                                        std_inheritance,
+      proc = GNUNET_OS_start_process_s (std_inheritance,
                                         lsocks,
                                         loprefix,
                                         quotedbinary,
@@ -738,8 +737,7 @@ start_arm_service (struct GNUNET_ARM_Handle *h,
                                         lopostfix,
                                         NULL);
     else
-      proc = GNUNET_OS_start_process_s (GNUNET_NO,
-                                        std_inheritance,
+      proc = GNUNET_OS_start_process_s (std_inheritance,
                                         lsocks,
                                         loprefix,
                                         quotedbinary,
@@ -752,8 +750,7 @@ start_arm_service (struct GNUNET_ARM_Handle *h,
   else
   {
     if (NULL == config)
-      proc = GNUNET_OS_start_process_s (GNUNET_NO,
-                                        std_inheritance,
+      proc = GNUNET_OS_start_process_s (std_inheritance,
                                         lsocks,
                                         loprefix,
                                         quotedbinary,
@@ -761,8 +758,7 @@ start_arm_service (struct GNUNET_ARM_Handle *h,
                                         lopostfix,
                                         NULL);
     else
-      proc = GNUNET_OS_start_process_s (GNUNET_NO,
-                                        std_inheritance,
+      proc = GNUNET_OS_start_process_s (std_inheritance,
                                         lsocks,
                                         loprefix,
                                         quotedbinary,
@@ -976,10 +972,7 @@ GNUNET_ARM_request_service_start (struct GNUNET_ARM_Handle *h,
      the above check should catch 99.99% of the cases where ARM
      is already running. */LOG (GNUNET_ERROR_TYPE_DEBUG,
        "Starting ARM service\n");
-  if (NULL == (sig = GNUNET_DISK_pipe (GNUNET_NO,
-                                       GNUNET_NO,
-                                       GNUNET_NO,
-                                       GNUNET_YES)))
+  if (NULL == (sig = GNUNET_DISK_pipe (GNUNET_DISK_PF_NONE)))
   {
     GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING,
                          "pipe");
diff --git a/src/arm/gnunet-service-arm.c b/src/arm/gnunet-service-arm.c
index 5efd8b72b10c98cb4abaff9f774e76cd9ff43843..263c99cc4b6f0f5eab6d15c0aa69ae283cd558ad 100644
--- a/src/arm/gnunet-service-arm.c
+++ b/src/arm/gnunet-service-arm.c
@@ -858,8 +858,10 @@ start_process (struct ServiceList *sl,
      * of ''-quoted strings, escaping should be considered. */
     if (NULL != options)
       options = GNUNET_CONFIGURATION_expand_dollar (cfg, options);
-    sl->proc = GNUNET_OS_start_process_s (sl->pipe_control,
-                                          GNUNET_OS_INHERIT_STD_OUT_AND_ERR,
+    sl->proc = GNUNET_OS_start_process_s (sl->pipe_control
+                                          ? GNUNET_OS_INHERIT_STD_OUT_AND_ERR
+                                          | GNUNET_OS_USE_PIPE_CONTROL
+                                          : GNUNET_OS_INHERIT_STD_OUT_AND_ERR,
                                           lsocks,
                                           loprefix,
                                           quotedbinary,
@@ -880,7 +882,11 @@ start_process (struct ServiceList *sl,
     if (GNUNET_YES == use_debug)
     {
       if (NULL == sl->config)
-        sl->proc = GNUNET_OS_start_process_s (sl->pipe_control,
+        sl->proc = GNUNET_OS_start_process_s (sl->pipe_control
+                                              ?
+                                              GNUNET_OS_INHERIT_STD_OUT_AND_ERR
+                                              | GNUNET_OS_USE_PIPE_CONTROL
+                                              :
                                               GNUNET_OS_INHERIT_STD_OUT_AND_ERR,
                                               lsocks,
                                               loprefix,
@@ -890,7 +896,11 @@ start_process (struct ServiceList *sl,
                                               options,
                                               NULL);
       else
-        sl->proc = GNUNET_OS_start_process_s (sl->pipe_control,
+        sl->proc = GNUNET_OS_start_process_s (sl->pipe_control
+                                              ?
+                                              GNUNET_OS_INHERIT_STD_OUT_AND_ERR
+                                              | GNUNET_OS_USE_PIPE_CONTROL
+                                              :
                                               GNUNET_OS_INHERIT_STD_OUT_AND_ERR,
                                               lsocks,
                                               loprefix,
@@ -905,7 +915,11 @@ start_process (struct ServiceList *sl,
     else
     {
       if (NULL == sl->config)
-        sl->proc = GNUNET_OS_start_process_s (sl->pipe_control,
+        sl->proc = GNUNET_OS_start_process_s (sl->pipe_control
+                                              ?
+                                              GNUNET_OS_INHERIT_STD_OUT_AND_ERR
+                                              | GNUNET_OS_USE_PIPE_CONTROL
+                                              :
                                               GNUNET_OS_INHERIT_STD_OUT_AND_ERR,
                                               lsocks,
                                               loprefix,
@@ -913,7 +927,11 @@ start_process (struct ServiceList *sl,
                                               options,
                                               NULL);
       else
-        sl->proc = GNUNET_OS_start_process_s (sl->pipe_control,
+        sl->proc = GNUNET_OS_start_process_s (sl->pipe_control
+                                              ?
+                                              GNUNET_OS_INHERIT_STD_OUT_AND_ERR
+                                              | GNUNET_OS_USE_PIPE_CONTROL
+                                              :
                                               GNUNET_OS_INHERIT_STD_OUT_AND_ERR,
                                               lsocks,
                                               loprefix,
@@ -2152,7 +2170,7 @@ main (int argc, char *const *argv)
     GNUNET_MQ_handler_end ()
   };
 
-  sigpipe = GNUNET_DISK_pipe (GNUNET_NO, GNUNET_NO, GNUNET_NO, GNUNET_NO);
+  sigpipe = GNUNET_DISK_pipe (GNUNET_DISK_PF_NONE);
   GNUNET_assert (NULL != sigpipe);
   shc_chld =
     GNUNET_SIGNAL_handler_install (GNUNET_SIGCHLD,
diff --git a/src/arm/mockup_service b/src/arm/mockup_service
new file mode 100755
index 0000000000000000000000000000000000000000..32f4ccc1419c3726211a5515a5efc2d6781e68c4
--- /dev/null
+++ b/src/arm/mockup_service
@@ -0,0 +1,130 @@
+#! /bin/sh
+
+# mockup_service - temporary wrapper script for .libs/mockup_service
+# Generated by ltmain.sh (GNU libtool) 2.2.6
+#
+# The mockup_service program cannot be directly executed until all the libtool
+# libraries that it depends on are installed.
+#
+# This wrapper script should never be moved out of the build directory.
+# If it is, it will not operate correctly.
+
+# Sed substitution that helps us do robust quoting.  It backslashifies
+# metacharacters that are still active within double-quoted strings.
+Xsed='/usr/bin/sed -e 1s/^X//'
+sed_quote_subst='s/\([`"$\\]\)/\\\1/g'
+
+# Be Bourne compatible
+if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then
+  emulate sh
+  NULLCMD=:
+  # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which
+  # is contrary to our usage.  Disable this feature.
+  alias -g '${1+"$@"}'='"$@"'
+  setopt NO_GLOB_SUBST
+else
+  case `(set -o) 2>/dev/null` in *posix*) set -o posix;; esac
+fi
+BIN_SH=xpg4; export BIN_SH # for Tru64
+DUALCASE=1; export DUALCASE # for MKS sh
+
+# The HP-UX ksh and POSIX shell print the target directory to stdout
+# if CDPATH is set.
+(unset CDPATH) >/dev/null 2>&1 && unset CDPATH
+
+relink_command=""
+
+# This environment variable determines our operation mode.
+if test "$libtool_install_magic" = "%%%MAGIC variable%%%"; then
+  # install mode needs the following variables:
+  generated_by_libtool_version='2.2.6'
+  notinst_deplibs=' ../../src/util/libgnunetutil.la'
+else
+  # When we are sourced in execute mode, $file and $ECHO are already set.
+  if test "$libtool_execute_magic" != "%%%MAGIC variable%%%"; then
+    ECHO="echo"
+    file="$0"
+    # Make sure echo works.
+    if test "X$1" = X--no-reexec; then
+      # Discard the --no-reexec flag, and continue.
+      shift
+    elif test "X`{ $ECHO '\t'; } 2>/dev/null`" = 'X\t'; then
+      # Yippee, $ECHO works!
+      :
+    else
+      # Restart under the correct shell, and then maybe $ECHO will work.
+      exec /bin/sh "$0" --no-reexec ${1+"$@"}
+    fi
+  fi
+
+  # Find the directory that this script lives in.
+  thisdir=`$ECHO "X$file" | $Xsed -e 's%/[^/]*$%%'`
+  test "x$thisdir" = "x$file" && thisdir=.
+
+  # Follow symbolic links until we get to the real thisdir.
+  file=`ls -ld "$file" | /usr/bin/sed -n 's/.*-> //p'`
+  while test -n "$file"; do
+    destdir=`$ECHO "X$file" | $Xsed -e 's%/[^/]*$%%'`
+
+    # If there was a directory component, then change thisdir.
+    if test "x$destdir" != "x$file"; then
+      case "$destdir" in
+      [\\/]* | [A-Za-z]:[\\/]*) thisdir="$destdir" ;;
+      *) thisdir="$thisdir/$destdir" ;;
+      esac
+    fi
+
+    file=`$ECHO "X$file" | $Xsed -e 's%^.*/%%'`
+    file=`ls -ld "$thisdir/$file" | /usr/bin/sed -n 's/.*-> //p'`
+  done
+
+
+  # Usually 'no', except on cygwin/mingw when embedded into
+  # the cwrapper.
+  WRAPPER_SCRIPT_BELONGS_IN_OBJDIR=no
+  if test "$WRAPPER_SCRIPT_BELONGS_IN_OBJDIR" = "yes"; then
+    # special case for '.'
+    if test "$thisdir" = "."; then
+      thisdir=`pwd`
+    fi
+    # remove .libs from thisdir
+    case "$thisdir" in
+    *[\\/].libs ) thisdir=`$ECHO "X$thisdir" | $Xsed -e 's%[\\/][^\\/]*$%%'` ;;
+    .libs )   thisdir=. ;;
+    esac
+  fi
+
+  # Try to get the absolute directory name.
+  absdir=`cd "$thisdir" && pwd`
+  test -n "$absdir" && thisdir="$absdir"
+
+  program='mockup_service'
+  progdir="$thisdir/.libs"
+
+
+  if test -f "$progdir/$program"; then
+    # Add our own library path to DYLD_LIBRARY_PATH
+    DYLD_LIBRARY_PATH="/Users/soufi/Career/Munich/TUM/MasterOfScience/Research/GNUnet/EclipseWorkspaceGNUnet/gnunet/src/util/.libs:$DYLD_LIBRARY_PATH"
+
+    # Some systems cannot cope with colon-terminated DYLD_LIBRARY_PATH
+    # The second colon is a workaround for a bug in BeOS R4 sed
+    DYLD_LIBRARY_PATH=`$ECHO "X$DYLD_LIBRARY_PATH" | $Xsed -e 's/::*$//'`
+
+    export DYLD_LIBRARY_PATH
+
+    if test "$libtool_execute_magic" != "%%%MAGIC variable%%%"; then
+      # Run the actual program with our arguments.
+
+      exec "$progdir/$program" ${1+"$@"}
+
+      $ECHO "$0: cannot exec $program $*" 1>&2
+      exit 1
+    fi
+  else
+    # The program doesn't exist.
+    $ECHO "$0: error: \`$progdir/$program' does not exist" 1>&2
+    $ECHO "This script is just a wrapper for $program." 1>&2
+    echo "See the libtool documentation for more information." 1>&2
+    exit 1
+  fi
+fi
diff --git a/src/ats-tests/.gitignore b/src/ats-tests/.gitignore
new file mode 100644
index 0000000000000000000000000000000000000000..5e15db4963b984843e963b565b99e4619eda023a
--- /dev/null
+++ b/src/ats-tests/.gitignore
@@ -0,0 +1,14 @@
+gnunet-solver-eval
+gnunet-ats-sim
+perf_ats_proportional_core_bandwidth
+perf_ats_proportional_core_latency
+perf_ats_proportional_core_none
+perf_ats_proportional_transport_bandwidth
+perf_ats_proportional_transport_latency
+perf_ats_proportional_transport_none
+perf_ats_mlp_core_bandwidth
+perf_ats_mlp_core_latency
+perf_ats_mlp_core_none
+perf_ats_mlp_transport_bandwidth
+perf_ats_mlp_transport_latency
+perf_ats_mlp_transport_none
diff --git a/src/ats-tests/experiments/evaluation1_dru_3_peers_1addr_1scope_prop.conf b/src/ats-tests/experiments/evaluation1_dru_3_peers_1addr_1scope_prop.conf
new file mode 100644
index 0000000000000000000000000000000000000000..4b66e5aea7b1e51affd441317b8f1aae34e4befa
--- /dev/null
+++ b/src/ats-tests/experiments/evaluation1_dru_3_peers_1addr_1scope_prop.conf
@@ -0,0 +1,24 @@
+@INLINE@ template_perf_ats.conf
+
+[transport]
+plugins = unix
+
+[ats]
+MODE = MLP
+UNSPECIFIED_QUOTA_IN = 128 KiB
+UNSPECIFIED_QUOTA_OUT = 128 KiB
+# LOOPBACK
+LOOPBACK_QUOTA_IN = 128 KiB
+LOOPBACK_QUOTA_OUT = 128 KiB
+# LAN
+LAN_QUOTA_IN = 128 KiB
+LAN_QUOTA_OUT = 128 KiB
+# WAN
+WAN_QUOTA_IN = 128 KiB
+WAN_QUOTA_OUT = 128 KiB
+# WLAN
+WLAN_QUOTA_IN = 128 KiB
+WLAN_QUOTA_OUT = 128 KiB
+# BLUETOOTH
+BLUETOOTH_QUOTA_IN = 128 KiB
+BLUETOOTH_QUOTA_OUT = 128 KiB
\ No newline at end of file
diff --git a/src/ats-tests/experiments/evaluation1_dru_3_peers_1addr_1scope_prop.exp b/src/ats-tests/experiments/evaluation1_dru_3_peers_1addr_1scope_prop.exp
new file mode 100644
index 0000000000000000000000000000000000000000..6a04e74913ff47d7150bbd52aa6dd865b55b2b28
--- /dev/null
+++ b/src/ats-tests/experiments/evaluation1_dru_3_peers_1addr_1scope_prop.exp
@@ -0,0 +1,46 @@
+[experiment]
+name = sc1_eval_dru_prop
+masters = 1
+slaves = 3
+max_duration = 20 s
+log_freq = 100 ms
+cfg_file = experiments/evaluation1_dru_3_peers_1addr_1scope_prop.conf
+ 
+[episode-0]
+# operations = start_send, stop_send, start_preference, stop_preference
+duration = 10 s
+op-0-operation = start_send
+op-0-src = 0
+op-0-dest = 0
+op-0-type = constant
+#op-0-period = 10 s
+op-0-base-rate= 10000
+#op-0-max-rate = 10000
+
+op-1-operation = start_send
+op-1-src = 0
+op-1-dest = 1
+op-1-type = constant
+#op-1-period = 10 s
+op-1-base-rate= 10000
+#op-1-max-rate = 10000
+
+op-2-operation = start_send
+op-2-src = 0
+op-2-dest = 2
+op-2-type = constant
+#op-1-period = 10 s
+op-2-base-rate= 10000
+#op-1-max-rate = 10000
+
+[episode-1]
+duration = 10 s
+op-0-operation = start_preference
+op-0-src = 0
+op-0-dest = 2
+op-0-type = constant
+#op-0-period = 10 s
+op-0-pref = bandwidth
+op-0-frequency = 1 s
+op-0-base-rate= 50
+#op-0-max-rate = 10000
\ No newline at end of file
diff --git a/src/ats-tests/experiments/send_linear_10_sec.exp b/src/ats-tests/experiments/send_linear_10_sec.exp
new file mode 100644
index 0000000000000000000000000000000000000000..efd2c7b082afb6e4aed53b0be023e7b8b6500e8d
--- /dev/null
+++ b/src/ats-tests/experiments/send_linear_10_sec.exp
@@ -0,0 +1,30 @@
+[experiment]
+ name = test
+ masters = 1
+ slaves = 3
+ max_duration = 2 s
+ cfg_file = gnunet_ats_sim_default.conf
+ 
+[episode-0]
+# operations = set_rate, start_send, stop_send, set_preference
+duration = 2 s
+op-0-operation = set_rate
+op-0-src = 0
+op-0-dest = 0
+op-0-type = constant
+op-0-base-rate= 10000
+op-0-max-rate = 10000
+
+op-1-operation = set_rate
+op-1-src = 0
+op-1-dest = 1
+op-1-type = constant
+op-1-base-rate= 10000
+op-1-max-rate = 10000
+
+op-2-operation = set_rate
+op-2-src = 0
+op-2-dest = 2
+op-2-type = constant
+op-2-base-rate= 10000
+op-2-max-rate = 10000
\ No newline at end of file
diff --git a/src/ats-tests/experiments/test.exp b/src/ats-tests/experiments/test.exp
new file mode 100644
index 0000000000000000000000000000000000000000..636139f89cec7ad0caefbca7ecd0ed39590b1282
--- /dev/null
+++ b/src/ats-tests/experiments/test.exp
@@ -0,0 +1,55 @@
+[experiment]
+ name = test
+ masters = 1
+ slaves = 2
+ max_duration = 15 s
+ log_freq = 100 ms
+ cfg_file = gnunet_ats_sim_default.conf
+ 
+[episode-0]
+# operations = start_send, stop_send, start_preference, stop_preference
+duration = 10 s
+op-0-operation = start_send
+op-0-src = 0
+op-0-dest = 0
+op-0-type = constant
+op-0-base-rate= 10000
+op-0-max-rate = 10000
+
+op-1-operation = start_send
+op-1-src = 0
+op-1-dest = 1
+op-1-type = sinus
+op-1-period = 5 s
+op-1-base-rate= 10000
+op-1-max-rate = 15000
+
+op-2-operation = start_preference
+op-2-src = 0
+op-2-dest = 0
+op-2-type = constant
+op-2-period = 5 s
+op-2-base-rate= 10
+op-2-max-rate = 5
+op-2-pref = latency
+op-2-frequency = 2 s
+
+op-3-operation = start_preference
+op-3-src = 0
+op-3-dest = 1
+op-3-type = linear
+op-3-period = 5 s
+op-3-base-rate= 40
+op-3-max-rate = 50
+op-3-pref = bandwidth
+op-3-frequency = 750 ms
+
+[episode-1]
+duration = 5 s
+op-0-operation = stop_preference
+op-0-src = 0
+op-0-dest = 0
+
+op-1-operation = stop_preference
+op-1-src = 0
+op-1-dest = 1
diff --git a/src/ats-tests/perf_ats.h b/src/ats-tests/perf_ats.h
new file mode 100644
index 0000000000000000000000000000000000000000..6460aa098bf440b4de6d5aa7090c5da0a0c6e94f
--- /dev/null
+++ b/src/ats-tests/perf_ats.h
@@ -0,0 +1,256 @@
+/*
+   This file is part of GNUnet.
+   Copyright (C) 2010-2013 GNUnet e.V.
+
+   GNUnet is free software: you can redistribute it and/or modify it
+   under the terms of the GNU Affero General Public License as published
+   by the Free Software Foundation, either version 3 of the License,
+   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
+   Affero General Public License for more details.
+
+   You should have received a copy of the GNU Affero General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+     SPDX-License-Identifier: AGPL3.0-or-later
+ */
+/**
+ * @file ats/perf_ats.c
+ * @brief ats benchmark: start peers and modify preferences, monitor change over time
+ * @author Christian Grothoff
+ * @author Matthias Wachs
+ */
+#include "platform.h"
+#include "gnunet_util_lib.h"
+#include "gnunet_testbed_service.h"
+#include "gnunet_ats_service.h"
+#include "gnunet_core_service.h"
+#include "ats-testing.h"
+
+#define TEST_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, \
+                                                    120)
+#define BENCHMARK_DURATION GNUNET_TIME_relative_multiply ( \
+    GNUNET_TIME_UNIT_SECONDS, 10)
+#define LOGGING_FREQUENCY GNUNET_TIME_relative_multiply ( \
+    GNUNET_TIME_UNIT_MILLISECONDS, 500)
+#define TESTNAME_PREFIX "perf_ats_"
+#define DEFAULT_SLAVES_NUM 2
+#define DEFAULT_MASTERS_NUM 1
+
+#define TEST_ATS_PREFRENCE_FREQUENCY GNUNET_TIME_relative_multiply ( \
+    GNUNET_TIME_UNIT_SECONDS, 1)
+#define TEST_ATS_PREFRENCE_START 1.0
+#define TEST_ATS_PREFRENCE_DELTA 1.0
+
+#define TEST_MESSAGE_TYPE_PING 12345
+#define TEST_MESSAGE_TYPE_PONG 12346
+#define TEST_MESSAGE_SIZE 1000
+#define TEST_MESSAGE_FREQUENCY GNUNET_TIME_relative_multiply ( \
+    GNUNET_TIME_UNIT_SECONDS, 1)
+
+/**
+ * Information about a benchmarking partner
+ */
+struct BenchmarkPartner
+{
+  /**
+   * The peer itself this partner belongs to
+   */
+  struct BenchmarkPeer *me;
+
+  /**
+   * The partner peer
+   */
+  struct BenchmarkPeer *dest;
+
+  /**
+   * Core transmit handles
+   */
+  struct GNUNET_CORE_TransmitHandle *cth;
+
+  /**
+   * Transport transmit handles
+   */
+  struct GNUNET_TRANSPORT_TransmitHandle *tth;
+
+  /**
+   * Timestamp to calculate communication layer delay
+   */
+  struct GNUNET_TIME_Absolute last_message_sent;
+
+  /**
+   * Accumulated RTT for all messages
+   */
+  unsigned int total_app_rtt;
+
+  /**
+   * Number of messages sent to this partner
+   */
+  unsigned int messages_sent;
+
+  /**
+   * Number of bytes sent to this partner
+   */
+  unsigned int bytes_sent;
+
+  /**
+   * Number of messages received from this partner
+   */
+  unsigned int messages_received;
+
+  /**
+   * Number of bytes received from this partner
+   */
+  unsigned int bytes_received;
+
+  /* Current ATS properties */
+
+  uint32_t ats_distance;
+
+  uint32_t ats_delay;
+
+  uint32_t bandwidth_in;
+
+  uint32_t bandwidth_out;
+
+  uint32_t ats_utilization_up;
+
+  uint32_t ats_utilization_down;
+
+  uint32_t ats_network_type;
+
+  uint32_t ats_cost_wan;
+
+  uint32_t ats_cost_lan;
+
+  uint32_t ats_cost_wlan;
+};
+
+
+/**
+ * Information we track for a peer in the testbed.
+ */
+struct BenchmarkPeer
+{
+  /**
+   * Handle with testbed.
+   */
+  struct GNUNET_TESTBED_Peer *peer;
+
+  /**
+   * Unique identifier
+   */
+  int no;
+
+  /**
+   * Is this peer a measter: GNUNET_YES/GNUNET_NO
+   */
+  int master;
+
+  /**
+   *  Peer ID
+   */
+  struct GNUNET_PeerIdentity id;
+
+  /**
+   * Testbed operation to get peer information
+   */
+  struct GNUNET_TESTBED_Operation *peer_id_op;
+
+  /**
+   * Testbed operation to connect to ATS performance service
+   */
+  struct GNUNET_TESTBED_Operation *ats_perf_op;
+
+  /**
+   * Testbed operation to connect to core
+   */
+  struct GNUNET_TESTBED_Operation *comm_op;
+
+  /**
+   * ATS performance handle
+   */
+  struct GNUNET_ATS_PerformanceHandle *ats_perf_handle;
+
+  /**
+   * Masters only:
+   * Testbed connect operations to connect masters to slaves
+   */
+  struct TestbedConnectOperation *core_connect_ops;
+
+  /**
+   *  Core handle
+   */
+  struct GNUNET_CORE_Handle *ch;
+
+  /**
+   *  Core handle
+   */
+  struct GNUNET_TRANSPORT_Handle *th;
+
+  /**
+   * Masters only:
+   * Peer to set ATS preferences for
+   */
+  struct BenchmarkPeer *pref_partner;
+
+  /**
+   * Masters only
+   * Progress task
+   */
+  struct GNUNET_SCHEDULER_Task *ats_task;
+
+  /**
+   * Masters only
+   * Progress task
+   */
+  double pref_value;
+
+  /**
+   * Array of partners with num_slaves entries (if master) or
+   * num_master entries (if slave)
+   */
+  struct BenchmarkPartner *partners;
+
+  /**
+   * Number of partners
+   */
+  int num_partners;
+
+  /**
+   * Number of core connections
+   */
+  int core_connections;
+
+  /**
+   * Masters only:
+   * Number of connections to slave peers
+   */
+  int core_slave_connections;
+
+  /**
+   * Total number of messages this peer has sent
+   */
+  unsigned int total_messages_sent;
+
+  /**
+   * Total number of bytes this peer has sent
+   */
+  unsigned int total_bytes_sent;
+
+  /**
+   * Total number of messages this peer has received
+   */
+  unsigned int total_messages_received;
+
+  /**
+   * Total number of bytes this peer has received
+   */
+  unsigned int total_bytes_received;
+};
+
+
+/* end of file perf_ats.h */
diff --git a/src/ats-tests/perf_ats_logging.c b/src/ats-tests/perf_ats_logging.c
new file mode 100644
index 0000000000000000000000000000000000000000..ac8fa8950d62e00350778df5054aad8f1adff64a
--- /dev/null
+++ b/src/ats-tests/perf_ats_logging.c
@@ -0,0 +1,780 @@
+/*
+   This file is part of GNUnet.
+   Copyright (C) 2010-2013 GNUnet e.V.
+
+   GNUnet is free software: you can redistribute it and/or modify it
+   under the terms of the GNU Affero General Public License as published
+   by the Free Software Foundation, either version 3 of the License,
+   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
+   Affero General Public License for more details.
+
+   You should have received a copy of the GNU Affero General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+     SPDX-License-Identifier: AGPL3.0-or-later
+ */
+/**
+ * @file ats/perf_ats_logging.c
+ * @brief ats benchmark: logging for performance tests
+ * @author Christian Grothoff
+ * @author Matthias Wachs
+ */
+#include "platform.h"
+#include "gnunet_util_lib.h"
+#include "perf_ats.h"
+
+#define THROUGHPUT_TEMPLATE "#!/usr/bin/gnuplot \n" \
+  "set datafile separator ';' \n" \
+  "set title \"Throughput between Master and Slaves\" \n" \
+  "set xlabel \"Time in ms\" \n" \
+  "set ylabel \"Bytes/s\" \n" \
+  "set grid \n"
+
+#define RTT_TEMPLATE "#!/usr/bin/gnuplot \n" \
+  "set datafile separator ';' \n" \
+  "set title \"Application level roundtrip time between Master and Slaves\" \n" \
+  "set xlabel \"Time in ms\" \n" \
+  "set ylabel \"ms\" \n" \
+  "set grid \n"
+
+#define BW_TEMPLATE "#!/usr/bin/gnuplot \n" \
+  "set datafile separator ';' \n" \
+  "set title \"Bandwidth inbound and outbound between Master and Slaves\" \n" \
+  "set xlabel \"Time in ms\" \n" \
+  "set ylabel \"Bytes / s \" \n" \
+  "set grid \n"
+
+#define LOG_ITEMS_TIME 2
+#define LOG_ITEMS_PER_PEER 17
+
+#define LOG_ITEM_BYTES_SENT 1
+#define LOG_ITEM_MSGS_SENT 2
+#define LOG_ITEM_THROUGHPUT_SENT 3
+#define LOG_ITEM_BYTES_RECV 4
+#define LOG_ITEM_MSGS_RECV 5
+#define LOG_ITEM_THROUGHPUT_RECV 6
+#define LOG_ITEM_APP_RTT 7
+#define LOG_ITEM_ATS_BW_IN 8
+#define LOG_ITEM_ATS_BW_OUT 9
+#define LOG_ITEM_ATS_COSTS_LAN 10
+#define LOG_ITEM_ATS_WAN 11
+#define LOG_ITEM_ATS_WLAN 12
+#define LOG_ITEM_ATS_DELAY 13
+#define LOG_ITEM_ATS_DISTANCE 14
+#define LOG_ITEM_ATS_NETWORKTYPE 15
+#define LOG_ITEM_ATS_UTIL_UP 16
+#define LOG_ITEM_ATS_UTIL_DOWN 17
+
+/**
+ * Logging task
+ */
+static struct GNUNET_SCHEDULER_Task *log_task;
+
+/**
+ * Reference to perf_ats' masters
+ */
+static int num_peers;
+static int running;
+static char *name;
+static struct GNUNET_TIME_Relative frequency;
+
+/**
+ * A single logging time step for a partner
+ */
+struct PartnerLoggingTimestep
+{
+  /**
+   * Peer
+   */
+  struct BenchmarkPeer *slave;
+
+  /**
+   * Total number of messages this peer has sent
+   */
+  unsigned int total_messages_sent;
+
+  /**
+   * Total number of bytes this peer has sent
+   */
+  unsigned int total_bytes_sent;
+
+  /**
+   * Total number of messages this peer has received
+   */
+  unsigned int total_messages_received;
+
+  /**
+   * Total number of bytes this peer has received
+   */
+  unsigned int total_bytes_received;
+
+  /**
+   * Total outbound throughput for master in Bytes / s
+   */
+  unsigned int throughput_sent;
+
+  /**
+   * Total inbound throughput for master in Bytes / s
+   */
+  unsigned int throughput_recv;
+
+  /**
+   * Accumulated RTT for all messages
+   */
+  unsigned int total_app_rtt;
+
+  /**
+   * Current application level delay
+   */
+  unsigned int app_rtt;
+
+  /* Current ATS properties */
+
+  uint32_t ats_distance;
+
+  uint32_t ats_delay;
+
+  uint32_t bandwidth_in;
+
+  uint32_t bandwidth_out;
+
+  uint32_t ats_utilization_up;
+
+  uint32_t ats_utilization_down;
+
+  uint32_t ats_network_type;
+
+  uint32_t ats_cost_wan;
+
+  uint32_t ats_cost_lan;
+
+  uint32_t ats_cost_wlan;
+};
+
+
+/**
+ * A single logging time step for a peer
+ */
+struct PeerLoggingTimestep
+{
+  /**
+   * Next in DLL
+   */
+  struct PeerLoggingTimestep *next;
+
+  /**
+   * Prev in DLL
+   */
+  struct PeerLoggingTimestep *prev;
+
+  /**
+   * Logging timestamp
+   */
+  struct GNUNET_TIME_Absolute timestamp;
+
+  /**
+   * Total number of messages this peer has sent
+   */
+  unsigned int total_messages_sent;
+
+  /**
+   * Total number of bytes this peer has sent
+   */
+  unsigned int total_bytes_sent;
+
+  /**
+   * Total number of messages this peer has received
+   */
+  unsigned int total_messages_received;
+
+  /**
+   * Total number of bytes this peer has received
+   */
+  unsigned int total_bytes_received;
+
+  /**
+   * Total outbound throughput for master in Bytes / s
+   */
+  unsigned int total_throughput_send;
+
+  /**
+   * Total inbound throughput for master in Bytes / s
+   */
+  unsigned int total_throughput_recv;
+
+  /**
+   * Logs for slaves
+   */
+  struct PartnerLoggingTimestep *slaves_log;
+};
+
+/**
+ * Entry for a benchmark peer
+ */
+struct LoggingPeer
+{
+  /**
+   * Peer
+   */
+  struct BenchmarkPeer *peer;
+
+  /**
+   * Start time
+   */
+  struct GNUNET_TIME_Absolute start;
+
+  /**
+   * DLL for logging entries: head
+   */
+  struct PeerLoggingTimestep *head;
+
+  /**
+   * DLL for logging entries: tail
+   */
+  struct PeerLoggingTimestep *tail;
+};
+
+/**
+ * Log structure of length num_peers
+ */
+static struct LoggingPeer *lp;
+
+
+static void
+write_throughput_gnuplot_script (char *fn, struct LoggingPeer *lp)
+{
+  struct GNUNET_DISK_FileHandle *f;
+  char *gfn;
+  char *data;
+  int c_s;
+  int peer_index;
+
+  GNUNET_asprintf (&gfn, "gnuplot_throughput_%s", fn);
+  f = GNUNET_DISK_file_open (gfn,
+                             GNUNET_DISK_OPEN_WRITE | GNUNET_DISK_OPEN_CREATE,
+                             GNUNET_DISK_PERM_USER_EXEC
+                             | GNUNET_DISK_PERM_USER_READ
+                             | GNUNET_DISK_PERM_USER_WRITE);
+  if (NULL == f)
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Cannot open gnuplot file `%s'\n",
+                gfn);
+    GNUNET_free (gfn);
+    return;
+  }
+
+  /* Write header */
+
+  if (GNUNET_SYSERR == GNUNET_DISK_file_write (f, THROUGHPUT_TEMPLATE, strlen (
+                                                 THROUGHPUT_TEMPLATE)))
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                "Cannot write data to plot file `%s'\n", gfn);
+
+  /* Write master data */
+  peer_index = LOG_ITEMS_TIME;
+  GNUNET_asprintf (&data,
+                   "plot '%s' using 2:%u with lines title 'Master %u send total', \\\n" \
+                   "'%s' using 2:%u with lines title 'Master %u receive total', \\\n",
+                   fn, peer_index + LOG_ITEM_THROUGHPUT_SENT, lp->peer->no,
+                   fn, peer_index + LOG_ITEM_THROUGHPUT_RECV, lp->peer->no);
+  if (GNUNET_SYSERR == GNUNET_DISK_file_write (f, data, strlen (data)))
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                "Cannot write data to plot file `%s'\n", gfn);
+  GNUNET_free (data);
+
+  peer_index = LOG_ITEMS_TIME + LOG_ITEMS_PER_PEER;
+  for (c_s = 0; c_s < lp->peer->num_partners; c_s++)
+  {
+    GNUNET_asprintf (&data,
+                     "'%s' using 2:%u with lines title 'Master %u - Slave %u send', \\\n" \
+                     "'%s' using 2:%u with lines title 'Master %u - Slave %u receive'%s\n",
+                     fn, peer_index + LOG_ITEM_THROUGHPUT_SENT, lp->peer->no,
+                     lp->peer->partners[c_s].dest->no,
+                     fn, peer_index + LOG_ITEM_THROUGHPUT_RECV, lp->peer->no,
+                     lp->peer->partners[c_s].dest->no,
+                     (c_s < lp->peer->num_partners - 1) ? ", \\" :
+                     "\n pause -1");
+    if (GNUNET_SYSERR == GNUNET_DISK_file_write (f, data, strlen (data)))
+      GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                  "Cannot write data to plot file `%s'\n", gfn);
+    GNUNET_free (data);
+    peer_index += LOG_ITEMS_PER_PEER;
+  }
+
+  if (GNUNET_SYSERR == GNUNET_DISK_file_close (f))
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Cannot close gnuplot file `%s'\n",
+                gfn);
+  else
+    GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+                "Data successfully written to plot file `%s'\n", gfn);
+
+  GNUNET_free (gfn);
+}
+
+
+static void
+write_rtt_gnuplot_script (char *fn, struct LoggingPeer *lp)
+{
+  struct GNUNET_DISK_FileHandle *f;
+  char *gfn;
+  char *data;
+  int c_s;
+  int index;
+
+  GNUNET_asprintf (&gfn, "gnuplot_rtt_%s", fn);
+  f = GNUNET_DISK_file_open (gfn,
+                             GNUNET_DISK_OPEN_WRITE | GNUNET_DISK_OPEN_CREATE,
+                             GNUNET_DISK_PERM_USER_EXEC
+                             | GNUNET_DISK_PERM_USER_READ
+                             | GNUNET_DISK_PERM_USER_WRITE);
+  if (NULL == f)
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Cannot open gnuplot file `%s'\n",
+                gfn);
+    GNUNET_free (gfn);
+    return;
+  }
+
+  /* Write header */
+
+  if (GNUNET_SYSERR == GNUNET_DISK_file_write (f, RTT_TEMPLATE, strlen (
+                                                 RTT_TEMPLATE)))
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                "Cannot write data to plot file `%s'\n", gfn);
+
+  index = LOG_ITEMS_TIME + LOG_ITEMS_PER_PEER;
+  for (c_s = 0; c_s < lp->peer->num_partners; c_s++)
+  {
+    GNUNET_asprintf (&data,
+                     "%s'%s' using 2:%u with lines title 'Master %u - Slave %u '%s\n",
+                     (0 == c_s) ? "plot " : "",
+                     fn, index + LOG_ITEM_APP_RTT, lp->peer->no,
+                     lp->peer->partners[c_s].dest->no,
+                     (c_s < lp->peer->num_partners - 1) ? ", \\" :
+                     "\n pause -1");
+    if (GNUNET_SYSERR == GNUNET_DISK_file_write (f, data, strlen (data)))
+      GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                  "Cannot write data to plot file `%s'\n", gfn);
+    GNUNET_free (data);
+    index += LOG_ITEMS_PER_PEER;
+  }
+
+  if (GNUNET_SYSERR == GNUNET_DISK_file_close (f))
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Cannot close gnuplot file `%s'\n",
+                gfn);
+  else
+    GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+                "Data successfully written to plot file `%s'\n", gfn);
+  GNUNET_free (gfn);
+}
+
+
+static void
+write_bw_gnuplot_script (char *fn, struct LoggingPeer *lp)
+{
+  struct GNUNET_DISK_FileHandle *f;
+  char *gfn;
+  char *data;
+  int c_s;
+  int index;
+
+  GNUNET_asprintf (&gfn, "gnuplot_bw_%s", fn);
+  f = GNUNET_DISK_file_open (gfn,
+                             GNUNET_DISK_OPEN_WRITE | GNUNET_DISK_OPEN_CREATE,
+                             GNUNET_DISK_PERM_USER_EXEC
+                             | GNUNET_DISK_PERM_USER_READ
+                             | GNUNET_DISK_PERM_USER_WRITE);
+  if (NULL == f)
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Cannot open gnuplot file `%s'\n",
+                gfn);
+    GNUNET_free (gfn);
+    return;
+  }
+
+  /* Write header */
+
+  if (GNUNET_SYSERR == GNUNET_DISK_file_write (f, BW_TEMPLATE, strlen (
+                                                 BW_TEMPLATE)))
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                "Cannot write data to plot file `%s'\n", gfn);
+
+  index = LOG_ITEMS_TIME + LOG_ITEMS_PER_PEER;
+  for (c_s = 0; c_s < lp->peer->num_partners; c_s++)
+  {
+    GNUNET_asprintf (&data, "%s" \
+                     "'%s' using 2:%u with lines title 'BW out master %u - Slave %u ', \\\n" \
+                     "'%s' using 2:%u with lines title 'BW in master %u - Slave %u '" \
+                     "%s\n",
+                     (0 == c_s) ? "plot " : "",
+                     fn, index + LOG_ITEM_ATS_BW_OUT, lp->peer->no,
+                     lp->peer->partners[c_s].dest->no,
+                     fn, index + LOG_ITEM_ATS_BW_IN, lp->peer->no,
+                     lp->peer->partners[c_s].dest->no,
+                     (c_s < lp->peer->num_partners - 1) ? ", \\" :
+                     "\n pause -1");
+    if (GNUNET_SYSERR == GNUNET_DISK_file_write (f, data, strlen (data)))
+      GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                  "Cannot write data to plot file `%s'\n", gfn);
+    GNUNET_free (data);
+    index += LOG_ITEMS_PER_PEER;
+  }
+
+  if (GNUNET_SYSERR == GNUNET_DISK_file_close (f))
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Cannot close gnuplot file `%s'\n",
+                gfn);
+  else
+    GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+                "Data successfully written to plot file `%s'\n", gfn);
+  GNUNET_free (gfn);
+}
+
+
+static void
+write_to_file ()
+{
+  struct GNUNET_DISK_FileHandle *f;
+
+  char *filename;
+  char *data;
+  char *slave_string;
+  char *slave_string_tmp;
+  struct PeerLoggingTimestep *cur_lt;
+  struct PartnerLoggingTimestep *plt;
+  int c_m;
+  int c_s;
+
+  for (c_m = 0; c_m < num_peers; c_m++)
+  {
+    GNUNET_asprintf (&filename, "%llu_master_%u_%s_%s.data",
+                     GNUNET_TIME_absolute_get ().abs_value_us,
+                     lp[c_m].peer->no, GNUNET_i2s (&lp[c_m].peer->id), name);
+
+    f = GNUNET_DISK_file_open (filename,
+                               GNUNET_DISK_OPEN_WRITE | GNUNET_DISK_OPEN_CREATE,
+                               GNUNET_DISK_PERM_USER_READ
+                               | GNUNET_DISK_PERM_USER_WRITE);
+    if (NULL == f)
+    {
+      GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Cannot open log file `%s'\n",
+                  filename);
+      GNUNET_free (filename);
+      return;
+    }
+
+    for (cur_lt = lp[c_m].head; NULL != cur_lt; cur_lt = cur_lt->next)
+    {
+      GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+                  "Master [%u]: timestamp %llu %llu ; %u %u %u ; %u %u %u\n",
+                  lp[c_m].peer->no,
+                  cur_lt->timestamp, GNUNET_TIME_absolute_get_difference (
+                    lp[c_m].start, cur_lt->timestamp).rel_value_us / 1000,
+                  cur_lt->total_messages_sent, cur_lt->total_bytes_sent,
+                  cur_lt->total_throughput_send,
+                  cur_lt->total_messages_received, cur_lt->total_bytes_received,
+                  cur_lt->total_throughput_recv);
+
+      slave_string = GNUNET_strdup (";");
+      for (c_s = 0; c_s < lp[c_m].peer->num_partners; c_s++)
+      {
+        plt = &cur_lt->slaves_log[c_s];
+        /* Log partners */
+
+        /* Assembling slave string */
+        GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+                    "\t Slave [%u]: %u %u %u ; %u %u %u rtt %u delay %u bw_in %u bw_out %u \n",
+                    plt->slave->no,
+                    plt->total_messages_sent, plt->total_bytes_sent,
+                    plt->throughput_sent,
+                    plt->total_messages_received, plt->total_bytes_received,
+                    plt->throughput_recv,
+                    plt->app_rtt, plt->ats_delay,
+                    plt->bandwidth_in, plt->bandwidth_out);
+
+        GNUNET_asprintf (&slave_string_tmp,
+                         "%s%u;%u;%u;%u;%u;%u;%.3f;%u;%u;%u;%u;%u;%u;%u;%u;%u;%u;",
+                         slave_string,
+                         plt->total_messages_sent, plt->total_bytes_sent,
+                         plt->throughput_sent,
+                         plt->total_messages_received,
+                         plt->total_bytes_received, plt->throughput_sent,
+                         (double) plt->app_rtt / 1000,
+                         plt->bandwidth_in, plt->bandwidth_out,
+                         plt->ats_cost_lan, plt->ats_cost_wan,
+                         plt->ats_cost_wlan,
+                         plt->ats_delay, plt->ats_distance,
+                         plt->ats_network_type,
+                         plt->ats_utilization_up, plt->ats_utilization_down);
+        GNUNET_free (slave_string);
+        slave_string = slave_string_tmp;
+      }
+      /* Assembling master string */
+
+
+      GNUNET_asprintf (&data, "%llu;%llu;%u;%u;%u;%u;%u;%u;;;;;;;;;;;%s\n",
+                       cur_lt->timestamp,
+                       GNUNET_TIME_absolute_get_difference (lp[c_m].start,
+                                                            cur_lt->timestamp).
+                       rel_value_us / 1000,
+                       cur_lt->total_messages_sent, cur_lt->total_bytes_sent,
+                       cur_lt->total_throughput_send,
+                       cur_lt->total_messages_received,
+                       cur_lt->total_bytes_received,
+                       cur_lt->total_throughput_recv,
+                       slave_string);
+      GNUNET_free (slave_string);
+
+      if (GNUNET_SYSERR == GNUNET_DISK_file_write (f, data, strlen (data)))
+        GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                    "Cannot write data to log file `%s'\n", filename);
+      GNUNET_free (data);
+    }
+    if (GNUNET_SYSERR == GNUNET_DISK_file_close (f))
+    {
+      GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Cannot close log file `%s'\n",
+                  filename);
+      GNUNET_free (filename);
+      return;
+    }
+
+    write_throughput_gnuplot_script (filename, lp);
+    write_rtt_gnuplot_script (filename, lp);
+    write_bw_gnuplot_script (filename, lp);
+
+    GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+                "Data file successfully written to log file `%s'\n", filename);
+    GNUNET_free (filename);
+  }
+}
+
+
+void
+collect_log_now (void)
+{
+  struct LoggingPeer *bp;
+  struct PeerLoggingTimestep *mlt;
+  struct PeerLoggingTimestep *prev_log_mlt;
+  struct PartnerLoggingTimestep *slt;
+  struct PartnerLoggingTimestep *prev_log_slt;
+  struct BenchmarkPartner *p;
+  struct GNUNET_TIME_Relative delta;
+  int c_s;
+  int c_m;
+  unsigned int app_rtt;
+  double mult;
+
+  if (GNUNET_YES != running)
+    return;
+
+  for (c_m = 0; c_m < num_peers; c_m++)
+  {
+    bp = &lp[c_m];
+    mlt = GNUNET_new (struct PeerLoggingTimestep);
+    GNUNET_CONTAINER_DLL_insert_tail (bp->head, bp->tail, mlt);
+    prev_log_mlt = mlt->prev;
+
+    /* Collect data */
+
+    /* Current master state */
+    mlt->timestamp = GNUNET_TIME_absolute_get ();
+    mlt->total_bytes_sent = bp->peer->total_bytes_sent;
+    mlt->total_messages_sent = bp->peer->total_messages_sent;
+    mlt->total_bytes_received = bp->peer->total_bytes_received;
+    mlt->total_messages_received = bp->peer->total_messages_received;
+
+    /* Throughput */
+    if (NULL == prev_log_mlt)
+    {
+      /* Get difference to start */
+      delta = GNUNET_TIME_absolute_get_difference (lp[c_m].start,
+                                                   mlt->timestamp);
+    }
+    else
+    {
+      /* Get difference to last timestep */
+      delta = GNUNET_TIME_absolute_get_difference (mlt->prev->timestamp,
+                                                   mlt->timestamp);
+    }
+
+    /* Multiplication factor for throughput calculation */
+    mult = (1.0 * 1000 * 1000) / (delta.rel_value_us);
+
+    /* Total throughput */
+    if (NULL != prev_log_mlt)
+    {
+      if (mlt->total_bytes_sent - mlt->prev->total_bytes_sent > 0)
+        mlt->total_throughput_send = mult * (mlt->total_bytes_sent
+                                             - mlt->prev->total_bytes_sent);
+      else
+        mlt->total_throughput_send = prev_log_mlt->total_throughput_send;     /* no msgs send */
+
+      if (mlt->total_bytes_received - mlt->prev->total_bytes_received > 0)
+        mlt->total_throughput_recv = mult * (mlt->total_bytes_received
+                                             - mlt->prev->total_bytes_received);
+      else
+        mlt->total_throughput_recv = prev_log_mlt->total_throughput_recv;     /* no msgs received */
+    }
+    else
+    {
+      mlt->total_throughput_send = mult * mlt->total_bytes_sent;
+      mlt->total_throughput_send = mult * mlt->total_bytes_received;
+    }
+
+    mlt->slaves_log = GNUNET_malloc (bp->peer->num_partners
+                                     * sizeof(struct PartnerLoggingTimestep));
+
+    for (c_s = 0; c_s < bp->peer->num_partners; c_s++)
+    {
+      p = &bp->peer->partners[c_s];
+      slt = &mlt->slaves_log[c_s];
+
+      slt->slave = p->dest;
+      /* Bytes sent from master to this slave */
+      slt->total_bytes_sent = p->bytes_sent;
+      /* Messages sent from master to this slave */
+      slt->total_messages_sent = p->messages_sent;
+      /* Bytes master received from this slave */
+      slt->total_bytes_received = p->bytes_received;
+      /* Messages master received from this slave */
+      slt->total_messages_received = p->messages_received;
+      slt->total_app_rtt = p->total_app_rtt;
+      /* ats performance information */
+      slt->ats_cost_lan = p->ats_cost_lan;
+      slt->ats_cost_wan = p->ats_cost_wan;
+      slt->ats_cost_wlan = p->ats_cost_wlan;
+      slt->ats_delay = p->ats_delay;
+      slt->ats_distance = p->ats_distance;
+      slt->ats_network_type = p->ats_network_type;
+      slt->ats_utilization_down = p->ats_utilization_down;
+      slt->ats_utilization_up = p->ats_utilization_up;
+      slt->bandwidth_in = p->bandwidth_in;
+      slt->bandwidth_out = p->bandwidth_out;
+
+      /* Total application level rtt  */
+      if (NULL == prev_log_mlt)
+      {
+        if (0 != slt->total_messages_sent)
+          app_rtt = slt->total_app_rtt / slt->total_messages_sent;
+        else
+          app_rtt = 0;
+      }
+      else
+      {
+        prev_log_slt = &prev_log_mlt->slaves_log[c_s];
+        if ((slt->total_messages_sent - prev_log_slt->total_messages_sent) > 0)
+          app_rtt = (slt->total_app_rtt - prev_log_slt->total_app_rtt)
+                    / (slt->total_messages_sent
+                       - prev_log_slt->total_messages_sent);
+        else
+          app_rtt = prev_log_slt->app_rtt;       /* No messages were */
+      }
+      slt->app_rtt = app_rtt;
+
+      /* Partner throughput */
+      if (NULL != prev_log_mlt)
+      {
+        prev_log_slt = &prev_log_mlt->slaves_log[c_s];
+        if (slt->total_bytes_sent - prev_log_slt->total_bytes_sent > 0)
+          slt->throughput_sent = mult * (slt->total_bytes_sent
+                                         - prev_log_slt->total_bytes_sent);
+        else
+          slt->throughput_sent = prev_log_slt->throughput_sent;       /* no msgs send */
+
+        if (slt->total_bytes_received - prev_log_slt->total_bytes_received > 0)
+          slt->throughput_recv = mult * (slt->total_bytes_received
+                                         - prev_log_slt->total_bytes_received);
+        else
+          slt->throughput_recv = prev_log_slt->throughput_recv;       /* no msgs received */
+      }
+      else
+      {
+        slt->throughput_sent = mult * slt->total_bytes_sent;
+        slt->throughput_sent = mult * slt->total_bytes_received;
+      }
+
+      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                  "Master [%u]: slave [%u]\n",
+                  bp->peer->no, p->dest->no);
+    }
+  }
+}
+
+
+static void
+collect_log_task (void *cls)
+{
+  log_task = NULL;
+  collect_log_now ();
+  log_task = GNUNET_SCHEDULER_add_delayed (frequency,
+                                           &collect_log_task, NULL);
+}
+
+
+void
+perf_logging_stop ()
+{
+  int c_m;
+  struct PeerLoggingTimestep *cur;
+
+  if (GNUNET_YES != running)
+    return;
+
+  if (NULL != log_task)
+  {
+    GNUNET_SCHEDULER_cancel (log_task);
+    log_task = NULL;
+  }
+  collect_log_task (NULL);
+
+  GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+              _ ("Stop logging\n"));
+
+  write_to_file ();
+
+  for (c_m = 0; c_m < num_peers; c_m++)
+  {
+    while (NULL != (cur = lp[c_m].head))
+    {
+      GNUNET_CONTAINER_DLL_remove (lp[c_m].head, lp[c_m].tail, cur);
+      GNUNET_free (cur->slaves_log);
+      GNUNET_free (cur);
+    }
+  }
+
+  GNUNET_free (lp);
+}
+
+
+void
+perf_logging_start (struct GNUNET_TIME_Relative log_frequency,
+                    char *testname, struct BenchmarkPeer *masters, int
+                    num_masters)
+{
+  int c_m;
+
+  GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+              _ ("Start logging `%s'\n"), testname);
+
+  num_peers = num_masters;
+  name = testname;
+  frequency = log_frequency;
+
+  lp = GNUNET_malloc (num_masters * sizeof(struct LoggingPeer));
+
+  for (c_m = 0; c_m < num_masters; c_m++)
+  {
+    lp[c_m].peer = &masters[c_m];
+    lp[c_m].start = GNUNET_TIME_absolute_get ();
+  }
+
+  /* Schedule logging task */
+  log_task = GNUNET_SCHEDULER_add_now (&collect_log_task, NULL);
+  running = GNUNET_YES;
+}
+
+
+/* end of file perf_ats_logging.c */
diff --git a/src/ats-tests/template_perf_ats.conf b/src/ats-tests/template_perf_ats.conf
new file mode 100644
index 0000000000000000000000000000000000000000..74f608bfbc222a00544bca82a80a4f873fe28b1d
--- /dev/null
+++ b/src/ats-tests/template_perf_ats.conf
@@ -0,0 +1,52 @@
+@INLINE@ ../../contrib/conf/gnunet/no_forcestart.conf
+
+[testbed]
+# How long should operations wait?
+OPERATION_TIMEOUT = 60 s
+
+[transport-udp]
+BROADCAST = NO
+
+[peerinfo]
+USE_INCLUDED_HELLOS = NO
+
+[transport]
+#PREFIX = valgrind --leak-check=yes
+
+[ats]
+# PREFIX = valgrind
+
+# Network specific inbound/outbound quotas
+UNSPECIFIED_QUOTA_IN = 128 KiB
+UNSPECIFIED_QUOTA_OUT = 128 KiB
+# LOOPBACK
+LOOPBACK_QUOTA_IN = 128 KiB
+LOOPBACK_QUOTA_OUT = 128 KiB
+# LAN
+LAN_QUOTA_IN = 128 KiB
+LAN_QUOTA_OUT = 128 KiB
+# WAN
+WAN_QUOTA_IN = 128 KiB
+WAN_QUOTA_OUT = 128 KiB
+# WLAN
+WLAN_QUOTA_IN = 128 KiB
+WLAN_QUOTA_OUT = 128 KiB
+# BLUETOOTH
+BLUETOOTH_QUOTA_IN = 128 KiB
+BLUETOOTH_QUOTA_OUT = 128 KiB
+
+[transport-blacklist-M1RGJB4FQSM17JJ3M9BF7Q0I8MCO8C462NMOHI26RLT7C7A2KE6HCOPRA4ARM5HPL1J9IDDK5G8SFU5GUSHCTBH90ECETK1BFQD76R0]
+HIJN5O404QNUR37OSJUTNJ6H2KJS198DHI2J3I8SE3DMKVRG1RNQPODN1IJBF14KEMPPPRM0B9F9ILFKHOFCA655CH6M5OCNCMR0FE0 =
+CDTU8QQ8UPLGHR3B91V0CLTDOHONLB8QGHGUEM2JM1GANTEV0O6T20SD2N2HDN2QSHDG6IDTBR48KRDCS601FI6VHG59E7DQA98JD2O =
+
+[transport-blacklist-93ARIS6Q347RPU9EFPS9LA00VPHQLG3RBLKEKTHV4D6UVGEAC75KIIBFB5U9KK9P9P1RU1CBPV4BSSDUTB2AL2N2LG9KSO9APQNLS0O]
+HIJN5O404QNUR37OSJUTNJ6H2KJS198DHI2J3I8SE3DMKVRG1RNQPODN1IJBF14KEMPPPRM0B9F9ILFKHOFCA655CH6M5OCNCMR0FE0 =
+CDTU8QQ8UPLGHR3B91V0CLTDOHONLB8QGHGUEM2JM1GANTEV0O6T20SD2N2HDN2QSHDG6IDTBR48KRDCS601FI6VHG59E7DQA98JD2O =
+
+[transport-blacklist-OF84RAOAU2B1SOSEHJH6350MA0F7C98U55RI76LGIQOM7O33TFHPNUFB47CDBSCOLIINMVJ2U82445ABOBQRIVREG20L31KVDV5HG60]
+HIJN5O404QNUR37OSJUTNJ6H2KJS198DHI2J3I8SE3DMKVRG1RNQPODN1IJBF14KEMPPPRM0B9F9ILFKHOFCA655CH6M5OCNCMR0FE0 =
+CDTU8QQ8UPLGHR3B91V0CLTDOHONLB8QGHGUEM2JM1GANTEV0O6T20SD2N2HDN2QSHDG6IDTBR48KRDCS601FI6VHG59E7DQA98JD2O =
+
+[transport-blacklist-548J7M14O4I0F8I84U0UFARVJ97DB6QOT3MCA8O8SNAIT5JJ8TR95LUVAP3N5L7DN33IB49SNMF3Q3C0VPLTGP9ASCULA9S2OIMHHH8]
+HIJN5O404QNUR37OSJUTNJ6H2KJS198DHI2J3I8SE3DMKVRG1RNQPODN1IJBF14KEMPPPRM0B9F9ILFKHOFCA655CH6M5OCNCMR0FE0 =
+CDTU8QQ8UPLGHR3B91V0CLTDOHONLB8QGHGUEM2JM1GANTEV0O6T20SD2N2HDN2QSHDG6IDTBR48KRDCS601FI6VHG59E7DQA98JD2O =
diff --git a/src/ats-tool/.gitignore b/src/ats-tool/.gitignore
new file mode 100644
index 0000000000000000000000000000000000000000..2de03f0e8f810104540e5401304b92fabed05df3
--- /dev/null
+++ b/src/ats-tool/.gitignore
@@ -0,0 +1 @@
+gnunet-ats
diff --git a/src/ats/.gitignore b/src/ats/.gitignore
new file mode 100644
index 0000000000000000000000000000000000000000..fa72eb136f5bc4f21ffc4cb714e3f6020e9fd8ee
--- /dev/null
+++ b/src/ats/.gitignore
@@ -0,0 +1,6 @@
+gnunet-service-ats
+test_ats_api_proportional
+test_ats_reservation_api_proportional
+test_ats_api_mlp
+test_ats_api_ril
+gnunet-service-ats-new
diff --git a/src/ats/ats_api_performance.c b/src/ats/ats_api_performance.c
index acc9356ede260bfebb90a5c3de276ca1fdcdbc8b..7349fb989d857333ecacec058ed923d438a60943 100644
--- a/src/ats/ats_api_performance.c
+++ b/src/ats/ats_api_performance.c
@@ -496,7 +496,7 @@ handle_address_list (void *cls,
     return; /* was canceled */
 
   memset (&allzeros, '\0', sizeof(allzeros));
-  if ((0 == GNUNET_is_zero (&pi->peer)) &&
+  if ((GNUNET_YES == GNUNET_is_zero (&pi->peer)) &&
       (0 == plugin_name_length) &&
       (0 == plugin_address_length))
   {
diff --git a/src/ats/experiments/example.exp b/src/ats/experiments/example.exp
new file mode 100644
index 0000000000000000000000000000000000000000..a490e5ec61e8b641951233209176025f46dc65b1
--- /dev/null
+++ b/src/ats/experiments/example.exp
@@ -0,0 +1,104 @@
+[experiment]
+name = test
+max_duration = 15 s
+log_freq = 1000 ms
+cfg_file = experiments/gnunet_ats_sim_default.conf
+log_output_dir = data/
+log_append_time_stamp = no
+  
+[episode-0]
+# Setup addresses
+
+# operations = address_add, address_del, start_set_property, stop_set_property, 
+# start_set_preference, stop_preference, start_request, stop_request
+duration = 0
+op-0-operation = address_add
+op-0-address-id = 0
+op-0-peer-id = 0
+op-0-address-session = 0
+op-0-address-network = 0
+op-0-address = 0_0_test
+op-0-plugin = test
+
+op-1-operation = address_add
+op-1-address-id = 1
+op-1-peer-id = 1
+op-1-address-session = 0
+op-1-address-network = 0
+op-1-address = 1_1_test
+op-1-plugin = test
+
+op-2-operation = start_request
+op-2-peer-id = 0
+
+op-3-operation = start_request
+op-3-peer-id = 1
+
+[episode-1]
+# Set delay
+duration = 5 s
+
+op-0-operation = start_set_property
+op-0-address-id = 0
+op-0-peer-id = 0
+# constant, linear, sinus, random
+op-0-gen-type = random
+op-0-base-rate= 10000
+op-0-max-rate = 20000
+op-0-frequency = 1000 ms
+# bandwidth, latency
+# "TERMINATOR", "UTILIZATION_UP", "UTILIZATION_DOWN", "UTILIZATION_PAYLOAD_UP", "UTILIZATION_PAYLOAD_DOWN", "NETWORK_TYPE", "DELAY", "DISTANCE", "COST_WAN", "COST_LAN", "COST_WLAN"
+op-0-property = DELAY  
+
+op-1-operation = start_set_property
+op-1-address-id = 1
+op-1-peer-id = 1
+# constant, linear, sinus, random
+op-1-gen-type = constant
+op-1-base-rate= 1
+op-1-max-rate = 1
+op-1-frequency = 1000 ms
+# bandwidth, latency
+# "TERMINATOR", "UTILIZATION_UP", "UTILIZATION_DOWN", "UTILIZATION_PAYLOAD_UP", "UTILIZATION_PAYLOAD_DOWN", "NETWORK_TYPE", "DELAY", "DISTANCE", "COST_WAN", "COST_LAN", "COST_WLAN"
+op-1-property = DELAY  
+
+
+[episode-2]
+# Shutdown
+duration = 2 s
+op-0-operation = stop_set_property
+op-0-address-id = 0
+op-0-peer-id = 0
+op-0-property = DELAY
+
+op-1-operation = stop_set_property
+op-1-address-id = 1
+op-1-peer-id = 1
+op-1-property = DELAY
+
+[episode-3]
+# Shutdown
+duration = 2 s
+
+op-0-operation = stop_request
+op-0-peer-id = 0  
+
+op-1-operation = stop_request
+op-1-peer-id = 1
+
+op-2-operation = address_del
+op-2-address-id = 0
+op-2-peer-id = 0
+op-2-address-session = 0
+op-2-address-network = 0
+op-2-address = 0_0_test
+op-2-plugin = test
+
+op-2-operation = address_del
+op-2-address-id = 1
+op-2-peer-id = 1
+op-2-address-session = 0
+op-2-address-network = 0
+op-2-address = 1_1_test
+op-2-plugin = test
+
diff --git a/src/ats/experiments/gnunet_ats_sim_default.conf b/src/ats/experiments/gnunet_ats_sim_default.conf
new file mode 100644
index 0000000000000000000000000000000000000000..14e0a2e0b372d07883616ef981307f07cbd70cf3
--- /dev/null
+++ b/src/ats/experiments/gnunet_ats_sim_default.conf
@@ -0,0 +1,18 @@
+[ats]
+UNSPECIFIED_QUOTA_IN = 64 KiB
+UNSPECIFIED_QUOTA_OUT = 64 KiB
+# LOOPBACK
+LOOPBACK_QUOTA_IN = 64 KiB
+LOOPBACK_QUOTA_OUT = 64 KiB
+# LAN
+LAN_QUOTA_IN = 64 KiB
+LAN_QUOTA_OUT = 64 KiB
+# WAN
+WAN_QUOTA_IN = 64 KiB
+WAN_QUOTA_OUT = 64 KiB
+# WLAN
+WLAN_QUOTA_IN = 64 KiB
+WLAN_QUOTA_OUT = 64 KiB
+# BLUETOOTH
+BLUETOOTH_QUOTA_IN = 64 KiB
+BLUETOOTH_QUOTA_OUT = 64 KiB
diff --git a/src/ats/experiments/set_preference.exp b/src/ats/experiments/set_preference.exp
new file mode 100644
index 0000000000000000000000000000000000000000..34f9af29623b7940518849f29e5842cda1453a7d
--- /dev/null
+++ b/src/ats/experiments/set_preference.exp
@@ -0,0 +1,95 @@
+# Example setting up two peers 
+
+[experiment]
+name = test
+max_duration = 15 s
+log_freq = 1000 ms
+log_prefix = set_preference
+cfg_file = experiments/gnunet_ats_sim_default.conf
+  
+[episode-0]
+# Setup addresses
+
+# operations = address_add, address_del, start_set_property, stop_set_property, 
+# start_set_preference, stop_preference, start_request, stop_request
+duration = 1 s
+
+op-0-operation = address_add
+op-0-address-id = 0
+op-0-peer-id = 0
+op-0-address-session = 0
+op-0-address-network = lan
+op-0-address = 0_0_test
+op-0-plugin = test
+
+op-1-operation = address_add
+op-1-address-id = 1
+op-1-peer-id = 1
+op-1-address-session = 0
+op-1-address-network = lan
+op-1-address = 1_1_test
+op-1-plugin = test
+
+op-2-operation = start_request
+op-2-peer-id = 0
+
+op-3-operation = start_request
+op-3-peer-id = 1
+
+[episode-1]
+# Set delay
+duration = 20 s
+
+op-0-operation = start_set_preference
+op-0-address-id = 0
+op-0-peer-id = 0
+op-0-client-id = 1
+# constant, linear, sinus, random
+op-0-gen-type = linear
+op-0-base-rate= 1000
+op-0-max-rate = 10000
+op-0-period = 10 s
+op-0-frequency = 500 ms
+op-0-feedback_delay = 500 ms
+# BANDWIDTH, LATENCY
+op-0-pref = BANDWIDTH  
+
+
+op-1-operation = start_set_preference
+op-1-address-id = 1
+op-1-peer-id = 1
+op-1-client-id = 1
+# constant, linear, sinus, random
+op-1-gen-type = constant
+op-1-base-rate= 1000
+op-1-max-rate = 1000
+op-1-period = 10 s
+op-1-frequency = 500 ms
+# BANDWIDTH, LATENCY
+op-1-pref = BANDWIDTH  
+
+[episode-2]
+# Shutdown
+duration = 2 s
+
+op-0-operation = stop_request
+op-0-peer-id = 0  
+
+op-1-operation = stop_request
+op-1-peer-id = 1
+
+op-2-operation = address_del
+op-2-address-id = 0
+op-2-peer-id = 0
+op-2-address-session = 0
+op-2-address-network = 0
+op-2-address = 0_0_test
+op-2-plugin = test
+
+op-3-operation = address_del
+op-3-address-id = 1
+op-3-peer-id = 1
+op-3-address-session = 0
+op-3-address-network = 0
+op-3-address = 1_1_test
+op-3-plugin = test
diff --git a/src/ats/gnunet-ats-solver-eval.c b/src/ats/gnunet-ats-solver-eval.c
new file mode 100644
index 0000000000000000000000000000000000000000..25b9635321a928641c5684f63a679caa89fdb0bd
--- /dev/null
+++ b/src/ats/gnunet-ats-solver-eval.c
@@ -0,0 +1,3587 @@
+/*
+   This file is part of GNUnet.
+   Copyright (C) 2010-2013 GNUnet e.V.
+
+   GNUnet is free software: you can redistribute it and/or modify it
+   under the terms of the GNU Affero General Public License as published
+   by the Free Software Foundation, either version 3 of the License,
+   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
+   Affero General Public License for more details.
+
+   You should have received a copy of the GNU Affero General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+     SPDX-License-Identifier: AGPL3.0-or-later
+ */
+/**
+ * @file ats-tests/ats-testing-experiment.c
+ * @brief ats benchmark: controlled experiment execution
+ * @author Christian Grothoff
+ * @author Matthias Wachs
+ */
+#include "platform.h"
+#include "gnunet_util_lib.h"
+#include "gnunet-ats-solver-eval.h"
+#include "gnunet-service-ats_normalization.h"
+#include "gnunet-service-ats_preferences.c"
+
+#define BIG_M_STRING "unlimited"
+
+/**
+ * Handle for statistics.
+ */
+struct GNUNET_STATISTICS_Handle *GSA_stats;
+
+
+static struct Experiment *e;
+
+static struct LoggingHandle *l;
+
+static struct SolverHandle *sh;
+
+static struct TestPeer *peer_head;
+
+static struct TestPeer *peer_tail;
+
+static double default_properties[GNUNET_ATS_PropertyCount];
+static double default_preferences[GNUNET_ATS_PreferenceCount];
+
+/**
+ * cmd option -e: experiment file
+ */
+static char *opt_exp_file;
+
+static char *opt_solver;
+
+/**
+ * cmd option -l: enable logging
+ */
+static int opt_log;
+
+/**
+ * cmd option -p: enable plots
+ */
+static int opt_save;
+
+/**
+ * cmd option -v: verbose logs
+ */
+static int opt_verbose;
+
+/**
+ * cmd option -p: print logs
+ */
+static int opt_print;
+
+/**
+ * cmd option -d: disable normalization
+ */
+static int opt_disable_normalization;
+
+static int res;
+
+static void
+end_now ();
+
+
+static char *
+print_generator_type (enum GeneratorType g)
+{
+  switch (g)
+  {
+  case GNUNET_ATS_TEST_TG_CONSTANT:
+    return "CONSTANT";
+
+  case GNUNET_ATS_TEST_TG_LINEAR:
+    return "LINEAR";
+
+  case GNUNET_ATS_TEST_TG_RANDOM:
+    return "RANDOM";
+
+  case GNUNET_ATS_TEST_TG_SINUS:
+    return "SINUS";
+
+  default:
+    return "INVALID";
+    break;
+  }
+}
+
+
+static struct TestPeer *
+find_peer_by_id (int id)
+{
+  struct TestPeer *cur;
+
+  for (cur = peer_head; NULL != cur; cur = cur->next)
+    if (cur->id == id)
+      return cur;
+  return NULL;
+}
+
+
+static struct TestPeer *
+find_peer_by_pid (const struct GNUNET_PeerIdentity *pid)
+{
+  struct TestPeer *cur;
+
+  for (cur = peer_head; NULL != cur; cur = cur->next)
+    if (0 == GNUNET_memcmp (&cur->peer_id, pid))
+      return cur;
+  return NULL;
+}
+
+
+static struct TestAddress *
+find_address_by_id (struct TestPeer *peer, int aid)
+{
+  struct TestAddress *cur;
+
+  for (cur = peer->addr_head; NULL != cur; cur = cur->next)
+    if (cur->aid == aid)
+      return cur;
+  return NULL;
+}
+
+
+/**
+ * Logging
+ */
+void
+GNUNET_ATS_solver_logging_now (struct LoggingHandle *l)
+{
+  struct LoggingTimeStep *lts;
+  struct TestPeer *cur;
+  struct TestAddress *cur_addr;
+  struct LoggingPeer *log_p;
+  struct LoggingAddress *log_a;
+  int c;
+
+  lts = GNUNET_new (struct LoggingTimeStep);
+  GNUNET_CONTAINER_DLL_insert_tail (l->head, l->tail, lts);
+  lts->timestamp = GNUNET_TIME_absolute_get ();
+  if (NULL == lts->prev)
+    lts->delta = GNUNET_TIME_UNIT_ZERO;
+  else
+    lts->delta = GNUNET_TIME_absolute_get_duration (lts->prev->timestamp);
+
+  GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Logging %llu, delta %llu\n",
+              lts->timestamp.abs_value_us, lts->delta.rel_value_us);
+
+
+  /* Store logging data here */
+  for (cur = peer_head; NULL != cur; cur = cur->next)
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+                "Logging peer id %llu\n", cur->id);
+
+    log_p = GNUNET_new (struct LoggingPeer);
+    log_p->id = cur->id;
+    log_p->peer_id = cur->peer_id;
+    log_p->is_requested = cur->is_requested;
+    for (c = 0; c < GNUNET_ATS_PreferenceCount; c++)
+    {
+      log_p->pref_abs[c] = cur->pref_abs[c];
+      log_p->pref_norm[c] = cur->pref_norm[c];
+      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                  "\t %s = %.2f %.2f [abs/rel]\n",
+                  GNUNET_ATS_print_preference_type (c),
+                  log_p->pref_abs[c], log_p->pref_norm[c]);
+    }
+    GNUNET_CONTAINER_DLL_insert_tail (lts->head, lts->tail, log_p);
+
+    for (cur_addr = cur->addr_head; NULL != cur_addr; cur_addr = cur_addr->next)
+    {
+      GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+                  "Logging peer id %llu address %llu\n",
+                  cur->id, cur_addr->aid);
+      log_a = GNUNET_new (struct LoggingAddress);
+      log_a->aid = cur_addr->aid;
+      log_a->active = cur_addr->ats_addr->active;
+      log_a->network = cur_addr->network;
+      log_a->assigned_bw_in = cur_addr->ats_addr->assigned_bw_in;
+      log_a->assigned_bw_out = cur_addr->ats_addr->assigned_bw_out;
+      for (c = 0; c < GNUNET_ATS_PropertyCount; c++)
+      {
+        log_a->prop_abs[c] = cur_addr->prop_abs[c];
+        log_a->prop_norm[c] = cur_addr->prop_norm[c];
+        GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                    "\t %s = %.2f %.2f [abs/rel]\n",
+                    GNUNET_ATS_print_property_type (c),
+                    log_a->prop_abs[c],
+                    log_a->prop_norm[c]);
+      }
+      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "\t Active = %i\n", log_a->active);
+      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "\t BW in = %llu\n",
+                  log_a->assigned_bw_in);
+      GNUNET_log (GNUNET_ERROR_TYPE_INFO, "\t BW out = %llu\n",
+                  log_a->assigned_bw_out);
+
+      GNUNET_CONTAINER_DLL_insert_tail (log_p->addr_head, log_p->addr_tail,
+                                        log_a);
+    }
+  }
+}
+
+
+static void
+logging_task (void *cls)
+{
+  struct LoggingHandle *l = cls;
+
+  l->logging_task = NULL;
+  GNUNET_ATS_solver_logging_now (l);
+  l->logging_task = GNUNET_SCHEDULER_add_delayed (l->log_freq,
+                                                  &logging_task,
+                                                  l);
+}
+
+
+struct LoggingHandle *
+GNUNET_ATS_solver_logging_start (struct GNUNET_TIME_Relative freq)
+{
+  struct LoggingHandle *l;
+
+  l = GNUNET_new (struct LoggingHandle);
+
+  GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Start logging every  %s\n",
+              GNUNET_STRINGS_relative_time_to_string (freq, GNUNET_NO));
+  l->log_freq = freq;
+  l->logging_task = GNUNET_SCHEDULER_add_now (&logging_task, l);
+  return l;
+}
+
+
+void
+GNUNET_ATS_solver_logging_stop (struct LoggingHandle *l)
+{
+  if (NULL != l->logging_task)
+    GNUNET_SCHEDULER_cancel (l->logging_task);
+
+  GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Stop logging\n");
+
+  l->logging_task = NULL;
+}
+
+
+static struct LoggingFileHandle *
+find_logging_file_handle (struct LoggingFileHandle *lf_head,
+                          struct LoggingFileHandle *lf_tail,
+                          int peer_id, int address_id)
+{
+  struct LoggingFileHandle *res;
+
+  for (res = lf_head; NULL != res; res = res->next)
+    if ((res->pid == peer_id) && (res->aid == address_id))
+      return res;
+  return NULL;
+}
+
+
+void
+GNUNET_ATS_solver_logging_write_to_disk (struct LoggingHandle *l, int
+                                         add_time_stamp,
+                                         char *output_dir)
+{
+  struct LoggingTimeStep *lts;
+  struct LoggingPeer *log_p;
+  struct LoggingAddress *log_a;
+  struct LoggingFileHandle *lf_head;
+  struct LoggingFileHandle *lf_tail;
+  struct LoggingFileHandle *cur;
+  struct LoggingFileHandle *next;
+  char *filename;
+  char *datastring;
+  char *propstring;
+  char *propstring_tmp;
+  char *prefstring;
+  char *prefstring_tmp;
+  int c;
+  int use_dir;
+
+  use_dir = GNUNET_NO;
+  if (NULL != output_dir)
+  {
+    if (GNUNET_OK != GNUNET_DISK_directory_create_for_file (output_dir))
+    {
+      fprintf (stderr, "Failed to create directory `%s'\n", output_dir);
+      return;
+    }
+    else
+    {
+      fprintf (stderr, "Created directory `%s'\n", output_dir);
+      use_dir = GNUNET_YES;
+    }
+  }
+
+  lf_head = NULL;
+  lf_tail = NULL;
+
+  for (lts = l->head; NULL != lts; lts = lts->next)
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Writing log step %llu\n",
+                (long long unsigned int) lts->timestamp.abs_value_us);
+
+    for (log_p = lts->head; NULL != log_p; log_p = log_p->next)
+    {
+      for (log_a = log_p->addr_head; NULL != log_a; log_a = log_a->next)
+      {
+        cur = find_logging_file_handle (lf_head, lf_tail, log_p->id,
+                                        log_a->aid);
+        if (NULL == cur)
+        {
+          cur = GNUNET_new (struct LoggingFileHandle);
+          cur->aid = log_a->aid;
+          cur->pid = log_p->id;
+
+          if (GNUNET_YES == add_time_stamp)
+            GNUNET_asprintf (&filename, "%s%s%s_%s_p%u_a%u_%llu.log",
+                             (GNUNET_YES == use_dir) ? output_dir : "",
+                             (GNUNET_YES == use_dir) ? DIR_SEPARATOR_STR : "",
+                             e->log_prefix,
+                             opt_solver,
+                             cur->pid,
+                             cur->aid,
+                             l->head->timestamp.abs_value_us);
+          else
+            GNUNET_asprintf (&filename, "%s%s%s_%s_p%u_a%u.log",
+                             (GNUNET_YES == use_dir) ? output_dir : "",
+                             (GNUNET_YES == use_dir) ? DIR_SEPARATOR_STR : "",
+                             e->log_prefix,
+                             opt_solver,
+                             cur->pid,
+                             cur->aid);
+
+          fprintf (stderr,
+                   "Add writing log data for peer %llu address %llu to file `%s'\n",
+                   cur->pid, cur->aid, filename);
+
+
+          cur->f_hd = GNUNET_DISK_file_open (filename,
+                                             GNUNET_DISK_OPEN_READWRITE
+                                             | GNUNET_DISK_OPEN_CREATE
+                                             | GNUNET_DISK_OPEN_TRUNCATE,
+                                             GNUNET_DISK_PERM_USER_READ
+                                             | GNUNET_DISK_PERM_USER_WRITE
+                                             | GNUNET_DISK_PERM_GROUP_READ
+                                             | GNUNET_DISK_PERM_OTHER_READ);
+          if (NULL == cur->f_hd)
+          {
+            fprintf (stderr, "Cannot open `%s' to write log data!\n", filename);
+            GNUNET_free (filename);
+            GNUNET_free (cur);
+            goto cleanup;
+          }
+          GNUNET_free (filename);
+          GNUNET_CONTAINER_DLL_insert (lf_head, lf_tail, cur);
+
+          GNUNET_asprintf (&datastring,
+                           "#time delta;log duration;peer_requested;addr net; addr_active; bw in; bw out; " \
+                           "UTILIZATION_UP [abs/rel]; UTILIZATION_UP; UTILIZATION_DOWN; UTILIZATION_DOWN; " \
+                           "UTILIZATION_PAYLOAD_UP; UTILIZATION_PAYLOAD_UP; UTILIZATION_PAYLOAD_DOWN; UTILIZATION_PAYLOAD_DOWN;" \
+                           "DELAY; DELAY; " \
+                           "DISTANCE ;DISTANCE ; COST_WAN; COST_WAN; COST_LAN; COST_LAN; " \
+                           "COST_WLAN; COST_WLAN;COST_BT; COST_BT; PREF BW abs; PREF BW rel; PREF LATENCY abs; PREF LATENCY rel;\n");
+          GNUNET_DISK_file_write (cur->f_hd, datastring, strlen (datastring));
+          GNUNET_free (datastring);
+        }
+
+        prefstring = GNUNET_strdup ("");
+        for (c = 1; c < GNUNET_ATS_PreferenceCount; c++)
+        {
+          /*
+             fprintf(stderr,"\t %s = %.2f %.2f [abs/rel]\n",
+              GNUNET_ATS_print_preference_type(c),
+              log_p->pref_abs[c], log_p->pref_norm[c]);
+           */GNUNET_asprintf (&prefstring_tmp, "%s;%.3f;%.3f",
+                           prefstring, log_p->pref_abs[c], log_p->pref_norm[c]);
+
+
+          GNUNET_free (prefstring);
+          prefstring = GNUNET_strdup (prefstring_tmp);
+          GNUNET_free (prefstring_tmp);
+        }
+
+
+        propstring = GNUNET_strdup ("");
+        for (c = 1; c < GNUNET_ATS_PropertyCount; c++)
+        {
+          if (GNUNET_ATS_NETWORK_TYPE == c)
+            continue;
+          /*
+             fprintf(stderr, "\t %s = %.2f %.2f [abs/rel]\n",
+              GNUNET_ATS_print_property_type(c),
+              log_a->prop_abs[c], log_a->prop_norm[c]);*/
+          GNUNET_asprintf (&propstring_tmp, "%s%.3f;%.3f;",
+                           propstring,
+                           log_a->prop_abs[c],
+                           log_a->prop_norm[c]);
+          GNUNET_free (propstring);
+          propstring = GNUNET_strdup (propstring_tmp);
+          GNUNET_free (propstring_tmp);
+        }
+        GNUNET_asprintf (&datastring, "%llu;%llu;%u;%u;%i;%u;%u;%s;%s\n",
+                         GNUNET_TIME_absolute_get_difference (
+                           l->head->timestamp,
+                           lts->timestamp).
+                         rel_value_us / 1000, lts->delta,
+                         log_p->is_requested, log_a->network, log_a->active,
+                         log_a->assigned_bw_in, log_a->assigned_bw_out,
+                         propstring,
+                         prefstring);
+
+        GNUNET_DISK_file_write (cur->f_hd, datastring, strlen (datastring));
+        GNUNET_free (datastring);
+        GNUNET_free (prefstring);
+        GNUNET_free (propstring);
+      }
+    }
+  }
+
+cleanup:
+  next = lf_head;
+  for (cur = next; NULL != cur; cur = next)
+  {
+    next = cur->next;
+    GNUNET_CONTAINER_DLL_remove (lf_head, lf_tail, cur);
+    if (NULL != cur->f_hd)
+      GNUNET_DISK_file_close (cur->f_hd);
+    GNUNET_free (cur);
+  }
+}
+
+
+void
+GNUNET_ATS_solver_logging_eval (struct LoggingHandle *l)
+{
+  struct LoggingTimeStep *lts;
+  struct LoggingPeer *log_p;
+  struct LoggingAddress *log_a;
+  int c;
+
+  for (lts = l->head; NULL != lts; lts = lts->next)
+  {
+    fprintf (stderr, "Log step %llu %llu: \n",
+             (long long unsigned int) lts->timestamp.abs_value_us,
+             (long long unsigned int) lts->delta.rel_value_us);
+
+    for (log_p = lts->head; NULL != log_p; log_p = log_p->next)
+    {
+      fprintf (stderr, "\tLogging peer pid %llu\n", log_p->id);
+      for (c = 1; c < GNUNET_ATS_PreferenceCount; c++)
+      {
+        fprintf (stderr, "\t %s = %.2f %.2f [abs/rel]\n",
+                 GNUNET_ATS_print_preference_type (c),
+                 log_p->pref_abs[c], log_p->pref_norm[c]);
+      }
+
+      for (log_a = log_p->addr_head; NULL != log_a; log_a = log_a->next)
+      {
+        fprintf (stderr, "\tPeer pid %llu address %llu: %u %u %u\n",
+                 log_p->id, log_a->aid, log_a->active,
+                 log_a->assigned_bw_in,
+                 log_a->assigned_bw_out);
+
+        for (c = 1; c < GNUNET_ATS_PropertyCount; c++)
+        {
+          if (GNUNET_ATS_NETWORK_TYPE == c)
+            continue;
+          fprintf (stderr, "\t %s = %.2f %.2f [abs/rel]\n",
+                   GNUNET_ATS_print_property_type (c),
+                   log_a->prop_abs[c], log_a->prop_norm[c]);
+        }
+      }
+    }
+  }
+}
+
+
+void
+GNUNET_ATS_solver_logging_free (struct LoggingHandle *l)
+{
+  struct LoggingTimeStep *lts_cur;
+  struct LoggingTimeStep *lts_next;
+  struct LoggingPeer *log_p_cur;
+  struct LoggingPeer *log_p_next;
+  struct LoggingAddress *log_a_cur;
+  struct LoggingAddress *log_a_next;
+
+  if (NULL != l->logging_task)
+    GNUNET_SCHEDULER_cancel (l->logging_task);
+  l->logging_task = NULL;
+
+  lts_next = l->head;
+  while (NULL != (lts_cur = lts_next))
+  {
+    lts_next = lts_cur->next;
+
+    log_p_next = lts_cur->head;
+    while (NULL != (log_p_cur = log_p_next))
+    {
+      log_p_next = log_p_cur->next;
+
+      log_a_next = log_p_cur->addr_head;
+      while (NULL != (log_a_cur = log_a_next))
+      {
+        log_a_next = log_a_cur->next;
+
+        GNUNET_CONTAINER_DLL_remove (log_p_cur->addr_head, log_p_cur->addr_tail,
+                                     log_a_cur);
+        GNUNET_free (log_a_cur);
+      }
+
+      GNUNET_CONTAINER_DLL_remove (lts_cur->head, lts_cur->tail, log_p_cur);
+      GNUNET_free (log_p_cur);
+    }
+
+    GNUNET_CONTAINER_DLL_remove (l->head, l->tail, lts_cur);
+    GNUNET_free (lts_cur);
+  }
+
+  GNUNET_free (l);
+}
+
+
+/**
+ * Property Generators
+ */
+static struct PropertyGenerator *prop_gen_head;
+static struct PropertyGenerator *prop_gen_tail;
+
+
+static double
+get_property (struct PropertyGenerator *pg)
+{
+  struct GNUNET_TIME_Relative time_delta;
+  double delta_value;
+  double pref_value;
+
+  /* Calculate the current preference value */
+  switch (pg->type)
+  {
+  case GNUNET_ATS_TEST_TG_CONSTANT:
+    pref_value = pg->base_value;
+    break;
+
+  case GNUNET_ATS_TEST_TG_LINEAR:
+    time_delta = GNUNET_TIME_absolute_get_duration (pg->time_start);
+    /* Calculate point of time in the current period */
+    time_delta.rel_value_us = time_delta.rel_value_us
+                              % pg->duration_period.rel_value_us;
+    delta_value = ((double) time_delta.rel_value_us
+                   / pg->duration_period.rel_value_us) * (pg->max_value
+                                                          - pg->base_value);
+    if ((pg->max_value < pg->base_value) &&
+        ((pg->max_value - pg->base_value) > pg->base_value))
+    {
+      /* This will cause an underflow */
+      GNUNET_break (0);
+    }
+    pref_value = pg->base_value + delta_value;
+    break;
+
+  case GNUNET_ATS_TEST_TG_RANDOM:
+    delta_value = (double) GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK,
+                                                     10000 * (pg->max_value
+                                                              - pg->base_value))
+                  / 10000;
+    pref_value = pg->base_value + delta_value;
+    break;
+
+  case GNUNET_ATS_TEST_TG_SINUS:
+    time_delta = GNUNET_TIME_absolute_get_duration (pg->time_start);
+    /* Calculate point of time in the current period */
+    time_delta.rel_value_us = time_delta.rel_value_us
+                              % pg->duration_period.rel_value_us;
+    if ((pg->max_value - pg->base_value) > pg->base_value)
+    {
+      /* This will cause an underflow for second half of sinus period,
+       * will be detected in general when experiments are loaded */
+      GNUNET_break (0);
+    }
+    delta_value = (pg->max_value - pg->base_value)
+                  * sin ((2 * M_PI)
+                         / ((double) pg->duration_period.rel_value_us)
+                         * time_delta.rel_value_us);
+    pref_value = pg->base_value + delta_value;
+    break;
+
+  default:
+    pref_value = 0.0;
+    break;
+  }
+  GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Current property value is %f\n",
+              pref_value);
+  return pref_value;
+}
+
+
+static void
+set_prop_task (void *cls)
+{
+  struct PropertyGenerator *pg = cls;
+  struct TestPeer *p;
+  struct TestAddress *a;
+  double prop_value;
+  struct GNUNET_ATS_Information atsi;
+
+  pg->set_task = NULL;
+
+  if (GNUNET_NO == GNUNET_CONTAINER_multipeermap_contains_value (sh->addresses,
+                                                                 &pg->test_peer
+                                                                 ->peer_id,
+                                                                 pg->
+                                                                 test_address->
+                                                                 ats_addr))
+  {
+    GNUNET_break (0);
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                "Setting property generation for unknown address [%u:%u]\n",
+                pg->peer, pg->address_id);
+    return;
+  }
+  if (NULL == (p = find_peer_by_id (pg->peer)))
+  {
+    GNUNET_break (0);
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                "Setting property generation for unknown peer %u\n",
+                pg->peer);
+    return;
+  }
+  if (NULL == (a = find_address_by_id (p, pg->address_id)))
+  {
+    GNUNET_break (0);
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                "Setting property generation for unknown peer %u\n",
+                pg->peer);
+    return;
+  }
+
+  prop_value = get_property (pg);
+  a->prop_abs[pg->ats_property] = prop_value;
+
+  GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+              "Setting property for peer [%u] address [%u] for %s to %f\n",
+              pg->peer, pg->address_id,
+              GNUNET_ATS_print_property_type (pg->ats_property), prop_value);
+
+  atsi.type = htonl (pg->ats_property);
+  atsi.value = htonl ((uint32_t) prop_value);
+
+  /* set performance here! */
+  sh->sf->s_bulk_start (sh->sf->cls);
+  if (GNUNET_YES == opt_disable_normalization)
+  {
+    a->prop_abs[pg->ats_property] = prop_value;
+    a->prop_norm[pg->ats_property] = prop_value;
+    sh->sf->s_address_update_property (sh->sf->cls, a->ats_addr,
+                                       pg->ats_property, prop_value,
+                                       prop_value);
+  }
+  else
+    GAS_normalization_update_property (pg->test_address->ats_addr, &atsi, 1);
+  sh->sf->s_bulk_stop (sh->sf->cls);
+
+  pg->set_task = GNUNET_SCHEDULER_add_delayed (pg->frequency,
+                                               &set_prop_task, pg);
+}
+
+
+/**
+ * Set ats_property to 0 to find all pgs
+ */
+static struct PropertyGenerator *
+find_prop_gen (unsigned int peer, unsigned int address,
+               uint32_t ats_property)
+{
+  struct PropertyGenerator *cur;
+
+  for (cur = prop_gen_head; NULL != cur; cur = cur->next)
+    if ((cur->peer == peer) && (cur->address_id == address))
+    {
+      if ((cur->ats_property == ats_property) || (0 == ats_property))
+        return cur;
+    }
+  return NULL;
+}
+
+
+void
+GNUNET_ATS_solver_generate_property_stop (struct PropertyGenerator *pg)
+{
+  GNUNET_CONTAINER_DLL_remove (prop_gen_head, prop_gen_tail, pg);
+
+  if (NULL != pg->set_task)
+  {
+    GNUNET_SCHEDULER_cancel (pg->set_task);
+    pg->set_task = NULL;
+  }
+  GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+              "Removing old up preference generator peer [%u] address [%u] `%s'\n",
+              pg->peer, pg->address_id,
+              GNUNET_ATS_print_property_type (pg->ats_property));
+
+  GNUNET_free (pg);
+}
+
+
+/**
+ * Generate between the source master and the partner and set property with a
+ * value depending on the generator.
+ *
+ * @param peer source
+ * @param address_id partner
+ * @param test_peer the peer
+ * @param test_address the address
+ * @param type type of generator
+ * @param base_value base value
+ * @param value_rate maximum value
+ * @param period duration of a period of generation (~ 1/frequency)
+ * @param frequency how long to generate property
+ * @param ats_property ATS property to generate
+ * @return the property generator
+ */
+struct PropertyGenerator *
+GNUNET_ATS_solver_generate_property_start (unsigned int peer,
+                                           unsigned int address_id,
+                                           struct TestPeer *test_peer,
+                                           struct TestAddress *test_address,
+                                           enum GeneratorType type,
+                                           long int base_value,
+                                           long int value_rate,
+                                           struct GNUNET_TIME_Relative period,
+                                           struct GNUNET_TIME_Relative
+                                           frequency,
+                                           uint32_t ats_property)
+{
+  struct PropertyGenerator *pg;
+
+  pg = GNUNET_new (struct PropertyGenerator);
+  GNUNET_CONTAINER_DLL_insert (prop_gen_head, prop_gen_tail, pg);
+  pg->type = type;
+  pg->peer = peer;
+  pg->test_address = test_address;
+  pg->test_peer = test_peer;
+  pg->address_id = address_id;
+  pg->ats_property = ats_property;
+  pg->base_value = base_value;
+  pg->max_value = value_rate;
+  pg->duration_period = period;
+  pg->frequency = frequency;
+  pg->time_start = GNUNET_TIME_absolute_get ();
+
+  switch (type)
+  {
+  case GNUNET_ATS_TEST_TG_CONSTANT:
+    GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+                "Setting up %s property generator peer [%u] address [%u] `%s'" \
+                "max %u Bips\n",
+                print_generator_type (type), pg->peer, pg->address_id,
+                GNUNET_ATS_print_property_type (ats_property),
+                base_value);
+    break;
+
+  case GNUNET_ATS_TEST_TG_LINEAR:
+    GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+                "Setting up %s property generator peer [%u] address [%u] `%s' " \
+                "min %u Bips max %u Bips\n",
+                print_generator_type (type), pg->peer, pg->address_id,
+                GNUNET_ATS_print_property_type (ats_property),
+                base_value, value_rate);
+    break;
+
+  case GNUNET_ATS_TEST_TG_SINUS:
+    GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+                "Setting up %s property generator peer [%u] address [%u] `%s' " \
+                "baserate %u Bips, amplitude %u Bps\n",
+                print_generator_type (type), pg->peer, pg->address_id,
+                GNUNET_ATS_print_property_type (ats_property),
+                base_value, value_rate);
+    break;
+
+  case GNUNET_ATS_TEST_TG_RANDOM:
+    GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+                "Setting up %s property generator peer [%u] address [%u] `%s' " \
+                "min %u Bips max %u Bps\n",
+                print_generator_type (type), pg->peer, pg->address_id,
+                GNUNET_ATS_print_property_type (ats_property),
+                base_value, value_rate);
+    break;
+
+  default:
+    break;
+  }
+
+  pg->set_task = GNUNET_SCHEDULER_add_now (&set_prop_task, pg);
+  return pg;
+}
+
+
+/**
+ * Stop all preferences generators
+ */
+void
+GNUNET_ATS_solver_generate_property_stop_all ()
+{
+  struct PropertyGenerator *cur;
+  struct PropertyGenerator *next;
+
+  next = prop_gen_head;
+  for (cur = next; NULL != cur; cur = next)
+  {
+    next = cur->next;
+    GNUNET_ATS_solver_generate_property_stop (cur);
+  }
+}
+
+
+/**
+ * Preference Generators
+ */
+static struct PreferenceGenerator *pref_gen_head;
+static struct PreferenceGenerator *pref_gen_tail;
+
+
+static double
+get_preference (struct PreferenceGenerator *pg)
+{
+  struct GNUNET_TIME_Relative time_delta;
+  double delta_value;
+  double pref_value;
+
+  /* Calculate the current preference value */
+  switch (pg->type)
+  {
+  case GNUNET_ATS_TEST_TG_CONSTANT:
+    pref_value = pg->base_value;
+    break;
+
+  case GNUNET_ATS_TEST_TG_LINEAR:
+    time_delta = GNUNET_TIME_absolute_get_duration (pg->time_start);
+    /* Calculate point of time in the current period */
+    time_delta.rel_value_us = time_delta.rel_value_us
+                              % pg->duration_period.rel_value_us;
+    delta_value = ((double) time_delta.rel_value_us
+                   / pg->duration_period.rel_value_us) * (pg->max_value
+                                                          - pg->base_value);
+    if ((pg->max_value < pg->base_value) &&
+        ((pg->max_value - pg->base_value) > pg->base_value))
+    {
+      /* This will cause an underflow */
+      GNUNET_break (0);
+    }
+    pref_value = pg->base_value + delta_value;
+    break;
+
+  case GNUNET_ATS_TEST_TG_RANDOM:
+    delta_value = (double) GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK,
+                                                     10000 * (pg->max_value
+                                                              - pg->base_value))
+                  / 10000;
+    pref_value = pg->base_value + delta_value;
+    break;
+
+  case GNUNET_ATS_TEST_TG_SINUS:
+    time_delta = GNUNET_TIME_absolute_get_duration (pg->time_start);
+    /* Calculate point of time in the current period */
+    time_delta.rel_value_us = time_delta.rel_value_us
+                              % pg->duration_period.rel_value_us;
+    if ((pg->max_value - pg->base_value) > pg->base_value)
+    {
+      /* This will cause an underflow for second half of sinus period,
+       * will be detected in general when experiments are loaded */
+      GNUNET_break (0);
+    }
+    delta_value = (pg->max_value - pg->base_value)
+                  * sin ((2 * M_PI)
+                         / ((double) pg->duration_period.rel_value_us)
+                         * time_delta.rel_value_us);
+    pref_value = pg->base_value + delta_value;
+    break;
+
+  default:
+    pref_value = 0.0;
+    break;
+  }
+  GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Current preference value is %f\n",
+              pref_value);
+  return pref_value;
+}
+
+
+static void
+set_feedback_task (void *cls)
+{
+  struct PreferenceGenerator *pg = cls;
+  struct TestPeer *p;
+  double feedback;
+  uint32_t bw_acc_out;
+  uint32_t bw_acc_in;
+  uint32_t delay_acc_in;
+  struct GNUNET_TIME_Relative dur;
+  double p_new;
+
+  pg->feedback_task = NULL;
+
+  if (NULL == (p = find_peer_by_id (pg->peer)))
+  {
+    GNUNET_break (0);
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                "Setting feedback for unknown peer %u\n", pg->peer);
+    return;
+  }
+
+  switch (pg->kind)
+  {
+  case GNUNET_ATS_PREFERENCE_BANDWIDTH:
+    dur = GNUNET_TIME_absolute_get_duration (pg->feedback_last_bw_update);
+    bw_acc_in = dur.rel_value_us * pg->last_assigned_bw_in
+                + pg->feedback_bw_in_acc;
+    pg->feedback_bw_in_acc = 0;
+
+    bw_acc_out = dur.rel_value_us * pg->last_assigned_bw_out
+                 + pg->feedback_bw_out_acc;
+    p_new = get_preference (pg);
+    feedback = (p_new / pg->pref_bw_old) * (bw_acc_in + bw_acc_out)
+               / (2 * GNUNET_TIME_absolute_get_duration (
+                    pg->feedback_last).rel_value_us);
+
+    break;
+
+  case GNUNET_ATS_PREFERENCE_LATENCY:
+    dur = GNUNET_TIME_absolute_get_duration (pg->feedback_last_delay_update);
+    delay_acc_in = dur.rel_value_us * pg->last_delay_value
+                   + pg->feedback_delay_acc;
+    pg->feedback_delay_acc = 0;
+
+    p_new = get_preference (pg);
+    feedback = (p_new / pg->pref_latency_old) * (delay_acc_in)
+               / (GNUNET_TIME_absolute_get_duration (
+                    pg->feedback_last).rel_value_us);
+
+    break;
+
+  default:
+    GNUNET_break (0);
+    feedback = 0.0;
+    break;
+  }
+  GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+              "Giving feedback for peer [%u] for client %p pref %s of %.3f\n",
+              pg->peer, NULL + (pg->client_id),
+              GNUNET_ATS_print_preference_type (pg->kind),
+              feedback);
+
+  sh->sf->s_feedback (sh->sf->cls, NULL + (pg->client_id), &p->peer_id,
+                      pg->feedback_frequency, pg->kind, feedback);
+  pg->feedback_last = GNUNET_TIME_absolute_get ();
+
+
+  pg->feedback_bw_out_acc = 0;
+  pg->feedback_bw_in_acc = 0;
+  pg->feedback_last_bw_update = GNUNET_TIME_absolute_get ();
+
+  pg->feedback_delay_acc = 0;
+  pg->feedback_last_delay_update = GNUNET_TIME_absolute_get ();
+
+
+  pg->feedback_task = GNUNET_SCHEDULER_add_delayed (pg->feedback_frequency,
+                                                    &set_feedback_task, pg);
+}
+
+
+static void
+set_pref_task (void *cls)
+{
+  struct PreferenceGenerator *pg = cls;
+  struct TestPeer *p;
+  double pref_value;
+
+  pg->set_task = NULL;
+
+  if (NULL == (p = find_peer_by_id (pg->peer)))
+  {
+    GNUNET_break (0);
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                "Setting preference for unknown peer %u\n", pg->peer);
+    return;
+  }
+
+  pref_value = get_preference (pg);
+  switch (pg->kind)
+  {
+  case GNUNET_ATS_PREFERENCE_BANDWIDTH:
+    pg->pref_bw_old = pref_value;
+    break;
+
+  case GNUNET_ATS_PREFERENCE_LATENCY:
+    pg->pref_latency_old = pref_value;
+    break;
+
+  default:
+    break;
+  }
+
+  p->pref_abs[pg->kind] = pref_value;
+
+  GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+              "Setting preference for peer [%u] for client %p pref %s to %f\n",
+              pg->peer, NULL + (pg->client_id),
+              GNUNET_ATS_print_preference_type (pg->kind), pref_value);
+
+  if (GNUNET_YES == opt_disable_normalization)
+  {
+    p->pref_abs[pg->kind] = pref_value;
+    p->pref_norm[pg->kind] = pref_value;
+    sh->sf->s_pref (sh->sf->cls, &p->peer_id, pg->kind, pref_value);
+  }
+  else
+    update_preference (NULL + (pg->client_id),
+                       &p->peer_id,
+                       pg->kind,
+                       pref_value);
+
+  pg->set_task = GNUNET_SCHEDULER_add_delayed (pg->frequency,
+                                               &set_pref_task,
+                                               pg);
+}
+
+
+static struct PreferenceGenerator *
+find_pref_gen (unsigned int peer, enum GNUNET_ATS_PreferenceKind kind)
+{
+  struct PreferenceGenerator *cur;
+
+  for (cur = pref_gen_head; NULL != cur; cur = cur->next)
+    if (cur->peer == peer)
+    {
+      if ((cur->kind == kind) || (GNUNET_ATS_PREFERENCE_END == kind))
+        return cur;
+    }
+  return NULL;
+}
+
+
+void
+GNUNET_ATS_solver_generate_preferences_stop (struct PreferenceGenerator *pg)
+{
+  GNUNET_CONTAINER_DLL_remove (pref_gen_head, pref_gen_tail, pg);
+
+  if (NULL != pg->feedback_task)
+  {
+    GNUNET_SCHEDULER_cancel (pg->feedback_task);
+    pg->feedback_task = NULL;
+  }
+
+  if (NULL != pg->set_task)
+  {
+    GNUNET_SCHEDULER_cancel (pg->set_task);
+    pg->set_task = NULL;
+  }
+  GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+              "Removing old up preference generator peer [%u] `%s'\n",
+              pg->peer, GNUNET_ATS_print_preference_type (pg->kind));
+
+  GNUNET_free (pg);
+}
+
+
+static struct TestAddress*
+find_active_address (struct TestPeer *p)
+{
+  struct TestAddress *cur;
+
+  for (cur = p->addr_head; NULL != cur; cur = cur->next)
+    if (GNUNET_YES == cur->ats_addr->active)
+      return cur;
+  return NULL;
+}
+
+
+/**
+ * Generate between the source master and the partner and set property with a
+ * value depending on the generator.
+ *
+ * @param peer source
+ * @param address_id partner
+ * @param client_id the client
+ * @param type type of generator
+ * @param base_value base value
+ * @param value_rate maximum value
+ * @param period duration of a period of generation (~ 1/frequency)
+ * @param frequency how long to generate property
+ * @param kind ATS preference to generate
+ * @param feedback_frequency how often to give feedback
+ * @return the preference generator
+ */
+struct PreferenceGenerator *
+GNUNET_ATS_solver_generate_preferences_start (unsigned int peer,
+                                              unsigned int address_id,
+                                              unsigned int client_id,
+                                              enum GeneratorType type,
+                                              long int base_value,
+                                              long int value_rate,
+                                              struct GNUNET_TIME_Relative
+                                              period,
+                                              struct GNUNET_TIME_Relative
+                                              frequency,
+                                              enum GNUNET_ATS_PreferenceKind
+                                              kind,
+                                              struct GNUNET_TIME_Relative
+                                              feedback_frequency)
+{
+  struct PreferenceGenerator *pg;
+  struct TestPeer *p;
+
+  if (NULL == (p = find_peer_by_id (peer)))
+  {
+    GNUNET_break (0);
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                "Starting preference for unknown peer %u\n", peer);
+    return NULL;
+  }
+
+  pg = GNUNET_new (struct PreferenceGenerator);
+  GNUNET_CONTAINER_DLL_insert (pref_gen_head, pref_gen_tail, pg);
+  pg->type = type;
+  pg->peer = peer;
+  pg->client_id = client_id;
+  pg->kind = kind;
+  pg->base_value = base_value;
+  pg->max_value = value_rate;
+  pg->duration_period = period;
+  pg->frequency = frequency;
+  pg->time_start = GNUNET_TIME_absolute_get ();
+  pg->feedback_frequency = feedback_frequency;
+
+  switch (type)
+  {
+  case GNUNET_ATS_TEST_TG_CONSTANT:
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                "Setting up %s preference generator peer [%u] `%s' max %u Bips\n",
+                print_generator_type (type), pg->peer,
+                GNUNET_ATS_print_preference_type (kind),
+                base_value);
+    break;
+
+  case GNUNET_ATS_TEST_TG_LINEAR:
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                "Setting up %s preference generator peer [%u] `%s' min %u Bips max %u Bips\n",
+                print_generator_type (type), pg->peer,
+                GNUNET_ATS_print_preference_type (kind),
+                base_value, value_rate);
+    break;
+
+  case GNUNET_ATS_TEST_TG_SINUS:
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                "Setting up %s preference generator peer [%u] `%s' baserate %u Bips, amplitude %u Bps\n",
+                print_generator_type (type), pg->peer,
+                GNUNET_ATS_print_preference_type (kind),
+                base_value, value_rate);
+    break;
+
+  case GNUNET_ATS_TEST_TG_RANDOM:
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                "Setting up %s preference generator peer [%u] `%s' min %u Bips max %u Bps\n",
+                print_generator_type (type), pg->peer,
+                GNUNET_ATS_print_preference_type (kind),
+                base_value, value_rate);
+    break;
+
+  default:
+    break;
+  }
+
+  pg->set_task = GNUNET_SCHEDULER_add_now (&set_pref_task, pg);
+  if (GNUNET_TIME_UNIT_FOREVER_REL.rel_value_us !=
+      feedback_frequency.rel_value_us)
+  {
+    struct TestAddress *addr = find_active_address (p);
+
+    pg->last_assigned_bw_in = p->assigned_bw_in;
+    pg->last_assigned_bw_out = p->assigned_bw_out;
+    pg->feedback_bw_in_acc = 0;
+    pg->feedback_bw_out_acc = 0;
+    pg->last_delay_value = addr->prop_norm[GNUNET_ATS_QUALITY_NET_DELAY];
+    pg->feedback_delay_acc = 0;
+
+    pg->feedback_last_bw_update = GNUNET_TIME_absolute_get ();
+    pg->feedback_last_delay_update = GNUNET_TIME_absolute_get ();
+    pg->feedback_last = GNUNET_TIME_absolute_get ();
+    pg->feedback_task = GNUNET_SCHEDULER_add_delayed (feedback_frequency,
+                                                      &set_feedback_task, pg);
+  }
+
+  return pg;
+}
+
+
+/**
+ * Stop all preferences generators
+ */
+void
+GNUNET_ATS_solver_generate_preferences_stop_all ()
+{
+  struct PreferenceGenerator *cur;
+  struct PreferenceGenerator *next;
+
+  next = pref_gen_head;
+  for (cur = next; NULL != cur; cur = next)
+  {
+    next = cur->next;
+    GNUNET_ATS_solver_generate_preferences_stop (cur);
+  }
+}
+
+
+/**
+ * Experiments
+ */
+static const char *
+print_op (enum OperationType op)
+{
+  switch (op)
+  {
+  case SOLVER_OP_ADD_ADDRESS:
+    return "ADD_ADDRESS";
+
+  case SOLVER_OP_DEL_ADDRESS:
+    return "DEL_ADDRESS";
+
+  case SOLVER_OP_START_SET_PREFERENCE:
+    return "START_SET_PREFERENCE";
+
+  case SOLVER_OP_STOP_SET_PREFERENCE:
+    return "STOP_STOP_PREFERENCE";
+
+  case SOLVER_OP_START_SET_PROPERTY:
+    return "START_SET_PROPERTY";
+
+  case SOLVER_OP_STOP_SET_PROPERTY:
+    return "STOP_SET_PROPERTY";
+
+  case SOLVER_OP_START_REQUEST:
+    return "START_REQUEST";
+
+  case SOLVER_OP_STOP_REQUEST:
+    return "STOP_REQUEST";
+
+  default:
+    break;
+  }
+  return "";
+}
+
+
+static struct Experiment *
+create_experiment ()
+{
+  struct Experiment *e;
+
+  e = GNUNET_new (struct Experiment);
+  e->name = NULL;
+  e->start = NULL;
+  e->total_duration = GNUNET_TIME_UNIT_ZERO;
+  return e;
+}
+
+
+static void
+free_experiment (struct Experiment *e)
+{
+  struct Episode *cur;
+  struct Episode *next;
+  struct GNUNET_ATS_TEST_Operation *cur_o;
+  struct GNUNET_ATS_TEST_Operation *next_o;
+
+  next = e->start;
+  for (cur = next; NULL != cur; cur = next)
+  {
+    next = cur->next;
+
+    next_o = cur->head;
+    for (cur_o = next_o; NULL != cur_o; cur_o = next_o)
+    {
+      next_o = cur_o->next;
+      GNUNET_free (cur_o->address);
+      GNUNET_free (cur_o->plugin);
+      GNUNET_free (cur_o);
+    }
+    GNUNET_free (cur);
+  }
+
+  GNUNET_free (e->name);
+  GNUNET_free (e->log_prefix);
+  GNUNET_free (e->log_output_dir);
+  GNUNET_free (e->cfg_file);
+  GNUNET_free (e);
+}
+
+
+static int
+load_op_add_address (struct GNUNET_ATS_TEST_Operation *o,
+                     struct Episode *e,
+                     int op_counter,
+                     char *sec_name,
+                     const struct GNUNET_CONFIGURATION_Handle *cfg)
+{
+  char *op_name;
+  char *op_network;
+
+  /* peer pid */
+  GNUNET_asprintf (&op_name, "op-%u-peer-id", op_counter);
+  if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_number (cfg,
+                                                              sec_name, op_name,
+                                                              &o->peer_id))
+  {
+    fprintf (stderr, "Missing peer-id in operation %u `%s' in episode `%s'\n",
+             op_counter, "ADD_ADDRESS", op_name);
+    GNUNET_free (op_name);
+    return GNUNET_SYSERR;
+  }
+  GNUNET_free (op_name);
+
+  /* address pid */
+  GNUNET_asprintf (&op_name, "op-%u-address-id", op_counter);
+  if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_number (cfg,
+                                                              sec_name, op_name,
+                                                              &o->address_id))
+  {
+    fprintf (stderr,
+             "Missing address-id in operation %u `%s' in episode `%s'\n",
+             op_counter, "ADD_ADDRESS", op_name);
+    GNUNET_free (op_name);
+    return GNUNET_SYSERR;
+  }
+  GNUNET_free (op_name);
+
+  /* plugin */
+  GNUNET_asprintf (&op_name, "op-%u-plugin", op_counter);
+  if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_string (cfg,
+                                                              sec_name, op_name,
+                                                              &o->plugin))
+  {
+    fprintf (stderr, "Missing plugin in operation %u `%s' in episode `%s'\n",
+             op_counter, "ADD_ADDRESS", op_name);
+    GNUNET_free (op_name);
+    return GNUNET_SYSERR;
+  }
+  GNUNET_free (op_name);
+
+  /* address  */
+  GNUNET_asprintf (&op_name, "op-%u-address", op_counter);
+  if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_string (cfg,
+                                                              sec_name, op_name,
+                                                              &o->address))
+  {
+    fprintf (stderr, "Missing address in operation %u `%s' in episode `%s'\n",
+             op_counter, "ADD_ADDRESS", op_name);
+    GNUNET_free (op_name);
+    return GNUNET_SYSERR;
+  }
+  GNUNET_free (op_name);
+
+  /* session */
+  GNUNET_asprintf (&op_name, "op-%u-address-session", op_counter);
+  if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_number (cfg,
+                                                              sec_name, op_name,
+                                                              &o->
+                                                              address_session))
+  {
+    fprintf (stderr,
+             "Missing address-session in operation %u `%s' in episode `%s'\n",
+             op_counter, "ADD_ADDRESS", op_name);
+    GNUNET_free (op_name);
+    return GNUNET_SYSERR;
+  }
+  GNUNET_free (op_name);
+
+  /* network */
+  GNUNET_asprintf (&op_name, "op-%u-address-network", op_counter);
+  if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_string (cfg,
+                                                              sec_name, op_name,
+                                                              &op_network))
+  {
+    fprintf (stderr,
+             "Missing address-network in operation %u `%s' in episode `%s'\n",
+             op_counter, "ADD_ADDRESS", op_name);
+    GNUNET_free (op_name);
+    return GNUNET_SYSERR;
+  }
+  else
+  {
+    GNUNET_STRINGS_utf8_toupper (op_network, op_network);
+    if (0 == strcmp (op_network, "UNSPECIFIED"))
+    {
+      o->address_network = GNUNET_NT_UNSPECIFIED;
+    }
+    else if (0 == strcmp (op_network, "LOOPBACK"))
+    {
+      o->address_network = GNUNET_NT_LOOPBACK;
+    }
+    else if (0 == strcmp (op_network, "LAN"))
+    {
+      o->address_network = GNUNET_NT_LAN;
+    }
+    else if (0 == strcmp (op_network, "WAN"))
+    {
+      o->address_network = GNUNET_NT_WAN;
+    }
+    else if (0 == strcmp (op_network, "WLAN"))
+    {
+      o->address_network = GNUNET_NT_WLAN;
+    }
+    else if (0 == strcmp (op_network, "BT"))
+    {
+      o->address_network = GNUNET_NT_BT;
+    }
+    else
+    {
+      fprintf (stderr,
+               "Invalid address-network in operation %u `%s' in episode `%s': `%s'\n",
+               op_counter, "ADD_ADDRESS", op_name, op_network);
+      GNUNET_free (op_network);
+      GNUNET_free (op_name);
+      return GNUNET_SYSERR;
+    }
+  }
+  GNUNET_free (op_network);
+  GNUNET_free (op_name);
+
+  GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+              "Found operation %s: [%llu:%llu] address `%s' plugin `%s' \n",
+              "ADD_ADDRESS", o->peer_id, o->address_id, o->address, o->plugin);
+
+  return GNUNET_OK;
+}
+
+
+static int
+load_op_del_address (struct GNUNET_ATS_TEST_Operation *o,
+                     struct Episode *e,
+                     int op_counter,
+                     char *sec_name,
+                     const struct GNUNET_CONFIGURATION_Handle *cfg)
+{
+  char *op_name;
+
+  // char *op_network;
+
+  /* peer pid */
+  GNUNET_asprintf (&op_name, "op-%u-peer-id", op_counter);
+  if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_number (cfg,
+                                                              sec_name, op_name,
+                                                              &o->peer_id))
+  {
+    fprintf (stderr, "Missing peer-id in operation %u `%s' in episode `%s'\n",
+             op_counter, "DEL_ADDRESS", op_name);
+    GNUNET_free (op_name);
+    return GNUNET_SYSERR;
+  }
+  GNUNET_free (op_name);
+
+  /* address pid */
+  GNUNET_asprintf (&op_name, "op-%u-address-id", op_counter);
+  if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_number (cfg,
+                                                              sec_name, op_name,
+                                                              &o->address_id))
+  {
+    fprintf (stderr,
+             "Missing address-id in operation %u `%s' in episode `%s'\n",
+             op_counter, "DEL_ADDRESS", op_name);
+    GNUNET_free (op_name);
+    return GNUNET_SYSERR;
+  }
+  GNUNET_free (op_name);
+
+#if 0
+  /* plugin */
+  GNUNET_asprintf (&op_name, "op-%u-plugin", op_counter);
+  if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_string (cfg,
+                                                              sec_name, op_name,
+                                                              &o->plugin))
+  {
+    fprintf (stderr, "Missing plugin in operation %u `%s' in episode `%s'\n",
+             op_counter, "DEL_ADDRESS", op_name);
+    GNUNET_free (op_name);
+    return GNUNET_SYSERR;
+  }
+  GNUNET_free (op_name);
+
+  /* address  */
+  GNUNET_asprintf (&op_name, "op-%u-address", op_counter);
+  if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_string (cfg,
+                                                              sec_name, op_name,
+                                                              &o->address))
+  {
+    fprintf (stderr, "Missing address in operation %u `%s' in episode `%s'\n",
+             op_counter, "DEL_ADDRESS", op_name);
+    GNUNET_free (op_name);
+    return GNUNET_SYSERR;
+  }
+  GNUNET_free (op_name);
+
+  /* session */
+  GNUNET_asprintf (&op_name, "op-%u-address-session", op_counter);
+  if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_number (cfg,
+                                                              sec_name, op_name,
+                                                              &o->
+                                                              address_session))
+  {
+    fprintf (stderr,
+             "Missing address-session in operation %u `%s' in episode `%s'\n",
+             op_counter, "DEL_ADDRESS", op_name);
+    GNUNET_free (op_name);
+    return GNUNET_SYSERR;
+  }
+  GNUNET_free (op_name);
+#endif
+
+  GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+              "Found operation %s: [%llu:%llu] address `%s' plugin `%s' \n",
+              "DEL_ADDRESS", o->peer_id, o->address_id, o->address, o->plugin);
+
+  return GNUNET_OK;
+}
+
+
+static enum GNUNET_ATS_Property
+parse_preference_string (const char *str)
+{
+  int c = 0;
+  char *props[GNUNET_ATS_PreferenceCount] = GNUNET_ATS_PreferenceTypeString;
+
+  for (c = 0; c < GNUNET_ATS_PreferenceCount; c++)
+    if (0 == strcmp (str, props[c]))
+      return c;
+  return 0;
+}
+
+
+static int
+load_op_start_set_preference (struct GNUNET_ATS_TEST_Operation *o,
+                              struct Episode *e,
+                              int op_counter,
+                              char *sec_name,
+                              const struct GNUNET_CONFIGURATION_Handle *cfg)
+{
+  char *op_name;
+  char *type;
+  char *pref;
+
+  /* peer pid */
+  GNUNET_asprintf (&op_name, "op-%u-peer-id", op_counter);
+  if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_number (cfg,
+                                                              sec_name, op_name,
+                                                              &o->peer_id))
+  {
+    fprintf (stderr, "Missing peer-id in operation %u  `%s' in episode `%s'\n",
+             op_counter, "START_SET_PREFERENCE", op_name);
+    GNUNET_free (op_name);
+    return GNUNET_SYSERR;
+  }
+  GNUNET_free (op_name);
+
+  /* address pid */
+  GNUNET_asprintf (&op_name, "op-%u-client-id", op_counter);
+  if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_number (cfg,
+                                                              sec_name, op_name,
+                                                              &o->client_id))
+  {
+    fprintf (stderr, "Missing client-id in operation %u `%s' in episode `%s'\n",
+             op_counter, "START_SET_PREFERENCE", op_name);
+    GNUNET_free (op_name);
+    return GNUNET_SYSERR;
+  }
+  GNUNET_free (op_name);
+
+  /* generator */
+  GNUNET_asprintf (&op_name, "op-%u-gen-type", op_counter);
+  if ((GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_string (cfg,
+                                                               sec_name,
+                                                               op_name, &type)))
+  {
+    fprintf (stderr, "Missing type in operation %u `%s' in episode `%s'\n",
+             op_counter, "START_SET_PREFERENCE", op_name);
+    GNUNET_free (op_name);
+    return GNUNET_SYSERR;
+  }
+
+  /* Load arguments for set_rate, start_send, set_preference */
+  if (0 == strcmp (type, "constant"))
+  {
+    o->gen_type = GNUNET_ATS_TEST_TG_CONSTANT;
+  }
+  else if (0 == strcmp (type, "linear"))
+  {
+    o->gen_type = GNUNET_ATS_TEST_TG_LINEAR;
+  }
+  else if (0 == strcmp (type, "sinus"))
+  {
+    o->gen_type = GNUNET_ATS_TEST_TG_SINUS;
+  }
+  else if (0 == strcmp (type, "random"))
+  {
+    o->gen_type = GNUNET_ATS_TEST_TG_RANDOM;
+  }
+  else
+  {
+    fprintf (stderr, "Invalid generator type %u `%s' in episode %u\n",
+             op_counter, op_name, e->id);
+    GNUNET_free (type);
+    GNUNET_free (op_name);
+    return GNUNET_SYSERR;
+  }
+  GNUNET_free (type);
+  GNUNET_free (op_name);
+
+
+  /* Get base rate */
+  GNUNET_asprintf (&op_name, "op-%u-base-rate", op_counter);
+  if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_number (cfg,
+                                                              sec_name, op_name,
+                                                              &o->base_rate))
+  {
+    fprintf (stderr, "Missing base rate in operation %u `%s' in episode %u\n",
+             op_counter, op_name, e->id);
+    GNUNET_free (op_name);
+    return GNUNET_SYSERR;
+  }
+  GNUNET_free (op_name);
+
+
+  /* Get max rate */
+  GNUNET_asprintf (&op_name, "op-%u-max-rate", op_counter);
+  if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_number (cfg,
+                                                              sec_name, op_name,
+                                                              &o->max_rate))
+  {
+    if ((GNUNET_ATS_TEST_TG_LINEAR == o->gen_type) ||
+        (GNUNET_ATS_TEST_TG_RANDOM == o->gen_type) ||
+        (GNUNET_ATS_TEST_TG_SINUS == o->gen_type))
+    {
+      fprintf (stderr, "Missing max rate in operation %u `%s' in episode %u\n",
+               op_counter, op_name, e->id);
+      GNUNET_free (op_name);
+      return GNUNET_SYSERR;
+    }
+  }
+  GNUNET_free (op_name);
+
+  /* Get period */
+  GNUNET_asprintf (&op_name, "op-%u-period", op_counter);
+  if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_time (cfg,
+                                                            sec_name, op_name,
+                                                            &o->period))
+  {
+    o->period = e->duration;
+  }
+  GNUNET_free (op_name);
+
+  /* Get frequency */
+  GNUNET_asprintf (&op_name, "op-%u-frequency", op_counter);
+  if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_time (cfg,
+                                                            sec_name, op_name,
+                                                            &o->frequency))
+  {
+    fprintf (stderr, "Missing frequency in operation %u `%s' in episode %u\n",
+             op_counter, op_name, e->id);
+    GNUNET_free (op_name);
+    return GNUNET_SYSERR;
+  }
+  GNUNET_free (op_name);
+
+  /* Get preference */
+  GNUNET_asprintf (&op_name, "op-%u-pref", op_counter);
+  if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_string (cfg,
+                                                              sec_name, op_name,
+                                                              &pref))
+  {
+    fprintf (stderr, "Missing preference in operation %u `%s' in episode %u\n",
+             op_counter, op_name, e->id);
+    GNUNET_free (op_name);
+    return GNUNET_SYSERR;
+  }
+
+  if (0 == (o->pref_type = parse_preference_string (pref)))
+  {
+    fprintf (stderr, "Invalid preference in operation %u `%s' in episode %u\n",
+             op_counter, op_name, e->id);
+    GNUNET_free (op_name);
+    GNUNET_free (pref);
+    return GNUNET_SYSERR;
+  }
+  GNUNET_free (pref);
+  GNUNET_free (op_name);
+
+  /* Get feedback delay */
+  GNUNET_asprintf (&op_name, "op-%u-feedback_delay", op_counter);
+  if (GNUNET_OK == GNUNET_CONFIGURATION_get_value_time (cfg,
+                                                        sec_name, op_name,
+                                                        &o->feedback_delay))
+  {
+    fprintf (stderr,
+             "Using feedback delay %llu in operation %u `%s' in episode %u\n",
+             (long long unsigned int) o->feedback_delay.rel_value_us,
+             op_counter, op_name, e->id);
+  }
+  else
+    o->feedback_delay = GNUNET_TIME_UNIT_FOREVER_REL;
+  GNUNET_free (op_name);
+
+  GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+              "Found operation %s: [%llu:%llu]: %s = %llu\n",
+              "START_SET_PREFERENCE", o->peer_id, o->address_id,
+              GNUNET_ATS_print_preference_type (o->pref_type), o->base_rate);
+
+  return GNUNET_OK;
+}
+
+
+static int
+load_op_stop_set_preference (struct GNUNET_ATS_TEST_Operation *o,
+                             struct Episode *e,
+                             int op_counter,
+                             char *sec_name,
+                             const struct GNUNET_CONFIGURATION_Handle *cfg)
+{
+  char *op_name;
+  char *pref;
+
+  /* peer pid */
+  GNUNET_asprintf (&op_name, "op-%u-peer-id", op_counter);
+  if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_number (cfg,
+                                                              sec_name, op_name,
+                                                              &o->peer_id))
+  {
+    fprintf (stderr, "Missing peer-id in operation %u  `%s' in episode `%s'\n",
+             op_counter, "STOP_SET_PREFERENCE", op_name);
+    GNUNET_free (op_name);
+    return GNUNET_SYSERR;
+  }
+  GNUNET_free (op_name);
+
+  /* address pid */
+  GNUNET_asprintf (&op_name, "op-%u-address-id", op_counter);
+  if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_number (cfg,
+                                                              sec_name, op_name,
+                                                              &o->address_id))
+  {
+    fprintf (stderr,
+             "Missing address-id in operation %u `%s' in episode `%s'\n",
+             op_counter, "STOP_SET_PREFERENCE", op_name);
+    GNUNET_free (op_name);
+    return GNUNET_SYSERR;
+  }
+  GNUNET_free (op_name);
+
+  /* Get preference */
+  GNUNET_asprintf (&op_name, "op-%u-pref", op_counter);
+  if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_string (cfg,
+                                                              sec_name, op_name,
+                                                              &pref))
+  {
+    fprintf (stderr,
+             "Missing preference in operation %u `%s' in episode `%s'\n",
+             op_counter, "STOP_SET_PREFERENCE", op_name);
+    GNUNET_free (op_name);
+    return GNUNET_SYSERR;
+  }
+
+  if (0 == (o->pref_type = parse_preference_string (pref)))
+  {
+    fprintf (stderr, "Invalid preference in operation %u `%s' in episode %u\n",
+             op_counter, op_name, e->id);
+    GNUNET_free (op_name);
+    GNUNET_free (pref);
+    return GNUNET_SYSERR;
+  }
+  GNUNET_free (pref);
+  GNUNET_free (op_name);
+
+  GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+              "Found operation %s: [%llu:%llu]: %s\n",
+              "STOP_SET_PREFERENCE", o->peer_id, o->address_id,
+              GNUNET_ATS_print_preference_type (o->pref_type));
+  return GNUNET_OK;
+}
+
+
+static enum GNUNET_ATS_Property
+parse_property_string (const char *str)
+{
+  enum GNUNET_ATS_Property c;
+
+  for (c = 0; c < GNUNET_ATS_PropertyCount; c++)
+    if (0 == strcmp (str,
+                     GNUNET_ATS_print_property_type (c)))
+      return c;
+  return 0;
+}
+
+
+static int
+load_op_start_set_property (struct GNUNET_ATS_TEST_Operation *o,
+                            struct Episode *e,
+                            int op_counter,
+                            char *sec_name,
+                            const struct GNUNET_CONFIGURATION_Handle *cfg)
+{
+  char *op_name;
+  char *type;
+  char *prop;
+
+  /* peer pid */
+  GNUNET_asprintf (&op_name, "op-%u-peer-id", op_counter);
+  if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_number (cfg,
+                                                              sec_name, op_name,
+                                                              &o->peer_id))
+  {
+    fprintf (stderr, "Missing peer-id in operation %u  `%s' in episode `%s'\n",
+             op_counter, "START_SET_PROPERTY", op_name);
+    GNUNET_free (op_name);
+    return GNUNET_SYSERR;
+  }
+  GNUNET_free (op_name);
+
+  /* address pid */
+  GNUNET_asprintf (&op_name, "op-%u-address-id", op_counter);
+  if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_number (cfg,
+                                                              sec_name, op_name,
+                                                              &o->address_id))
+  {
+    fprintf (stderr,
+             "Missing address-id in operation %u `%s' in episode `%s'\n",
+             op_counter, "START_SET_PROPERTY", op_name);
+    GNUNET_free (op_name);
+    return GNUNET_SYSERR;
+  }
+  GNUNET_free (op_name);
+
+  /* generator */
+  GNUNET_asprintf (&op_name, "op-%u-gen-type", op_counter);
+  if ((GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_string (cfg,
+                                                               sec_name,
+                                                               op_name, &type)))
+  {
+    fprintf (stderr, "Missing type in operation %u `%s' in episode `%s'\n",
+             op_counter, "START_SET_PROPERTY", op_name);
+    GNUNET_free (op_name);
+    return GNUNET_SYSERR;
+  }
+
+  /* Load arguments for set_rate, start_send, set_preference */
+  if (0 == strcmp (type, "constant"))
+  {
+    o->gen_type = GNUNET_ATS_TEST_TG_CONSTANT;
+  }
+  else if (0 == strcmp (type, "linear"))
+  {
+    o->gen_type = GNUNET_ATS_TEST_TG_LINEAR;
+  }
+  else if (0 == strcmp (type, "sinus"))
+  {
+    o->gen_type = GNUNET_ATS_TEST_TG_SINUS;
+  }
+  else if (0 == strcmp (type, "random"))
+  {
+    o->gen_type = GNUNET_ATS_TEST_TG_RANDOM;
+  }
+  else
+  {
+    fprintf (stderr, "Invalid generator type %u `%s' in episode %u\n",
+             op_counter, op_name, e->id);
+    GNUNET_free (type);
+    GNUNET_free (op_name);
+    return GNUNET_SYSERR;
+  }
+  GNUNET_free (type);
+  GNUNET_free (op_name);
+
+
+  /* Get base rate */
+  GNUNET_asprintf (&op_name, "op-%u-base-rate", op_counter);
+  if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_number (cfg,
+                                                              sec_name, op_name,
+                                                              &o->base_rate))
+  {
+    fprintf (stderr, "Missing base rate in operation %u `%s' in episode %u\n",
+             op_counter, op_name, e->id);
+    GNUNET_free (op_name);
+    return GNUNET_SYSERR;
+  }
+  GNUNET_free (op_name);
+
+
+  /* Get max rate */
+  GNUNET_asprintf (&op_name, "op-%u-max-rate", op_counter);
+  if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_number (cfg,
+                                                              sec_name, op_name,
+                                                              &o->max_rate))
+  {
+    if ((GNUNET_ATS_TEST_TG_LINEAR == o->gen_type) ||
+        (GNUNET_ATS_TEST_TG_RANDOM == o->gen_type) ||
+        (GNUNET_ATS_TEST_TG_SINUS == o->gen_type))
+    {
+      fprintf (stderr, "Missing max rate in operation %u `%s' in episode %u\n",
+               op_counter, op_name, e->id);
+      GNUNET_free (op_name);
+      return GNUNET_SYSERR;
+    }
+  }
+  GNUNET_free (op_name);
+
+  /* Get period */
+  GNUNET_asprintf (&op_name, "op-%u-period", op_counter);
+  if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_time (cfg,
+                                                            sec_name, op_name,
+                                                            &o->period))
+  {
+    o->period = e->duration;
+  }
+  GNUNET_free (op_name);
+
+  /* Get frequency */
+  GNUNET_asprintf (&op_name, "op-%u-frequency", op_counter);
+  if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_time (cfg,
+                                                            sec_name, op_name,
+                                                            &o->frequency))
+  {
+    fprintf (stderr, "Missing frequency in operation %u `%s' in episode %u\n",
+             op_counter, op_name, e->id);
+    GNUNET_free (op_name);
+    return GNUNET_SYSERR;
+  }
+  GNUNET_free (op_name);
+
+  /* Get preference */
+  GNUNET_asprintf (&op_name, "op-%u-property", op_counter);
+  if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_string (cfg,
+                                                              sec_name, op_name,
+                                                              &prop))
+  {
+    fprintf (stderr, "Missing property in operation %u `%s' in episode %u\n",
+             op_counter, op_name, e->id);
+    GNUNET_free (op_name);
+    GNUNET_free (prop);
+    return GNUNET_SYSERR;
+  }
+
+  if (0 == (o->prop_type = parse_property_string (prop)))
+  {
+    fprintf (stderr, "Invalid property in operation %u `%s' in episode %u\n",
+             op_counter, op_name, e->id);
+    GNUNET_free (op_name);
+    GNUNET_free (prop);
+    return GNUNET_SYSERR;
+  }
+
+  GNUNET_free (prop);
+  GNUNET_free (op_name);
+
+  GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+              "Found operation %s: [%llu:%llu] %s = %llu\n",
+              "START_SET_PROPERTY", o->peer_id, o->address_id,
+              GNUNET_ATS_print_property_type (o->prop_type), o->base_rate);
+
+  return GNUNET_OK;
+}
+
+
+static int
+load_op_stop_set_property (struct GNUNET_ATS_TEST_Operation *o,
+                           struct Episode *e,
+                           int op_counter,
+                           char *sec_name,
+                           const struct GNUNET_CONFIGURATION_Handle *cfg)
+{
+  char *op_name;
+  char *pref;
+
+  /* peer pid */
+  GNUNET_asprintf (&op_name, "op-%u-peer-id", op_counter);
+  if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_number (cfg,
+                                                              sec_name, op_name,
+                                                              &o->peer_id))
+  {
+    fprintf (stderr, "Missing peer-id in operation %u  `%s' in episode `%s'\n",
+             op_counter, "STOP_SET_PROPERTY", op_name);
+    GNUNET_free (op_name);
+    return GNUNET_SYSERR;
+  }
+  GNUNET_free (op_name);
+
+  /* address pid */
+  GNUNET_asprintf (&op_name, "op-%u-address-id", op_counter);
+  if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_number (cfg,
+                                                              sec_name, op_name,
+                                                              &o->address_id))
+  {
+    fprintf (stderr,
+             "Missing address-id in operation %u `%s' in episode `%s'\n",
+             op_counter, "STOP_SET_PROPERTY", op_name);
+    GNUNET_free (op_name);
+    return GNUNET_SYSERR;
+  }
+  GNUNET_free (op_name);
+
+  /* Get property */
+  GNUNET_asprintf (&op_name, "op-%u-property", op_counter);
+  if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_string (cfg,
+                                                              sec_name, op_name,
+                                                              &pref))
+  {
+    fprintf (stderr, "Missing property in operation %u `%s' in episode `%s'\n",
+             op_counter, "STOP_SET_PROPERTY", op_name);
+    GNUNET_free (op_name);
+    GNUNET_free (pref);
+    return GNUNET_SYSERR;
+  }
+
+  if (0 == (o->prop_type = parse_property_string (pref)))
+  {
+    fprintf (stderr, "Invalid property in operation %u `%s' in episode %u\n",
+             op_counter, op_name, e->id);
+    GNUNET_free (op_name);
+    GNUNET_free (pref);
+    return GNUNET_SYSERR;
+  }
+
+  GNUNET_free (pref);
+  GNUNET_free (op_name);
+
+  GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+              "Found operation %s: [%llu:%llu] %s\n",
+              "STOP_SET_PROPERTY", o->peer_id, o->address_id,
+              GNUNET_ATS_print_property_type (o->prop_type));
+
+  return GNUNET_OK;
+}
+
+
+static int
+load_op_start_request (struct GNUNET_ATS_TEST_Operation *o,
+                       struct Episode *e,
+                       int op_counter,
+                       char *sec_name,
+                       const struct GNUNET_CONFIGURATION_Handle *cfg)
+{
+  char *op_name;
+
+  /* peer pid */
+  GNUNET_asprintf (&op_name, "op-%u-peer-id", op_counter);
+  if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_number (cfg,
+                                                              sec_name, op_name,
+                                                              &o->peer_id))
+  {
+    fprintf (stderr, "Missing peer-id in operation %u  `%s' in episode `%s'\n",
+             op_counter, "START_REQUEST", op_name);
+    GNUNET_free (op_name);
+    return GNUNET_SYSERR;
+  }
+  GNUNET_free (op_name);
+  return GNUNET_OK;
+}
+
+
+static int
+load_op_stop_request (struct GNUNET_ATS_TEST_Operation *o,
+                      struct Episode *e,
+                      int op_counter,
+                      char *sec_name,
+                      const struct GNUNET_CONFIGURATION_Handle *cfg)
+{
+  char *op_name;
+
+  /* peer pid */
+  GNUNET_asprintf (&op_name, "op-%u-peer-id", op_counter);
+  if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_number (cfg,
+                                                              sec_name, op_name,
+                                                              &o->peer_id))
+  {
+    fprintf (stderr, "Missing peer-id in operation %u  `%s' in episode `%s'\n",
+             op_counter, "STOP_REQUEST", op_name);
+    GNUNET_free (op_name);
+    return GNUNET_SYSERR;
+  }
+  GNUNET_free (op_name);
+  return GNUNET_OK;
+}
+
+
+static int
+load_episode (struct Experiment *e, struct Episode *cur,
+              struct GNUNET_CONFIGURATION_Handle *cfg)
+{
+  struct GNUNET_ATS_TEST_Operation *o;
+  char *sec_name;
+  char *op_name;
+  char *op;
+  int op_counter = 0;
+  int res;
+
+  GNUNET_log (GNUNET_ERROR_TYPE_INFO, "=== Parsing episode %u\n", cur->id);
+  GNUNET_asprintf (&sec_name, "episode-%u", cur->id);
+
+  while (1)
+  {
+    /* Load operation */
+    GNUNET_asprintf (&op_name, "op-%u-operation", op_counter);
+    if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_string (cfg,
+                                                                sec_name,
+                                                                op_name, &op))
+    {
+      GNUNET_free (op_name);
+      break;
+    }
+    o = GNUNET_new (struct GNUNET_ATS_TEST_Operation);
+    GNUNET_log (GNUNET_ERROR_TYPE_INFO, "==== Parsing operation %u: `%s'\n",
+                cur->id, op_name);
+
+    /* operations = set_rate, start_send, stop_send, set_preference */
+    if (0 == strcmp (op, "address_add"))
+    {
+      o->type = SOLVER_OP_ADD_ADDRESS;
+      res = load_op_add_address (o, cur,
+                                 op_counter, sec_name, cfg);
+    }
+    else if (0 == strcmp (op, "address_del"))
+    {
+      o->type = SOLVER_OP_DEL_ADDRESS;
+      res = load_op_del_address (o, cur,
+                                 op_counter, sec_name, cfg);
+    }
+    else if (0 == strcmp (op, "start_set_property"))
+    {
+      o->type = SOLVER_OP_START_SET_PROPERTY;
+      res = load_op_start_set_property (o, cur,
+                                        op_counter, sec_name, cfg);
+    }
+    else if (0 == strcmp (op, "stop_set_property"))
+    {
+      o->type = SOLVER_OP_STOP_SET_PROPERTY;
+      res = load_op_stop_set_property (o, cur,
+                                       op_counter, sec_name, cfg);
+    }
+    else if (0 == strcmp (op, "start_set_preference"))
+    {
+      o->type = SOLVER_OP_START_SET_PREFERENCE;
+      res = load_op_start_set_preference (o, cur,
+                                          op_counter, sec_name, cfg);
+    }
+    else if (0 == strcmp (op, "stop_set_preference"))
+    {
+      o->type = SOLVER_OP_STOP_SET_PREFERENCE;
+      res = load_op_stop_set_preference (o, cur,
+                                         op_counter, sec_name, cfg);
+    }
+    else if (0 == strcmp (op, "start_request"))
+    {
+      o->type = SOLVER_OP_START_REQUEST;
+      res = load_op_start_request (o, cur,
+                                   op_counter, sec_name, cfg);
+    }
+    else if (0 == strcmp (op, "stop_request"))
+    {
+      o->type = SOLVER_OP_STOP_REQUEST;
+      res = load_op_stop_request (o, cur,
+                                  op_counter, sec_name, cfg);
+    }
+    else
+    {
+      fprintf (stderr, "Invalid operation %u `%s' in episode %u\n",
+               op_counter, op, cur->id);
+      res = GNUNET_SYSERR;
+    }
+
+    GNUNET_free (op);
+    GNUNET_free (op_name);
+
+    if (GNUNET_SYSERR == res)
+    {
+      GNUNET_free (o);
+      GNUNET_free (sec_name);
+      return GNUNET_SYSERR;
+    }
+
+    GNUNET_CONTAINER_DLL_insert_tail (cur->head, cur->tail, o);
+    op_counter++;
+  }
+  GNUNET_free (sec_name);
+  return GNUNET_OK;
+}
+
+
+static int
+load_episodes (struct Experiment *e, struct GNUNET_CONFIGURATION_Handle *cfg)
+{
+  int e_counter = 0;
+  char *sec_name;
+  struct GNUNET_TIME_Relative e_duration;
+  struct Episode *cur;
+  struct Episode *last;
+
+  e_counter = 0;
+  last = NULL;
+  while (1)
+  {
+    GNUNET_asprintf (&sec_name, "episode-%u", e_counter);
+    if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_time (cfg,
+                                                              sec_name,
+                                                              "duration",
+                                                              &e_duration))
+    {
+      GNUNET_free (sec_name);
+      break;
+    }
+
+    cur = GNUNET_new (struct Episode);
+    cur->duration = e_duration;
+    cur->id = e_counter;
+
+    if (GNUNET_OK != load_episode (e, cur, cfg))
+    {
+      GNUNET_free (sec_name);
+      GNUNET_free (cur);
+      return GNUNET_SYSERR;
+    }
+
+    GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Found episode %u with duration %s \n",
+                e_counter,
+                GNUNET_STRINGS_relative_time_to_string (cur->duration,
+                                                        GNUNET_YES));
+
+    /* Update experiment */
+    e->num_episodes++;
+    e->total_duration = GNUNET_TIME_relative_add (e->total_duration,
+                                                  cur->duration);
+    /* Put in linked list */
+    if (NULL == last)
+      e->start = cur;
+    else
+      last->next = cur;
+
+    GNUNET_free (sec_name);
+    e_counter++;
+    last = cur;
+  }
+  return e_counter;
+}
+
+
+static void
+timeout_experiment (void *cls)
+{
+  struct Experiment *e = cls;
+
+  e->experiment_timeout_task = NULL;
+  fprintf (stderr, "Experiment timeout!\n");
+
+  if (NULL != e->episode_timeout_task)
+  {
+    GNUNET_SCHEDULER_cancel (e->episode_timeout_task);
+    e->episode_timeout_task = NULL;
+  }
+
+  e->e_done_cb (e, GNUNET_TIME_absolute_get_duration (e->start_time),
+                GNUNET_SYSERR);
+}
+
+
+struct ATS_Address *
+create_ats_address (const struct GNUNET_PeerIdentity *peer,
+                    const char *plugin_name,
+                    const void *plugin_addr,
+                    size_t plugin_addr_len,
+                    uint32_t session_id,
+                    uint32_t network)
+{
+  struct ATS_Address *aa = NULL;
+
+  aa = GNUNET_malloc (sizeof(struct ATS_Address) + plugin_addr_len + strlen (
+                        plugin_name) + 1);
+  aa->atsi = GNUNET_new (struct GNUNET_ATS_Information);
+  aa->atsi[0].type = htonl (GNUNET_ATS_NETWORK_TYPE);
+  aa->atsi[0].value = htonl (network);
+  aa->atsi_count = 1;
+
+  aa->peer = *peer;
+  aa->addr_len = plugin_addr_len;
+  aa->addr = &aa[1];
+  aa->plugin = (char *) &aa[1] + plugin_addr_len;
+  GNUNET_memcpy (&aa[1], plugin_addr, plugin_addr_len);
+  GNUNET_memcpy (aa->plugin, plugin_name, strlen (plugin_name) + 1);
+  aa->session_id = session_id;
+
+  return aa;
+}
+
+
+static void
+enforce_add_address (struct GNUNET_ATS_TEST_Operation *op)
+{
+  struct TestPeer *p;
+  struct TestAddress *a;
+  int c;
+
+  if (NULL == (p = find_peer_by_id (op->peer_id)))
+  {
+    p = GNUNET_new (struct TestPeer);
+    p->id = op->peer_id;
+    p->assigned_bw_in = 0;
+    p->assigned_bw_out = 0;
+    memset (&p->peer_id, op->peer_id, sizeof(p->peer_id));
+    for (c = 0; c < GNUNET_ATS_PreferenceCount; c++)
+    {
+      p->pref_abs[c] = DEFAULT_ABS_PREFERENCE;
+      p->pref_norm[c] = DEFAULT_REL_PREFERENCE;
+    }
+
+    GNUNET_CONTAINER_DLL_insert (peer_head, peer_tail, p);
+  }
+
+  if (NULL != (find_address_by_id (p, op->address_id)))
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Duplicate address %u for peer %u\n",
+                op->address_id, op->peer_id);
+    return;
+  }
+
+  a = GNUNET_new (struct TestAddress);
+  a->aid = op->address_id;
+  a->network = op->address_network;
+  a->ats_addr = create_ats_address (&p->peer_id, op->plugin, op->address,
+                                    strlen (op->address) + 1,
+                                    op->address_session, op->address_network);
+  memset (&p->peer_id, op->peer_id, sizeof(p->peer_id));
+  GNUNET_CONTAINER_DLL_insert_tail (p->addr_head, p->addr_tail, a);
+
+  for (c = 0; c < GNUNET_ATS_PropertyCount; c++)
+    a->prop_norm[c] = DEFAULT_REL_QUALITY;
+
+  GNUNET_CONTAINER_multipeermap_put (sh->addresses, &p->peer_id, a->ats_addr,
+                                     GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE);
+
+  GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+              "Adding address %u for peer %u in network `%s'\n",
+              op->address_id, op->peer_id, GNUNET_NT_to_string (a->network));
+
+  sh->sf->s_add (sh->sf->cls, a->ats_addr, op->address_network);
+}
+
+
+static void
+enforce_del_address (struct GNUNET_ATS_TEST_Operation *op)
+{
+  struct TestPeer *p;
+  struct TestAddress *a;
+  struct PropertyGenerator *pg;
+
+  if (NULL == (p = find_peer_by_id (op->peer_id)))
+  {
+    GNUNET_break (0);
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                "Deleting address for unknown peer %u\n", op->peer_id);
+    return;
+  }
+
+  if (NULL == (a = find_address_by_id (p, op->address_id)))
+  {
+    GNUNET_break (0);
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                "Deleting address for unknown peer %u\n", op->peer_id);
+    return;
+  }
+
+  while (NULL != (pg = find_prop_gen (p->id, a->aid, 0)))
+  {
+    GNUNET_ATS_solver_generate_property_stop (pg);
+  }
+
+  GNUNET_assert (GNUNET_YES ==
+                 GNUNET_CONTAINER_multipeermap_remove (sh->addresses,
+                                                       &p->peer_id,
+                                                       a->ats_addr));
+  GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+              "Removing address %u for peer %u\n",
+              op->address_id,
+              op->peer_id);
+
+  sh->sf->s_del (sh->sf->cls, a->ats_addr);
+
+  if (NULL != l)
+  {
+    GNUNET_ATS_solver_logging_now (l);
+  }
+  GNUNET_CONTAINER_DLL_remove (p->addr_head, p->addr_tail, a);
+
+  GNUNET_free (a->ats_addr->atsi);
+  GNUNET_free (a->ats_addr);
+  GNUNET_free (a);
+}
+
+
+static void
+enforce_start_property (struct GNUNET_ATS_TEST_Operation *op)
+{
+  struct PropertyGenerator *pg;
+  struct TestPeer *p;
+  struct TestAddress *a;
+
+  if (NULL != (pg = find_prop_gen (op->peer_id, op->address_id, op->prop_type)))
+  {
+    GNUNET_ATS_solver_generate_property_stop (pg);
+    GNUNET_free (pg);
+  }
+
+  if (NULL == (p = find_peer_by_id (op->peer_id)))
+  {
+    GNUNET_break (0);
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                "Starting property generation for unknown peer %u\n",
+                op->peer_id);
+    return;
+  }
+
+  if (NULL == (a = find_address_by_id (p, op->address_id)))
+  {
+    GNUNET_break (0);
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                "Setting property for unknown address %u\n", op->peer_id);
+    return;
+  }
+
+  GNUNET_ATS_solver_generate_property_start (op->peer_id,
+                                             op->address_id,
+                                             p, a,
+                                             op->gen_type,
+                                             op->base_rate,
+                                             op->max_rate,
+                                             op->period,
+                                             op->frequency,
+                                             op->prop_type);
+}
+
+
+static void
+enforce_stop_property (struct GNUNET_ATS_TEST_Operation *op)
+{
+  struct PropertyGenerator *pg = find_prop_gen (op->peer_id, op->address_id,
+                                                op->prop_type);
+
+  if (NULL != pg)
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+                "Stopping preference generation for peer %u address %u\n",
+                op->peer_id,
+                op->address_id);
+    GNUNET_ATS_solver_generate_property_stop (pg);
+  }
+  else
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                "Cannot find preference generator for peer %u address %u\n",
+                op->peer_id, op->address_id);
+    GNUNET_break (0);
+  }
+}
+
+
+static void
+enforce_start_preference (struct GNUNET_ATS_TEST_Operation *op)
+{
+  struct PreferenceGenerator *pg;
+
+  if (NULL != (pg = find_pref_gen (op->peer_id, op->pref_type)))
+  {
+    GNUNET_ATS_solver_generate_preferences_stop (pg);
+    GNUNET_free (pg);
+  }
+
+  if (NULL == (find_peer_by_id (op->peer_id)))
+  {
+    GNUNET_break (0);
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                "Starting preference generation for unknown peer %u\n",
+                op->peer_id);
+    return;
+  }
+
+  GNUNET_ATS_solver_generate_preferences_start (op->peer_id,
+                                                op->address_id,
+                                                op->client_id,
+                                                op->gen_type,
+                                                op->base_rate,
+                                                op->max_rate,
+                                                op->period,
+                                                op->frequency,
+                                                op->pref_type,
+                                                op->frequency);
+}
+
+
+static void
+enforce_stop_preference (struct GNUNET_ATS_TEST_Operation *op)
+{
+  struct PreferenceGenerator *pg = find_pref_gen (op->peer_id,
+                                                  op->pref_type);
+
+  if (NULL != pg)
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+                "Stopping property generation for peer %u address %u\n",
+                op->peer_id,
+                op->address_id);
+    GNUNET_ATS_solver_generate_preferences_stop (pg);
+  }
+  else
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                "Cannot find preference generator for peer %u address %u\n",
+                op->peer_id, op->address_id);
+    GNUNET_break (0);
+  }
+}
+
+
+static void
+enforce_start_request (struct GNUNET_ATS_TEST_Operation *op)
+{
+  struct TestPeer *p;
+
+  if (NULL == (p = find_peer_by_id (op->peer_id)))
+  {
+    GNUNET_break (0);
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                "Requesting address for unknown peer %u\n", op->peer_id);
+    return;
+  }
+
+  GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Requesting address for peer %u\n",
+              op->peer_id);
+  p->is_requested = GNUNET_YES;
+
+  sh->sf->s_get (sh->sf->cls, &p->peer_id);
+}
+
+
+static void
+enforce_stop_request (struct GNUNET_ATS_TEST_Operation *op)
+{
+  struct TestPeer *p;
+
+  if (NULL == (p = find_peer_by_id (op->peer_id)))
+  {
+    GNUNET_break (0);
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                "Requesting address for unknown peer %u\n", op->peer_id);
+    return;
+  }
+
+  GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+              "Stop requesting address for peer %u\n",
+              op->peer_id);
+  p->is_requested = GNUNET_NO;
+  p->assigned_bw_in = 0;
+  p->assigned_bw_out = 0;
+  sh->sf->s_get_stop (sh->sf->cls, &p->peer_id);
+
+  if (NULL != l)
+  {
+    GNUNET_ATS_solver_logging_now (l);
+  }
+}
+
+
+static void
+enforce_episode (struct Episode *ep)
+{
+  struct GNUNET_ATS_TEST_Operation *cur;
+
+  for (cur = ep->head; NULL != cur; cur = cur->next)
+  {
+    switch (cur->type)
+    {
+    case SOLVER_OP_ADD_ADDRESS:
+      fprintf (stderr, "Enforcing operation: %s [%llu:%llu]\n",
+               print_op (cur->type), cur->peer_id, cur->address_id);
+      enforce_add_address (cur);
+      break;
+
+    case SOLVER_OP_DEL_ADDRESS:
+      fprintf (stderr, "Enforcing operation: %s [%llu:%llu]\n",
+               print_op (cur->type), cur->peer_id, cur->address_id);
+      enforce_del_address (cur);
+      break;
+
+    case SOLVER_OP_START_SET_PROPERTY:
+      fprintf (stderr, "Enforcing operation: %s [%llu:%llu] == %llu\n",
+               print_op (cur->type), cur->peer_id, cur->address_id,
+               cur->base_rate);
+      enforce_start_property (cur);
+      break;
+
+    case SOLVER_OP_STOP_SET_PROPERTY:
+      fprintf (stderr, "Enforcing operation: %s [%llu:%llu] == %llu\n",
+               print_op (cur->type), cur->peer_id, cur->address_id,
+               cur->base_rate);
+      enforce_stop_property (cur);
+      break;
+
+    case SOLVER_OP_START_SET_PREFERENCE:
+      fprintf (stderr, "Enforcing operation: %s [%llu:%llu] == %llu\n",
+               print_op (cur->type), cur->peer_id, cur->address_id,
+               cur->base_rate);
+      enforce_start_preference (cur);
+      break;
+
+    case SOLVER_OP_STOP_SET_PREFERENCE:
+      fprintf (stderr, "Enforcing operation: %s [%llu:%llu] == %llu\n",
+               print_op (cur->type), cur->peer_id, cur->address_id,
+               cur->base_rate);
+      enforce_stop_preference (cur);
+      break;
+
+    case SOLVER_OP_START_REQUEST:
+      fprintf (stderr, "Enforcing operation: %s [%llu]\n",
+               print_op (cur->type), cur->peer_id);
+      enforce_start_request (cur);
+      break;
+
+    case SOLVER_OP_STOP_REQUEST:
+      fprintf (stderr, "Enforcing operation: %s [%llu]\n",
+               print_op (cur->type), cur->peer_id);
+      enforce_stop_request (cur);
+      break;
+
+    default:
+      break;
+    }
+  }
+}
+
+
+static void
+timeout_episode (void *cls)
+{
+  struct Experiment *e = cls;
+
+  e->episode_timeout_task = NULL;
+  if (NULL != e->ep_done_cb)
+    e->ep_done_cb (e->cur);
+
+  /* Scheduling next */
+  e->cur = e->cur->next;
+  if (NULL == e->cur)
+  {
+    /* done */
+    fprintf (stderr, "Last episode done!\n");
+    if (NULL != e->experiment_timeout_task)
+    {
+      GNUNET_SCHEDULER_cancel (e->experiment_timeout_task);
+      e->experiment_timeout_task = NULL;
+    }
+    e->e_done_cb (e, GNUNET_TIME_absolute_get_duration (e->start_time),
+                  GNUNET_OK);
+    return;
+  }
+
+  fprintf (stderr, "Running episode %u with timeout %s\n",
+           e->cur->id,
+           GNUNET_STRINGS_relative_time_to_string (e->cur->duration,
+                                                   GNUNET_YES));
+  e->episode_timeout_task = GNUNET_SCHEDULER_add_delayed (e->cur->duration,
+                                                          &timeout_episode, e);
+  enforce_episode (e->cur);
+}
+
+
+void
+GNUNET_ATS_solvers_experimentation_run (struct Experiment *e,
+                                        GNUNET_ATS_TESTING_EpisodeDoneCallback
+                                        ep_done_cb,
+                                        GNUNET_ATS_TESTING_ExperimentDoneCallback
+                                        e_done_cb)
+{
+  fprintf (stderr, "Running experiment `%s'  with timeout %s\n", e->name,
+           GNUNET_STRINGS_relative_time_to_string (e->max_duration,
+                                                   GNUNET_YES));
+  e->e_done_cb = e_done_cb;
+  e->ep_done_cb = ep_done_cb;
+  e->start_time = GNUNET_TIME_absolute_get ();
+
+  /* Start total time out */
+  e->experiment_timeout_task = GNUNET_SCHEDULER_add_delayed (e->max_duration,
+                                                             &timeout_experiment,
+                                                             e);
+
+  /* Start */
+  if (NULL == e->start)
+  {
+    GNUNET_break (0);
+    return;
+  }
+
+  e->cur = e->start;
+  fprintf (stderr, "Running episode %u with timeout %s\n",
+           e->cur->id,
+           GNUNET_STRINGS_relative_time_to_string (e->cur->duration,
+                                                   GNUNET_YES));
+  e->episode_timeout_task = GNUNET_SCHEDULER_add_delayed (e->cur->duration,
+                                                          &timeout_episode, e);
+  enforce_episode (e->cur);
+}
+
+
+void
+GNUNET_ATS_solvers_experimentation_stop (struct Experiment *e)
+{
+  if (NULL != e->experiment_timeout_task)
+  {
+    GNUNET_SCHEDULER_cancel (e->experiment_timeout_task);
+    e->experiment_timeout_task = NULL;
+  }
+  if (NULL != e->episode_timeout_task)
+  {
+    GNUNET_SCHEDULER_cancel (e->episode_timeout_task);
+    e->episode_timeout_task = NULL;
+  }
+  if (NULL != e->cfg)
+  {
+    GNUNET_CONFIGURATION_destroy (e->cfg);
+    e->cfg = NULL;
+  }
+  free_experiment (e);
+}
+
+
+struct Experiment *
+GNUNET_ATS_solvers_experimentation_load (char *filename)
+{
+  struct Experiment *e;
+  struct GNUNET_CONFIGURATION_Handle *cfg;
+
+  e = NULL;
+
+  cfg = GNUNET_CONFIGURATION_create ();
+  if (GNUNET_SYSERR == GNUNET_CONFIGURATION_load (cfg, filename))
+  {
+    fprintf (stderr, "Failed to load `%s'\n", filename);
+    GNUNET_CONFIGURATION_destroy (cfg);
+    return NULL;
+  }
+
+  e = create_experiment ();
+
+  if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_string (cfg, "experiment",
+                                                              "name", &e->name))
+  {
+    fprintf (stderr, "Invalid %s \n", "name");
+    free_experiment (e);
+    return NULL;
+  }
+  else
+    GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Experiment name: `%s'\n", e->name);
+
+  if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_string (cfg, "experiment",
+                                                              "log_prefix",
+                                                              &e->log_prefix))
+  {
+    fprintf (stderr, "Invalid %s \n", "log_prefix");
+    free_experiment (e);
+    return NULL;
+  }
+  else
+    GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Experiment logging prefix: `%s'\n",
+                e->log_prefix);
+
+  if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_filename (cfg,
+                                                                "experiment",
+                                                                "log_output_dir",
+                                                                &e->
+                                                                log_output_dir))
+  {
+    e->log_output_dir = NULL;
+  }
+  else
+    GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+                "Experiment logging output directory: `%s'\n",
+                e->log_output_dir);
+
+
+  if (GNUNET_SYSERR == (e->log_append_time_stamp =
+                          GNUNET_CONFIGURATION_get_value_yesno (cfg,
+                                                                "experiment",
+                                                                "log_append_time_stamp")))
+    e->log_append_time_stamp = GNUNET_YES;
+  GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+              "Experiment logging append timestamp: `%s'\n",
+              (GNUNET_YES == e->log_append_time_stamp) ? "yes" : "no");
+
+
+  if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_filename (cfg,
+                                                                "experiment",
+                                                                "cfg_file",
+                                                                &e->cfg_file))
+  {
+    fprintf (stderr, "Invalid %s \n", "cfg_file");
+    free_experiment (e);
+    return NULL;
+  }
+  else
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Experiment configuration: `%s'\n",
+                e->cfg_file);
+    e->cfg = GNUNET_CONFIGURATION_create ();
+    if (GNUNET_SYSERR == GNUNET_CONFIGURATION_load (e->cfg, e->cfg_file))
+    {
+      fprintf (stderr, "Invalid configuration %s \n", "cfg_file");
+      free_experiment (e);
+      return NULL;
+    }
+  }
+
+  if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_time (cfg, "experiment",
+                                                            "log_freq",
+                                                            &e->log_freq))
+  {
+    fprintf (stderr, "Invalid %s \n", "log_freq");
+    free_experiment (e);
+    return NULL;
+  }
+  else
+    GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Experiment logging frequency: `%s'\n",
+                GNUNET_STRINGS_relative_time_to_string (e->log_freq,
+                                                        GNUNET_YES));
+
+  if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_time (cfg, "experiment",
+                                                            "max_duration",
+                                                            &e->max_duration))
+  {
+    fprintf (stderr, "Invalid %s", "max_duration");
+    free_experiment (e);
+    return NULL;
+  }
+  else
+    GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Experiment duration: `%s'\n",
+                GNUNET_STRINGS_relative_time_to_string (e->max_duration,
+                                                        GNUNET_YES));
+
+  if (GNUNET_SYSERR == load_episodes (e, cfg))
+  {
+    GNUNET_ATS_solvers_experimentation_stop (e);
+    GNUNET_CONFIGURATION_destroy (cfg);
+    e = NULL;
+    fprintf (stderr, "Failed to load experiment\n");
+    return NULL;
+  }
+  GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+              "Loaded %u episodes with total duration %s\n",
+              e->num_episodes,
+              GNUNET_STRINGS_relative_time_to_string (e->total_duration,
+                                                      GNUNET_YES));
+
+  GNUNET_CONFIGURATION_destroy (cfg);
+  return e;
+}
+
+
+/**
+ * Solver
+ */
+
+static int
+free_all_it (void *cls,
+             const struct GNUNET_PeerIdentity *key,
+             void *value)
+{
+  struct ATS_Address *address = value;
+
+  GNUNET_break (GNUNET_OK == GNUNET_CONTAINER_multipeermap_remove (
+                  sh->env.addresses,
+                  key, value));
+  GNUNET_free (address);
+
+  return GNUNET_OK;
+}
+
+
+void
+GNUNET_ATS_solvers_solver_stop (struct SolverHandle *sh)
+{
+  GNUNET_STATISTICS_destroy ((struct GNUNET_STATISTICS_Handle *) sh->env.stats,
+                             GNUNET_NO);
+  GNUNET_PLUGIN_unload (sh->plugin, sh->sf);
+  sh->sf = NULL;
+  GAS_normalization_stop ();
+
+  GNUNET_CONTAINER_multipeermap_iterate (sh->addresses,
+                                         &free_all_it,
+                                         NULL);
+  GNUNET_CONTAINER_multipeermap_destroy (sh->addresses);
+  GNUNET_free (sh->plugin);
+  GNUNET_free (sh);
+}
+
+
+/**
+ * Load quotas for networks from configuration
+ *
+ * @param cfg configuration handle
+ * @param out_dest where to write outbound quotas
+ * @param in_dest where to write inbound quotas
+ * @param dest_length length of inbound and outbound arrays
+ * @return number of networks loaded
+ */
+unsigned int
+GNUNET_ATS_solvers_load_quotas (const struct GNUNET_CONFIGURATION_Handle *cfg,
+                                unsigned long long *out_dest,
+                                unsigned long long *in_dest,
+                                int dest_length)
+{
+  char *entry_in = NULL;
+  char *entry_out = NULL;
+  char *quota_out_str;
+  char *quota_in_str;
+  int c;
+  int res;
+
+  for (c = 0; (c < GNUNET_NT_COUNT) && (c < dest_length); c++)
+  {
+    in_dest[c] = 0;
+    out_dest[c] = 0;
+    GNUNET_asprintf (&entry_out,
+                     "%s_QUOTA_OUT",
+                     GNUNET_NT_to_string (c));
+    GNUNET_asprintf (&entry_in,
+                     "%s_QUOTA_IN",
+                     GNUNET_NT_to_string (c));
+
+    /* quota out */
+    if (GNUNET_OK == GNUNET_CONFIGURATION_get_value_string (cfg, "ats",
+                                                            entry_out,
+                                                            &quota_out_str))
+    {
+      res = GNUNET_NO;
+      if (0 == strcmp (quota_out_str, BIG_M_STRING))
+      {
+        out_dest[c] = GNUNET_ATS_MaxBandwidth;
+        res = GNUNET_YES;
+      }
+      if ((GNUNET_NO == res) && (GNUNET_OK ==
+                                 GNUNET_STRINGS_fancy_size_to_bytes (
+                                   quota_out_str, &out_dest[c])))
+        res = GNUNET_YES;
+      if ((GNUNET_NO == res) && (GNUNET_OK ==
+                                 GNUNET_CONFIGURATION_get_value_number (cfg,
+                                                                        "ats",
+                                                                        entry_out,
+                                                                        &
+                                                                        out_dest
+                                                                        [c])))
+        res = GNUNET_YES;
+
+      if (GNUNET_NO == res)
+      {
+        GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                    _ (
+                      "Could not load quota for network `%s':  `%s', assigning default bandwidth %llu\n"),
+                    GNUNET_NT_to_string (c),
+                    quota_out_str,
+                    GNUNET_ATS_DefaultBandwidth);
+        out_dest[c] = GNUNET_ATS_DefaultBandwidth;
+      }
+      else
+      {
+        GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                    "Outbound quota configure for network `%s' is %llu\n",
+                    GNUNET_NT_to_string (c),
+                    out_dest[c]);
+      }
+      GNUNET_free (quota_out_str);
+    }
+    else
+    {
+      GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+                  _ (
+                    "No outbound quota configured for network `%s', assigning default bandwidth %llu\n"),
+                  GNUNET_NT_to_string (c),
+                  GNUNET_ATS_DefaultBandwidth);
+      out_dest[c] = GNUNET_ATS_DefaultBandwidth;
+    }
+
+    /* quota in */
+    if (GNUNET_OK == GNUNET_CONFIGURATION_get_value_string (cfg, "ats",
+                                                            entry_in,
+                                                            &quota_in_str))
+    {
+      res = GNUNET_NO;
+      if (0 == strcmp (quota_in_str, BIG_M_STRING))
+      {
+        in_dest[c] = GNUNET_ATS_MaxBandwidth;
+        res = GNUNET_YES;
+      }
+      if ((GNUNET_NO == res) && (GNUNET_OK ==
+                                 GNUNET_STRINGS_fancy_size_to_bytes (
+                                   quota_in_str, &in_dest[c])))
+        res = GNUNET_YES;
+      if ((GNUNET_NO == res) && (GNUNET_OK ==
+                                 GNUNET_CONFIGURATION_get_value_number (cfg,
+                                                                        "ats",
+                                                                        entry_in,
+                                                                        &in_dest
+                                                                        [c])))
+        res = GNUNET_YES;
+
+      if (GNUNET_NO == res)
+      {
+        GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                    _ (
+                      "Could not load quota for network `%s':  `%s', assigning default bandwidth %llu\n"),
+                    GNUNET_NT_to_string (c),
+                    quota_in_str,
+                    GNUNET_ATS_DefaultBandwidth);
+        in_dest[c] = GNUNET_ATS_DefaultBandwidth;
+      }
+      else
+      {
+        GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                    "Inbound quota configured for network `%s' is %llu\n",
+                    GNUNET_NT_to_string (c),
+                    in_dest[c]);
+      }
+      GNUNET_free (quota_in_str);
+    }
+    else
+    {
+      GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+                  _ (
+                    "No outbound quota configure for network `%s', assigning default bandwidth %llu\n"),
+                  GNUNET_NT_to_string (c),
+                  GNUNET_ATS_DefaultBandwidth);
+      out_dest[c] = GNUNET_ATS_DefaultBandwidth;
+    }
+    GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+                "Loaded quota for network `%s' (in/out): %llu %llu\n",
+                GNUNET_NT_to_string (c),
+                in_dest[c],
+                out_dest[c]);
+    GNUNET_free (entry_out);
+    GNUNET_free (entry_in);
+  }
+  return GNUNET_NT_COUNT;
+}
+
+
+/**
+ * Information callback for the solver
+ *
+ * @param cls the closure
+ * @param op the solver operation
+ * @param stat status of the solver operation
+ * @param add additional solver information
+ */
+static void
+solver_info_cb (void *cls,
+                enum GAS_Solver_Operation op,
+                enum GAS_Solver_Status stat,
+                enum GAS_Solver_Additional_Information add)
+{
+  char *add_info;
+
+  switch (add)
+  {
+  case GAS_INFO_NONE:
+    add_info = "GAS_INFO_NONE";
+    break;
+
+  case GAS_INFO_FULL:
+    add_info = "GAS_INFO_MLP_FULL";
+    break;
+
+  case GAS_INFO_UPDATED:
+    add_info = "GAS_INFO_MLP_UPDATED";
+    break;
+
+  case GAS_INFO_PROP_ALL:
+    add_info = "GAS_INFO_PROP_ALL";
+    break;
+
+  case GAS_INFO_PROP_SINGLE:
+    add_info = "GAS_INFO_PROP_SINGLE";
+    break;
+
+  default:
+    add_info = "INVALID";
+    break;
+  }
+
+  switch (op)
+  {
+  case GAS_OP_SOLVE_START:
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                "Solver notifies `%s' with result `%s' `%s'\n",
+                "GAS_OP_SOLVE_START",
+                (GAS_STAT_SUCCESS == stat) ? "SUCCESS" : "FAIL", add_info);
+    return;
+
+  case GAS_OP_SOLVE_STOP:
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                "Solver notifies `%s' with result `%s'\n", "GAS_OP_SOLVE_STOP",
+                (GAS_STAT_SUCCESS == stat) ? "SUCCESS" : "FAIL", add_info);
+    return;
+
+  case GAS_OP_SOLVE_SETUP_START:
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                "Solver notifies `%s' with result `%s'\n",
+                "GAS_OP_SOLVE_SETUP_START",
+                (GAS_STAT_SUCCESS == stat) ? "SUCCESS" : "FAIL");
+    return;
+
+  case GAS_OP_SOLVE_SETUP_STOP:
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                "Solver notifies `%s' with result `%s'\n",
+                "GAS_OP_SOLVE_SETUP_STOP",
+                (GAS_STAT_SUCCESS == stat) ? "SUCCESS" : "FAIL");
+    return;
+
+  case GAS_OP_SOLVE_MLP_LP_START:
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                "Solver notifies `%s' with result `%s'\n",
+                "GAS_OP_SOLVE_LP_START",
+                (GAS_STAT_SUCCESS == stat) ? "SUCCESS" : "FAIL");
+    return;
+
+  case GAS_OP_SOLVE_MLP_LP_STOP:
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                "Solver notifies `%s' with result `%s'\n",
+                "GAS_OP_SOLVE_LP_STOP",
+                (GAS_STAT_SUCCESS == stat) ? "SUCCESS" : "FAIL");
+    return;
+
+  case GAS_OP_SOLVE_MLP_MLP_START:
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                "Solver notifies `%s' with result `%s'\n",
+                "GAS_OP_SOLVE_MLP_START",
+                (GAS_STAT_SUCCESS == stat) ? "SUCCESS" : "FAIL");
+    return;
+
+  case GAS_OP_SOLVE_MLP_MLP_STOP:
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                "Solver notifies `%s' with result `%s'\n",
+                "GAS_OP_SOLVE_MLP_STOP",
+                (GAS_STAT_SUCCESS == stat) ? "SUCCESS" : "FAIL");
+    return;
+
+  case GAS_OP_SOLVE_UPDATE_NOTIFICATION_START:
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                "Solver notifies `%s' with result `%s'\n",
+                "GAS_OP_SOLVE_UPDATE_NOTIFICATION_START",
+                (GAS_STAT_SUCCESS == stat) ? "SUCCESS" : "FAIL");
+    return;
+
+  case GAS_OP_SOLVE_UPDATE_NOTIFICATION_STOP:
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                "Solver notifies `%s' with result `%s'\n",
+                "GAS_OP_SOLVE_UPDATE_NOTIFICATION_STOP",
+                (GAS_STAT_SUCCESS == stat) ? "SUCCESS" : "FAIL");
+    return;
+
+  default:
+    break;
+  }
+}
+
+
+static void
+solver_bandwidth_changed_cb (void *cls, struct ATS_Address *address)
+{
+  struct GNUNET_TIME_Relative duration;
+  struct TestPeer *p;
+  static struct PreferenceGenerator *pg;
+  uint32_t delta;
+
+  if ((0 == address->assigned_bw_out) && (0 == address->assigned_bw_in))
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+                "Solver notified to disconnect peer `%s'\n",
+                GNUNET_i2s (&address->peer));
+  }
+  p = find_peer_by_pid (&address->peer);
+  if (NULL == p)
+    return;
+  p->assigned_bw_out = address->assigned_bw_out;
+  p->assigned_bw_in = address->assigned_bw_in;
+
+  for (pg = pref_gen_head; NULL != pg; pg = pg->next)
+  {
+    if (pg->peer == p->id)
+    {
+      duration = GNUNET_TIME_absolute_get_duration (
+        pg->feedback_last_bw_update);
+      delta = duration.rel_value_us * pg->last_assigned_bw_out;
+      pg->feedback_bw_out_acc += delta;
+
+      delta = duration.rel_value_us * pg->last_assigned_bw_in;
+      pg->feedback_bw_in_acc += delta;
+
+      pg->last_assigned_bw_in = address->assigned_bw_in;
+      pg->last_assigned_bw_out = address->assigned_bw_out;
+      pg->feedback_last_bw_update = GNUNET_TIME_absolute_get ();
+    }
+  }
+
+  GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+              "Bandwidth changed addresses %s %p to %u Bps out / %u Bps in\n",
+              GNUNET_i2s (&address->peer),
+              address,
+              address->assigned_bw_out,
+              address->assigned_bw_in);
+
+  if (NULL != l)
+    GNUNET_ATS_solver_logging_now (l);
+
+  return;
+}
+
+
+const double *
+get_preferences_cb (void *cls, const struct GNUNET_PeerIdentity *id)
+{
+  struct TestPeer *p;
+
+  if (GNUNET_YES == opt_disable_normalization)
+  {
+    if (NULL == (p = find_peer_by_pid (id)))
+      return NULL;
+    return p->pref_abs;
+  }
+  else
+    return GAS_preference_get_by_peer (NULL,
+                                       id);
+}
+
+
+struct SolverHandle *
+GNUNET_ATS_solvers_solver_start (enum GNUNET_ATS_Solvers type)
+{
+  struct SolverHandle *sh;
+  char *solver_str;
+
+  switch (type)
+  {
+  case GNUNET_ATS_SOLVER_PROPORTIONAL:
+    solver_str = "proportional";
+    break;
+
+  case GNUNET_ATS_SOLVER_MLP:
+    solver_str = "mlp";
+    break;
+
+  case GNUNET_ATS_SOLVER_RIL:
+    solver_str = "ril";
+    break;
+
+  default:
+    GNUNET_break (0);
+    return NULL;
+    break;
+  }
+
+  sh = GNUNET_new (struct SolverHandle);
+  GNUNET_asprintf (&sh->plugin,
+                   "libgnunet_plugin_ats_%s",
+                   solver_str);
+  sh->addresses = GNUNET_CONTAINER_multipeermap_create (128, GNUNET_NO);
+
+  /* setup environment */
+  sh->env.cfg = e->cfg;
+  sh->env.stats = GNUNET_STATISTICS_create ("ats", e->cfg);
+  sh->env.addresses = sh->addresses;
+  sh->env.bandwidth_changed_cb = &solver_bandwidth_changed_cb;
+  sh->env.get_preferences = &get_preferences_cb;
+  sh->env.network_count = GNUNET_NT_COUNT;
+  sh->env.info_cb = &solver_info_cb;
+  sh->env.network_count = GNUNET_NT_COUNT;
+
+  /* start normalization */
+  GAS_normalization_start ();
+
+  /* load quotas */
+  if (GNUNET_NT_COUNT != GNUNET_ATS_solvers_load_quotas (e->cfg,
+                                                         sh->env.out_quota,
+                                                         sh->env.in_quota,
+                                                         GNUNET_NT_COUNT))
+  {
+    GNUNET_break (0);
+    GNUNET_free (sh->plugin);
+    GNUNET_free (sh);
+    end_now ();
+    return NULL;
+  }
+
+  sh->sf = GNUNET_PLUGIN_load (sh->plugin, &sh->env);
+  if (NULL == sh->sf)
+  {
+    fprintf (stderr, "Failed to load solver `%s'\n", sh->plugin);
+    GNUNET_break (0);
+    GNUNET_free (sh->plugin);
+    GNUNET_free (sh);
+    end_now ();
+    return NULL;
+  }
+  return sh;
+}
+
+
+static void
+done ()
+{
+  struct TestPeer *cur;
+  struct TestPeer *next;
+
+  struct TestAddress *cur_a;
+  struct TestAddress *next_a;
+
+  /* Stop logging */
+  GNUNET_ATS_solver_logging_stop (l);
+
+  /* Stop all preference generation */
+  GNUNET_ATS_solver_generate_preferences_stop_all ();
+
+  /* Stop all property generation */
+  GNUNET_ATS_solver_generate_property_stop_all ();
+
+  if (opt_print)
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_INFO, "== Printing log information \n");
+    GNUNET_ATS_solver_logging_eval (l);
+  }
+  if (opt_save)
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_INFO, "== Saving log information \n");
+    GNUNET_ATS_solver_logging_write_to_disk (l, e->log_append_time_stamp,
+                                             e->log_output_dir);
+  }
+
+  if (NULL != l)
+  {
+    GNUNET_ATS_solver_logging_free (l);
+    l = NULL;
+  }
+
+  /* Clean up experiment */
+  if (NULL != e)
+  {
+    GNUNET_ATS_solvers_experimentation_stop (e);
+    e = NULL;
+  }
+
+  next = peer_head;
+  while (NULL != (cur = next))
+  {
+    next = cur->next;
+    GNUNET_CONTAINER_DLL_remove (peer_head, peer_tail, cur);
+    next_a = cur->addr_head;
+    while (NULL != (cur_a = next_a))
+    {
+      next_a = cur_a->next;
+      GNUNET_CONTAINER_DLL_remove (cur->addr_head, cur->addr_tail, cur_a);
+      GNUNET_free (cur_a);
+    }
+    GNUNET_free (cur);
+  }
+  if (NULL != sh)
+  {
+    GNUNET_ATS_solvers_solver_stop (sh);
+    sh = NULL;
+  }
+
+  /* Shutdown */
+  end_now ();
+}
+
+
+static void
+experiment_done_cb (struct Experiment *e, struct GNUNET_TIME_Relative duration,
+                    int success)
+{
+  if (GNUNET_OK == success)
+    GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Experiment done successful in %s\n",
+                GNUNET_STRINGS_relative_time_to_string (duration, GNUNET_YES));
+  else
+    GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Experiment failed \n");
+
+  GNUNET_SCHEDULER_add_now (&done, NULL);
+}
+
+
+static void
+episode_done_cb (struct Episode *ep)
+{
+  GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Episode %u done\n", ep->id);
+}
+
+
+/**
+ * Do shutdown
+ */
+static void
+end_now ()
+{
+  if (NULL != e)
+  {
+    GNUNET_ATS_solvers_experimentation_stop (e);
+    e = NULL;
+  }
+  if (NULL != sh)
+  {
+    GNUNET_ATS_solvers_solver_stop (sh);
+    sh = NULL;
+  }
+}
+
+
+static void
+run (void *cls, char *const *args, const char *cfgfile,
+     const struct GNUNET_CONFIGURATION_Handle *cfg)
+{
+  enum GNUNET_ATS_Solvers solver;
+  int c;
+
+  if (NULL == opt_exp_file)
+  {
+    fprintf (stderr, "No experiment given ...\n");
+    res = 1;
+    end_now ();
+    return;
+  }
+
+  if (NULL == opt_solver)
+  {
+    fprintf (stderr, "No solver given ...\n");
+    res = 1;
+    end_now ();
+    return;
+  }
+
+  if (0 == strcmp (opt_solver, "mlp"))
+  {
+    solver = GNUNET_ATS_SOLVER_MLP;
+  }
+  else if (0 == strcmp (opt_solver, "proportional"))
+  {
+    solver = GNUNET_ATS_SOLVER_PROPORTIONAL;
+  }
+  else if (0 == strcmp (opt_solver, "ril"))
+  {
+    solver = GNUNET_ATS_SOLVER_RIL;
+  }
+  else
+  {
+    fprintf (stderr, "No solver given ...");
+    res = 1;
+    end_now ();
+    return;
+  }
+
+  for (c = 0; c < GNUNET_ATS_PropertyCount; c++)
+    default_properties[c] = DEFAULT_REL_QUALITY;
+
+  for (c = 0; c < GNUNET_ATS_PreferenceCount; c++)
+    default_preferences[c] = DEFAULT_REL_PREFERENCE;
+
+  /* load experiment */
+  GNUNET_log (GNUNET_ERROR_TYPE_INFO, "=== Loading experiment\n");
+  e = GNUNET_ATS_solvers_experimentation_load (opt_exp_file);
+  if (NULL == e)
+  {
+    fprintf (stderr, "Failed to load experiment ...\n");
+    res = 1;
+    end_now ();
+    return;
+  }
+
+  /* load solver */
+  GNUNET_log (GNUNET_ERROR_TYPE_INFO, "=== Loading solver\n");
+  sh = GNUNET_ATS_solvers_solver_start (solver);
+  if (NULL == sh)
+  {
+    fprintf (stderr, "Failed to start solver ...\n");
+    end_now ();
+    res = 1;
+    return;
+  }
+
+  /* start logging */
+  GNUNET_log (GNUNET_ERROR_TYPE_INFO, "=== Start logging \n");
+  l = GNUNET_ATS_solver_logging_start (e->log_freq);
+
+  /* run experiment */
+  GNUNET_log (GNUNET_ERROR_TYPE_INFO, "=== Running experiment \n");
+  GNUNET_ATS_solvers_experimentation_run (e, episode_done_cb,
+                                          experiment_done_cb);
+
+  /* WAIT */
+}
+
+
+/**
+ * Main function of the benchmark
+ *
+ * @param argc argument count
+ * @param argv argument values
+ */
+int
+main (int argc, char *argv[])
+{
+  opt_exp_file = NULL;
+  opt_solver = NULL;
+  opt_log = GNUNET_NO;
+  opt_save = GNUNET_NO;
+
+  res = 0;
+
+  static struct GNUNET_GETOPT_CommandLineOption options[] = {
+    GNUNET_GETOPT_option_string ('s',
+                                 "solver",
+                                 gettext_noop ("solver to use"),
+                                 &opt_solver),
+
+    GNUNET_GETOPT_option_string ('e',
+                                 "experiment"
+                                 gettext_noop ("experiment to use"),
+                                 &opt_exp_file),
+
+    GNUNET_GETOPT_option_verbose (&opt_verbose),
+
+    GNUNET_GETOPT_option_flag ('p',
+                               "print",
+                               gettext_noop ("print logging"),
+                               &opt_print),
+
+    GNUNET_GETOPT_option_flag ('f',
+                               "file",
+                               gettext_noop ("save logging to disk"),
+                               &opt_save),
+
+    GNUNET_GETOPT_option_flag ('d',
+                               "dn",
+                               gettext_noop ("disable normalization"),
+                               &opt_disable_normalization),
+
+    GNUNET_GETOPT_OPTION_END
+  };
+
+  GNUNET_PROGRAM_run (argc, argv, "gnunet-ats-solver-eval",
+                      NULL, options, &run, argv[0]);
+
+  return res;
+}
+
+
+/* end of file ats-testing-experiment.c*/
diff --git a/src/ats/gnunet-ats-solver-eval.h b/src/ats/gnunet-ats-solver-eval.h
new file mode 100644
index 0000000000000000000000000000000000000000..7d14bf761ec6529c93483819bf58393e2a3645f3
--- /dev/null
+++ b/src/ats/gnunet-ats-solver-eval.h
@@ -0,0 +1,335 @@
+/*
+   This file is part of GNUnet.
+   Copyright (C) 2010-2013 GNUnet e.V.
+
+   GNUnet is free software: you can redistribute it and/or modify it
+   under the terms of the GNU Affero General Public License as published
+   by the Free Software Foundation, either version 3 of the License,
+   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
+   Affero General Public License for more details.
+
+   You should have received a copy of the GNU Affero General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+     SPDX-License-Identifier: AGPL3.0-or-later
+ */
+/**
+ * @file ats-tests/ats-testing-experiment.c
+ * @brief ats benchmark: controlled experiment execution
+ * @author Christian Grothoff
+ * @author Matthias Wachs
+ */
+#ifndef GNUNET_ATS_SOLVER_EVAL_H
+#define GNUNET_ATS_SOLVER_EVAL_H
+
+#include "platform.h"
+#include "gnunet_util_lib.h"
+#include "gnunet_ats_plugin.h"
+#include "gnunet_ats_service.h"
+#include "gnunet-service-ats_addresses.h"
+#include "gnunet-service-ats_normalization.h"
+#include "test_ats_api_common.h"
+
+enum GeneratorType
+{
+  GNUNET_ATS_TEST_TG_LINEAR,
+  GNUNET_ATS_TEST_TG_CONSTANT,
+  GNUNET_ATS_TEST_TG_RANDOM,
+  GNUNET_ATS_TEST_TG_SINUS
+};
+
+
+enum OperationType
+{
+  SOLVER_OP_ADD_ADDRESS,
+  SOLVER_OP_DEL_ADDRESS,
+  SOLVER_OP_START_SET_PROPERTY,
+  SOLVER_OP_STOP_SET_PROPERTY,
+  SOLVER_OP_START_SET_PREFERENCE,
+  SOLVER_OP_STOP_SET_PREFERENCE,
+  SOLVER_OP_START_REQUEST,
+  SOLVER_OP_STOP_REQUEST,
+};
+
+struct SolverHandle
+{
+  /**
+   * Solver plugin name
+   */
+  char *plugin;
+
+  /**
+   * Solver environment
+   */
+  struct GNUNET_ATS_PluginEnvironment env;
+
+  /**
+   * Solver handle
+   */
+  struct GNUNET_ATS_SolverFunctions *sf;
+
+  /**
+   * Address hashmap
+   */
+  struct GNUNET_CONTAINER_MultiPeerMap *addresses;
+};
+
+enum GNUNET_ATS_Solvers
+{
+  GNUNET_ATS_SOLVER_PROPORTIONAL,
+  GNUNET_ATS_SOLVER_MLP,
+  GNUNET_ATS_SOLVER_RIL,
+};
+
+struct LoggingFileHandle
+{
+  /* DLL list for logging time steps */
+  struct LoggingFileHandle *next;
+  struct LoggingFileHandle *prev;
+
+  /* peer id */
+  long long unsigned int pid;
+
+  /* address id */
+  long long unsigned int aid;
+
+  struct GNUNET_DISK_FileHandle *f_hd;
+};
+
+struct LoggingTimeStep
+{
+  struct LoggingTimeStep *prev;
+  struct LoggingTimeStep *next;
+
+  struct LoggingPeer *head;
+  struct LoggingPeer *tail;
+
+  struct GNUNET_TIME_Absolute timestamp;
+  struct GNUNET_TIME_Relative delta;
+};
+
+struct LoggingPeer
+{
+  struct LoggingPeer *prev;
+  struct LoggingPeer *next;
+
+  long long unsigned int id;
+  struct GNUNET_PeerIdentity peer_id;
+  double pref_abs[GNUNET_ATS_PREFERENCE_END];
+  double pref_norm[GNUNET_ATS_PREFERENCE_END];
+  int is_requested;
+
+  struct LoggingAddress *addr_head;
+  struct LoggingAddress *addr_tail;
+};
+
+struct LoggingAddress
+{
+  struct LoggingAddress *next;
+  struct LoggingAddress *prev;
+
+  long long unsigned int aid;
+  int active;
+  uint32_t network;
+  uint32_t assigned_bw_in;
+  uint32_t assigned_bw_out;
+
+  double prop_abs[GNUNET_ATS_PropertyCount];
+  double prop_norm[GNUNET_ATS_PropertyCount];
+};
+
+
+struct TestPeer
+{
+  struct TestPeer *prev;
+  struct TestPeer *next;
+
+
+  long long unsigned int id;
+  int is_requested;
+  struct GNUNET_PeerIdentity peer_id;
+
+  double pref_abs[GNUNET_ATS_PreferenceCount];
+  double pref_norm[GNUNET_ATS_PreferenceCount];
+
+  uint32_t assigned_bw_in;
+  uint32_t assigned_bw_out;
+
+  struct TestAddress *addr_head;
+  struct TestAddress *addr_tail;
+};
+
+
+struct TestAddress
+{
+  struct TestAddress *next;
+  struct TestAddress *prev;
+
+  long long unsigned int aid;
+  struct ATS_Address *ats_addr;
+  uint32_t network;
+
+  double prop_abs[GNUNET_ATS_PropertyCount];
+  double prop_norm[GNUNET_ATS_PropertyCount];
+};
+
+struct Episode;
+
+struct Experiment;
+
+typedef void (*GNUNET_ATS_TESTING_EpisodeDoneCallback) (
+  struct Episode *e);
+
+typedef void (*GNUNET_ATS_TESTING_ExperimentDoneCallback) (struct Experiment *e,
+                                                           struct
+                                                           GNUNET_TIME_Relative
+                                                           duration, int
+                                                           success);
+
+/**
+ * An operation in an experiment
+ */
+struct GNUNET_ATS_TEST_Operation
+{
+  struct GNUNET_ATS_TEST_Operation *next;
+  struct GNUNET_ATS_TEST_Operation *prev;
+
+  long long unsigned int address_id;
+  long long unsigned int peer_id;
+  long long unsigned int client_id;
+
+  long long unsigned int address_session;
+  unsigned int address_network;
+  char*address;
+  char*plugin;
+
+
+  long long unsigned int base_rate;
+  long long unsigned int max_rate;
+  struct GNUNET_TIME_Relative period;
+  struct GNUNET_TIME_Relative frequency;
+  struct GNUNET_TIME_Relative feedback_delay;
+
+  enum OperationType type;
+  enum GeneratorType gen_type;
+  enum GNUNET_ATS_PreferenceKind pref_type;
+  // enum GNUNET_ATS_Property prop_type;
+};
+
+struct Episode
+{
+  int id;
+  struct Episode *next;
+  struct GNUNET_TIME_Relative duration;
+
+  struct GNUNET_ATS_TEST_Operation *head;
+  struct GNUNET_ATS_TEST_Operation *tail;
+};
+
+struct LoggingHandle
+{
+  struct GNUNET_SCHEDULER_Task *logging_task;
+  struct GNUNET_TIME_Relative log_freq;
+
+  /* DLL list for logging time steps */
+  struct LoggingTimeStep *head;
+  struct LoggingTimeStep *tail;
+};
+
+struct Experiment
+{
+  char *name;
+  char *log_prefix;
+  char *cfg_file;
+  char *log_output_dir;
+  int log_append_time_stamp;
+
+  struct GNUNET_TIME_Relative log_freq;
+  struct GNUNET_TIME_Relative max_duration;
+  struct GNUNET_TIME_Relative total_duration;
+  struct GNUNET_TIME_Absolute start_time;
+  unsigned int num_episodes;
+  struct Episode *start;
+
+  struct GNUNET_CONFIGURATION_Handle *cfg;
+
+  struct GNUNET_SCHEDULER_Task *experiment_timeout_task;
+  struct GNUNET_SCHEDULER_Task *episode_timeout_task;
+  struct Episode *cur;
+
+  GNUNET_ATS_TESTING_EpisodeDoneCallback ep_done_cb;
+  GNUNET_ATS_TESTING_ExperimentDoneCallback e_done_cb;
+};
+
+struct PreferenceGenerator
+{
+  struct PreferenceGenerator *prev;
+  struct PreferenceGenerator *next;
+
+  enum GeneratorType type;
+
+  long long unsigned int peer;
+  unsigned int client_id;
+
+  enum GNUNET_ATS_PreferenceKind kind;
+
+  long int base_value;
+  long int max_value;
+  struct GNUNET_TIME_Relative duration_period;
+  struct GNUNET_TIME_Relative frequency;
+  struct GNUNET_TIME_Relative feedback_frequency;
+
+  struct GNUNET_SCHEDULER_Task *set_task;
+  struct GNUNET_SCHEDULER_Task *feedback_task;
+  struct GNUNET_TIME_Absolute next_ping_transmission;
+  struct GNUNET_TIME_Absolute time_start;
+
+
+  /* Feedback */
+  uint32_t feedback_bw_out_acc;
+  uint32_t feedback_bw_in_acc;
+  uint32_t feedback_delay_acc;
+
+  double pref_bw_old;
+  double pref_latency_old;
+
+  struct GNUNET_TIME_Absolute feedback_last;
+
+  struct GNUNET_TIME_Absolute feedback_last_bw_update;
+  struct GNUNET_TIME_Absolute feedback_last_delay_update;
+  uint32_t last_assigned_bw_in;
+  uint32_t last_assigned_bw_out;
+  double last_delay_value;
+};
+
+
+struct PropertyGenerator
+{
+  struct PropertyGenerator *prev;
+  struct PropertyGenerator *next;
+
+  enum GeneratorType type;
+
+  long long unsigned int peer;
+  long long unsigned int address_id;
+
+  struct TestPeer *test_peer;
+  struct TestAddress *test_address;
+  uint32_t ats_property;
+
+  long int base_value;
+  long int max_value;
+  struct GNUNET_TIME_Relative duration_period;
+  struct GNUNET_TIME_Relative frequency;
+
+  struct GNUNET_SCHEDULER_Task *set_task;
+  struct GNUNET_TIME_Absolute next_ping_transmission;
+  struct GNUNET_TIME_Absolute time_start;
+};
+
+#endif /* #ifndef GNUNET_ATS_SOLVER_EVAL_H */
+/* end of file ats-testing.h */
diff --git a/src/ats/gnunet-service-ats_addresses.c b/src/ats/gnunet-service-ats_addresses.c
index e8a95c65e53e6af04b0e2f3c00d9d3f38ed0a7f9..3cd831a39e9d9733d35cf51075fd6593fd9d4937 100644
--- a/src/ats/gnunet-service-ats_addresses.c
+++ b/src/ats/gnunet-service-ats_addresses.c
@@ -685,7 +685,7 @@ GAS_handle_request_address_list (struct GNUNET_SERVICE_Client *client,
   memset (&allzeros,
           '\0',
           sizeof(struct GNUNET_PeerIdentity));
-  if (0 == GNUNET_is_zero (&alrm->peer))
+  if (GNUNET_YES == GNUNET_is_zero (&alrm->peer))
   {
     /* Return addresses for all peers */
     GAS_addresses_get_peer_info (NULL,
diff --git a/src/ats/perf_ats_simplistic_bandwidth.conf b/src/ats/perf_ats_simplistic_bandwidth.conf
new file mode 100644
index 0000000000000000000000000000000000000000..cec5b36f59d058af6d202fc418e4bd38c5e90e9e
--- /dev/null
+++ b/src/ats/perf_ats_simplistic_bandwidth.conf
@@ -0,0 +1,27 @@
+[hostlist]
+SERVERS = 
+
+[transport-udp]
+BROADCAST = NO
+
+[peerinfo]
+USE_INCLUDED_HELLOS = NO
+
+# Network specific inbound/outbound quotas
+UNSPECIFIED_QUOTA_IN = 128 KiB
+UNSPECIFIED_QUOTA_OUT = 128 KiB
+# LOOPBACK
+LOOPBACK_QUOTA_IN = 128 KiB
+LOOPBACK_QUOTA_OUT = 128 KiB
+# LAN
+LAN_QUOTA_IN = 128 KiB
+LAN_QUOTA_OUT = 128 KiB
+# WAN
+WAN_QUOTA_IN = 128 KiB
+WAN_QUOTA_OUT = 128 KiB
+# WLAN
+WLAN_QUOTA_IN = 128 KiB
+WLAN_QUOTA_OUT = 128 KiB
+# BLUETOOTH
+BLUETOOTH_QUOTA_IN = 128 KiB
+BLUETOOTH_QUOTA_OUT = 128 KiB
diff --git a/src/ats/perf_ats_simplistic_delay.conf b/src/ats/perf_ats_simplistic_delay.conf
new file mode 100644
index 0000000000000000000000000000000000000000..a5127d25fb58ed15396745e3ccccbec4cd334608
--- /dev/null
+++ b/src/ats/perf_ats_simplistic_delay.conf
@@ -0,0 +1,8 @@
+[hostlist]
+SERVERS = 
+
+[transport-udp]
+BROADCAST = NO
+
+[peerinfo]
+USE_INCLUDED_HELLOS = NO
diff --git a/src/ats/perf_ats_solver.c b/src/ats/perf_ats_solver.c
new file mode 100644
index 0000000000000000000000000000000000000000..2fbadef4d96460c7ae8d6df4a1580f8ee000b16b
--- /dev/null
+++ b/src/ats/perf_ats_solver.c
@@ -0,0 +1,1510 @@
+/*
+   This file is part of GNUnet.
+   Copyright (C) 2010,2011 GNUnet e.V.
+
+   GNUnet is free software: you can redistribute it and/or modify it
+   under the terms of the GNU Affero General Public License as published
+   by the Free Software Foundation, either version 3 of the License,
+   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
+   Affero General Public License for more details.
+
+   You should have received a copy of the GNU Affero General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+     SPDX-License-Identifier: AGPL3.0-or-later
+ */
+/**
+ * @file ats/perf_ats_solver.c
+ * @brief generic performance test for ATS solvers
+ * @author Christian Grothoff
+ * @author Matthias Wachs
+ */
+#include "platform.h"
+#include "gnunet_util_lib.h"
+#include "gnunet_statistics_service.h"
+#include "gnunet-service-ats_addresses.h"
+#include "gnunet-service-ats_plugins.h"
+#include "gnunet-service-ats_normalization.h"
+#include "gnunet-service-ats_preferences.h"
+#include "gnunet_ats_service.h"
+#include "gnunet_ats_plugin.h"
+#include "test_ats_api_common.h"
+
+#define DEFAULT_UPDATE_PERCENTAGE       20
+#define DEFAULT_PEERS_START     10
+#define DEFAULT_PEERS_END       10
+#define DEFAULT_ADDRESSES       10
+#define DEFAULT_ATS_COUNT       2
+
+
+/**
+ * Handle for statistics.
+ */
+struct GNUNET_STATISTICS_Handle *GSA_stats;
+
+/**
+ * Handle for ATS address component
+ */
+struct PerfHandle
+{
+  /**
+   * Performance peers
+   */
+  struct PerfPeer *peers;
+
+  /**
+   *  Solver handle
+   */
+  struct GNUNET_ATS_SolverFunctions *sf;
+
+  /**
+   * Statistics stat;
+   */
+  struct GNUNET_STATISTICS_Handle *stat;
+
+  /**
+   * A multihashmap to store all addresses
+   */
+  struct GNUNET_CONTAINER_MultiPeerMap *addresses;
+
+  /**
+   * Solver functions
+   * */
+  struct GNUNET_ATS_PluginEnvironment env;
+
+  /**
+   * Array for results for each iteration with length iterations
+   */
+  struct Iteration *iterations_results;
+
+  /**
+   * The current result
+   */
+  struct Result *current_result;
+
+  /**
+   * Current number of peers benchmarked
+   */
+  int current_p;
+
+  /**
+   * Current number of addresses benchmarked
+   */
+  int current_a;
+
+  /**
+   * Solver description as string
+   */
+  char *ats_string;
+
+  /**
+   * Configured ATS solver
+   */
+  int ats_mode;
+
+  /**
+   * #peers to start benchmarking with
+   */
+  int N_peers_start;
+
+  /**
+   * #peers to end benchmarking with
+   */
+  int N_peers_end;
+
+  /**
+   * #addresses to benchmarking with
+   */
+  int N_address;
+
+  /**
+   * Percentage of peers to update
+   */
+  int opt_update_percent;
+
+  /**
+   * Create gnuplot file
+   */
+  int create_datafile;
+
+  /**
+   * Measure updates
+   */
+  int measure_updates;
+
+  /**
+   * Number of iterations
+   */
+  int total_iterations;
+
+  /**
+   * Current iteration
+   */
+  int current_iteration;
+
+  /**
+   * Is a bulk operation running?
+   */
+  int bulk_running;
+
+  /**
+   * Is a bulk operation running?
+   */
+  int expecting_solution;
+
+  /**
+   * Was the problem just updates?
+   */
+  int performed_update;
+};
+
+/**
+ * Data structure to store results for a single iteration
+ */
+struct Iteration
+{
+  struct Result **results_array;
+
+  struct Result **update_results_array;
+};
+
+
+/**
+ * Result for a solver calculcation
+ */
+struct Result
+{
+  /**
+   * Previous element in the linked list
+   */
+  struct Result *prev;
+
+  /**
+   * Next element in the linked list
+   */
+  struct Result *next;
+
+  /**
+   * Number of peers this solution included
+   */
+  int peers;
+
+  /**
+   * Number of addresses per peer this solution included
+   */
+  int addresses;
+
+  /**
+   * Is this an update or a full solution
+   */
+  int update;
+
+  /**
+   * Was the solution valid or did the solver fail
+   */
+  int valid;
+
+  /**
+   * Result of the solver
+   */
+  enum GAS_Solver_Additional_Information info;
+
+  /**
+   * Duration of setting up the problem in the solver
+   */
+  struct GNUNET_TIME_Relative d_setup_full;
+
+  /**
+   * Duration of solving the LP problem in the solver
+   * MLP solver only
+   */
+  struct GNUNET_TIME_Relative d_lp_full;
+
+  /**
+   * Duration of solving the MLP problem in the solver
+   * MLP solver only
+   */
+  struct GNUNET_TIME_Relative d_mlp_full;
+
+  /**
+   * Duration of solving whole problem in the solver
+   */
+  struct GNUNET_TIME_Relative d_total_full;
+
+  /**
+   * Start time of setting up the problem in the solver
+   */
+  struct GNUNET_TIME_Absolute s_setup;
+
+  /**
+   * Start time of solving the LP problem in the solver
+   * MLP solver only
+   */
+  struct GNUNET_TIME_Absolute s_lp;
+
+  /**
+   * Start time of solving the MLP problem in the solver
+   * MLP solver only
+   */
+  struct GNUNET_TIME_Absolute s_mlp;
+
+  /**
+   * Start time of solving whole problem in the solver
+   */
+  struct GNUNET_TIME_Absolute s_total;
+
+  /**
+   * End time of setting up the problem in the solver
+   */
+  struct GNUNET_TIME_Absolute e_setup;
+
+  /**
+   * End time of solving the LP problem in the solver
+   * MLP solver only
+   */
+  struct GNUNET_TIME_Absolute e_lp;
+
+  /**
+   * End time of solving the MLP problem in the solver
+   * MLP solver only
+   */
+  struct GNUNET_TIME_Absolute e_mlp;
+
+  /**
+   * End time of solving whole problem in the solver
+   */
+  struct GNUNET_TIME_Absolute e_total;
+};
+
+/**
+ * Peer used for the benchmarking
+ */
+struct PerfPeer
+{
+  /**
+   * Peer identitity
+   */
+  struct GNUNET_PeerIdentity id;
+
+  /**
+   * Head of linked list of addresses used with this peer
+   */
+  struct ATS_Address *head;
+
+  /**
+   * Head of linked list of addresses used with this peer
+   */
+  struct ATS_Address *tail;
+};
+
+
+/**
+ * ATS performance handle
+ */
+static struct PerfHandle ph;
+
+/**
+ * Return value
+ */
+static int ret;
+
+
+/**
+ * Do shutdown
+ */
+static void
+end_now (int res)
+{
+  if (NULL != ph.stat)
+  {
+    GNUNET_STATISTICS_destroy (ph.stat, GNUNET_NO);
+    ph.stat = NULL;
+  }
+
+  GNUNET_free (ph.peers);
+  GNUNET_free (ph.iterations_results);
+
+  GAS_normalization_stop ();
+  GAS_preference_done ();
+  ret = res;
+}
+
+
+/**
+ * Create a peer used for benchmarking
+ *
+ * @param cp the number of the peer
+ */
+static void
+perf_create_peer (int cp)
+{
+  GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_WEAK,
+                              &ph.peers[cp].id, sizeof(struct
+                                                       GNUNET_PeerIdentity));
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Creating peer #%u: %s \n", cp,
+              GNUNET_i2s (&ph.peers[cp].id));
+}
+
+
+/**
+ * Perform an update for an address
+ *
+ * @param cur the address to update
+ */
+static void
+perf_update_address (struct ATS_Address *cur)
+{
+  int r_type;
+  int abs_val;
+  double rel_val;
+
+  r_type = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, 2);
+  switch (r_type)
+  {
+  case 0:
+    abs_val = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, 100);
+    rel_val = (100 + (double) abs_val) / 100;
+
+    GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+                "Updating peer `%s' address %p type %s abs val %u rel val %.3f\n",
+                GNUNET_i2s (&cur->peer), cur,
+                "GNUNET_ATS_QUALITY_NET_DELAY",
+                abs_val, rel_val);
+    ph.sf->s_address_update_property (ph.sf->cls, cur,
+                                      GNUNET_ATS_QUALITY_NET_DELAY,
+                                      abs_val, rel_val);
+    break;
+
+  case 1:
+    abs_val = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, 10);
+    rel_val = (100 + (double) abs_val) / 100;
+
+    GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+                "Updating peer `%s' address %p type %s abs val %u rel val %.3f\n",
+                GNUNET_i2s (&cur->peer), cur, "GNUNET_ATS_QUALITY_NET_DISTANCE",
+                abs_val, rel_val);
+    ph.sf->s_address_update_property (ph.sf->cls, cur,
+                                      GNUNET_ATS_QUALITY_NET_DISTANCE,
+                                      abs_val, rel_val);
+    break;
+
+  default:
+    break;
+  }
+}
+
+
+static void
+bandwidth_changed_cb (void *cls,
+                      struct ATS_Address *address)
+{
+  if ((0 == address->assigned_bw_out) && (0 == address->assigned_bw_in))
+    return;
+
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "Bandwidth changed addresses %s %p to %u Bps out / %u Bps in\n",
+              GNUNET_i2s (&address->peer),
+              address,
+              address->assigned_bw_out,
+              address->assigned_bw_in);
+  if (GNUNET_YES == ph.bulk_running)
+    GNUNET_break (0);
+  return;
+}
+
+
+static const double *
+get_preferences_cb (void *cls, const struct GNUNET_PeerIdentity *id)
+{
+  return GAS_preference_get_by_peer (NULL, id);
+}
+
+
+static void
+perf_address_initial_update (void *dead,
+                             struct GNUNET_CONTAINER_MultiPeerMap *addresses,
+                             struct ATS_Address *address)
+{
+  double delay;
+  double distance;
+  uint32_t random = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, 100);
+
+  delay = (100 + (double) random) / 100;
+  ph.sf->s_address_update_property (ph.sf->cls,
+                                    address, GNUNET_ATS_QUALITY_NET_DELAY,
+                                    100, delay);
+
+  random = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, 100);
+  distance = (100 + (double) random) / 100;
+
+  ph.sf->s_address_update_property (ph.sf->cls, address,
+                                    GNUNET_ATS_QUALITY_NET_DISTANCE,
+                                    10, distance);
+
+  GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+              "Initial update address %p : %.2f  %.2f\n",
+              address, delay, distance);
+}
+
+
+struct DUA_Ctx
+{
+  int r;
+  int c_cur_a;
+};
+
+
+static int
+do_update_address (void *cls,
+                   const struct GNUNET_PeerIdentity *pid,
+                   void *value)
+{
+  struct DUA_Ctx *ctx = cls;
+  struct ATS_Address *addr = value;
+
+  if (ctx->c_cur_a == ctx->r)
+    perf_update_address (addr);
+  ctx->c_cur_a++;
+  return GNUNET_OK;
+}
+
+
+/**
+ * Update a certain percentage of peers
+ *
+ * @param cp the current number of peers
+ * @param ca the current number of addresses
+ * @param percentage_peers the percentage of peers to update
+ */
+static void
+perf_update_all_addresses (unsigned int cp, unsigned int ca, unsigned int
+                           percentage_peers)
+{
+  int c_peer;
+  int c_select;
+  int c_cur_p;
+  int r;
+  int count;
+  unsigned int m[cp];
+  struct DUA_Ctx dua_ctx;
+
+  count = cp * ((double) percentage_peers / 100);
+  GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+              "Updating %u of %u peers \n", count, cp);
+
+  for (c_peer = 0; c_peer < cp; c_peer++)
+    m[c_peer] = 0;
+
+  c_select = 0;
+
+  while (c_select < count)
+  {
+    r = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, cp);
+    if (0 == m[r])
+    {
+      m[r] = 1;
+      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                  "Updating peer [%u] \n", r);
+      c_select++;
+    }
+  }
+  for (c_cur_p = 0; c_cur_p < cp; c_cur_p++)
+  {
+    if (1 == m[c_cur_p])
+    {
+      r = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, ca);
+      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                  "Updating peer [%u] address [%u]\n", c_cur_p, r);
+
+      dua_ctx.c_cur_a = 0;
+      dua_ctx.r = r;
+      GNUNET_CONTAINER_multipeermap_get_multiple (ph.addresses,
+                                                  &ph.peers[c_cur_p].id,
+                                                  &do_update_address,
+                                                  &dua_ctx);
+    }
+  }
+}
+
+
+/**
+ * Create an address for a peer
+ *
+ * @param cp index of the peer
+ * @param ca index of the address
+ * @return the address
+ */
+static struct ATS_Address *
+perf_create_address (int cp, int ca)
+{
+  struct ATS_Address *a;
+
+  a = create_address (&ph.peers[cp].id,
+                      "Test 1", "test 1", strlen ("test 1") + 1, 0);
+  GNUNET_CONTAINER_multipeermap_put (ph.addresses, &ph.peers[cp].id, a,
+                                     GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE);
+  return a;
+}
+
+
+/**
+ * Information callback for the solver
+ *
+ * @param op the solver operation
+ * @param stat status of the solver operation
+ * @param add additional solver information
+ */
+static void
+solver_info_cb (void *cls,
+                enum GAS_Solver_Operation op,
+                enum GAS_Solver_Status stat,
+                enum GAS_Solver_Additional_Information add)
+{
+  char *add_info;
+
+  switch (add)
+  {
+  case GAS_INFO_NONE:
+    add_info = "GAS_INFO_NONE";
+    break;
+
+  case GAS_INFO_FULL:
+    add_info = "GAS_INFO_MLP_FULL";
+    break;
+
+  case GAS_INFO_UPDATED:
+    add_info = "GAS_INFO_MLP_UPDATED";
+    break;
+
+  case GAS_INFO_PROP_ALL:
+    add_info = "GAS_INFO_PROP_ALL";
+    break;
+
+  case GAS_INFO_PROP_SINGLE:
+    add_info = "GAS_INFO_PROP_SINGLE";
+    break;
+
+  default:
+    add_info = "INVALID";
+    break;
+  }
+
+  struct Result *tmp;
+  switch (op)
+  {
+  case GAS_OP_SOLVE_START:
+    GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+                "Solver notifies `%s' with result `%s' `%s'\n",
+                "GAS_OP_SOLVE_START",
+                (GAS_STAT_SUCCESS == stat) ? "SUCCESS" : "FAIL", add_info);
+    if (GNUNET_NO == ph.expecting_solution)
+    {
+      /* We do not expect a solution at the moment */
+      GNUNET_break (0);
+      return;
+    }
+
+    if ((GAS_STAT_SUCCESS == stat) && (NULL == ph.current_result))
+    {
+      tmp = GNUNET_new (struct Result);
+      /* Create new result */
+      if ((add == GAS_INFO_UPDATED) || (GNUNET_YES == ph.performed_update))
+      {
+        ph.current_result = tmp;
+        // fprintf (stderr,"UPDATE %u %u\n",ph.current_iteration-1, ph.current_p);
+        ph.iterations_results[ph.current_iteration
+                              - 1].update_results_array[ph.current_p] = tmp;
+      }
+      else
+      {
+        ph.current_result = tmp;
+        // fprintf (stderr,"FULL %u %u\n",ph.current_iteration-1, ph.current_p);
+        ph.iterations_results[ph.current_iteration
+                              - 1].results_array[ph.current_p] = tmp;
+      }
+
+      ph.current_result->addresses = ph.current_a;
+      ph.current_result->peers = ph.current_p;
+      ph.current_result->s_total = GNUNET_TIME_absolute_get ();
+      ph.current_result->d_total_full = GNUNET_TIME_UNIT_FOREVER_REL;
+      ph.current_result->d_setup_full = GNUNET_TIME_UNIT_FOREVER_REL;
+      ph.current_result->d_lp_full = GNUNET_TIME_UNIT_FOREVER_REL;
+      ph.current_result->d_mlp_full = GNUNET_TIME_UNIT_FOREVER_REL;
+      ph.current_result->info = add;
+      if ((add == GAS_INFO_UPDATED) || (GNUNET_YES == ph.performed_update))
+      {
+        ph.current_result->update = GNUNET_YES;
+      }
+      else
+      {
+        ph.current_result->update = GNUNET_NO;
+      }
+    }
+    return;
+
+  case GAS_OP_SOLVE_STOP:
+    GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+                "Solver notifies `%s' with result `%s', `%s'\n",
+                "GAS_OP_SOLVE_STOP",
+                (GAS_STAT_SUCCESS == stat) ? "SUCCESS" : "FAIL", add_info);
+    if ((GNUNET_NO == ph.expecting_solution) || (NULL == ph.current_result))
+    {
+      /* We do not expect a solution at the moment */
+      GNUNET_break (0);
+      return;
+    }
+
+    if (GAS_STAT_SUCCESS == stat)
+      ph.current_result->valid = GNUNET_YES;
+    else
+      ph.current_result->valid = GNUNET_NO;
+
+    if (NULL != ph.current_result)
+    {
+      /* Finalize result */
+      ph.current_result->e_total = GNUNET_TIME_absolute_get ();
+      ph.current_result->d_total_full = GNUNET_TIME_absolute_get_difference (
+        ph.current_result->s_total, ph.current_result->e_total);
+    }
+    ph.current_result = NULL;
+    return;
+
+  case GAS_OP_SOLVE_SETUP_START:
+    GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+                "Solver notifies `%s' with result `%s'\n",
+                "GAS_OP_SOLVE_SETUP_START",
+                (GAS_STAT_SUCCESS == stat) ? "SUCCESS" : "FAIL");
+    if ((GNUNET_NO == ph.expecting_solution) || (NULL == ph.current_result))
+    {
+      GNUNET_break (0);
+      return;
+    }
+
+    if (GAS_STAT_SUCCESS == stat)
+      ph.current_result->valid = GNUNET_YES;
+    else
+      ph.current_result->valid = GNUNET_NO;
+
+    ph.current_result->s_setup = GNUNET_TIME_absolute_get ();
+    return;
+
+  case GAS_OP_SOLVE_SETUP_STOP:
+    GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+                "Solver notifies `%s' with result `%s'\n",
+                "GAS_OP_SOLVE_SETUP_STOP",
+                (GAS_STAT_SUCCESS == stat) ? "SUCCESS" : "FAIL");
+    if ((GNUNET_NO == ph.expecting_solution) || (NULL == ph.current_result))
+    {
+      GNUNET_break (0);
+      return;
+    }
+
+    if (GAS_STAT_SUCCESS == stat)
+      ph.current_result->valid = GNUNET_YES;
+    else
+      ph.current_result->valid = GNUNET_NO;
+
+    ph.current_result->e_setup = GNUNET_TIME_absolute_get ();
+    ph.current_result->d_setup_full = GNUNET_TIME_absolute_get_difference (
+      ph.current_result->s_setup, ph.current_result->e_setup);
+    return;
+
+  case GAS_OP_SOLVE_MLP_LP_START:
+    GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+                "Solver notifies `%s' with result `%s'\n",
+                "GAS_OP_SOLVE_LP_START",
+                (GAS_STAT_SUCCESS == stat) ? "SUCCESS" : "FAIL");
+    if ((GNUNET_NO == ph.expecting_solution) || (NULL == ph.current_result))
+    {
+      GNUNET_break (0);
+      return;
+    }
+
+    if (GAS_STAT_SUCCESS == stat)
+      ph.current_result->valid = GNUNET_YES;
+    else
+      ph.current_result->valid = GNUNET_NO;
+
+    ph.current_result->s_lp = GNUNET_TIME_absolute_get ();
+    return;
+
+  case GAS_OP_SOLVE_MLP_LP_STOP:
+    GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+                "Solver notifies `%s' with result `%s'\n",
+                "GAS_OP_SOLVE_LP_STOP",
+                (GAS_STAT_SUCCESS == stat) ? "SUCCESS" : "FAIL");
+    if ((GNUNET_NO == ph.expecting_solution) || (NULL == ph.current_result))
+    {
+      GNUNET_break (0);
+      return;
+    }
+
+    if (GAS_STAT_SUCCESS == stat)
+      ph.current_result->valid = GNUNET_YES;
+    else
+      ph.current_result->valid = GNUNET_NO;
+
+    ph.current_result->e_lp = GNUNET_TIME_absolute_get ();
+    ph.current_result->d_lp_full = GNUNET_TIME_absolute_get_difference (
+      ph.current_result->s_lp, ph.current_result->e_lp);
+    return;
+
+  case GAS_OP_SOLVE_MLP_MLP_START:
+    GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+                "Solver notifies `%s' with result `%s'\n",
+                "GAS_OP_SOLVE_MLP_START",
+                (GAS_STAT_SUCCESS == stat) ? "SUCCESS" : "FAIL");
+    if ((GNUNET_NO == ph.expecting_solution) || (NULL == ph.current_result))
+    {
+      GNUNET_break (0);
+      return;
+    }
+
+    if (GAS_STAT_SUCCESS == stat)
+      ph.current_result->valid = GNUNET_YES;
+    else
+      ph.current_result->valid = GNUNET_NO;
+
+    ph.current_result->s_mlp = GNUNET_TIME_absolute_get ();
+    return;
+
+  case GAS_OP_SOLVE_MLP_MLP_STOP:
+    GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+                "Solver notifies `%s' with result `%s'\n",
+                "GAS_OP_SOLVE_MLP_STOP",
+                (GAS_STAT_SUCCESS == stat) ? "SUCCESS" : "FAIL");
+    if ((GNUNET_NO == ph.expecting_solution) || (NULL == ph.current_result))
+    {
+      GNUNET_break (0);
+      return;
+    }
+
+    if (GAS_STAT_SUCCESS == stat)
+      ph.current_result->valid = GNUNET_YES;
+    else
+      ph.current_result->valid = GNUNET_NO;
+
+    ph.current_result->e_mlp = GNUNET_TIME_absolute_get ();
+    ph.current_result->d_mlp_full = GNUNET_TIME_absolute_get_difference (
+      ph.current_result->s_mlp, ph.current_result->e_mlp);
+    return;
+
+  case GAS_OP_SOLVE_UPDATE_NOTIFICATION_START:
+    GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+                "Solver notifies `%s' with result `%s'\n",
+                "GAS_OP_SOLVE_UPDATE_NOTIFICATION_START",
+                (GAS_STAT_SUCCESS == stat) ? "SUCCESS" : "FAIL");
+    return;
+
+  case GAS_OP_SOLVE_UPDATE_NOTIFICATION_STOP:
+    GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+                "Solver notifies `%s' with result `%s'\n",
+                "GAS_OP_SOLVE_UPDATE_NOTIFICATION_STOP",
+                (GAS_STAT_SUCCESS == stat) ? "SUCCESS" : "FAIL");
+    if (GAS_STAT_SUCCESS != stat)
+    {
+      GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                  "Solver `%s' failed to update problem with %u peers and %u address!\n",
+                  ph.ats_string, ph.current_p, ph.current_a);
+    }
+
+    return;
+
+  default:
+    break;
+  }
+}
+
+
+/**
+ * Evaluate results for a specific iteration
+ *
+ * @param iteration the iteration to evaluate
+ */
+static void
+evaluate (int iteration)
+{
+  struct Result *cur;
+  int cp;
+
+  for (cp = ph.N_peers_start; cp <= ph.N_peers_end; cp++)
+  {
+    cur = ph.iterations_results[ph.current_iteration - 1].results_array[cp];
+    if (0 == cp)
+      continue;
+    if (NULL == cur)
+    {
+      GNUNET_break (0);
+      fprintf (stderr,
+               "Missing result for %u peers\n", cp);
+      continue;
+    }
+
+
+    if (GNUNET_NO == cur->valid)
+    {
+      fprintf (stderr,
+               "Total time to solve %s for %u peers %u addresses: %s\n",
+               (GNUNET_YES == cur->update) ? "updated" : "full",
+               cur->peers, cur->addresses, "Failed to solve!");
+      continue;
+    }
+
+
+    if (GNUNET_TIME_UNIT_FOREVER_REL.rel_value_us !=
+        cur->d_total_full.rel_value_us)
+    {
+      fprintf (stderr,
+               "Total time to solve %s for %u peers %u addresses: %llu us\n",
+               (GNUNET_YES == cur->update) ? "updated" : "full",
+               cur->peers, cur->addresses,
+               (unsigned long long) cur->d_total_full.rel_value_us);
+    }
+
+
+    if (GNUNET_TIME_UNIT_FOREVER_REL.rel_value_us !=
+        cur->d_setup_full.rel_value_us)
+    {
+      GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+                  "Total time to setup %s %u peers %u addresses: %llu us\n",
+                  (GNUNET_YES == cur->update) ? "updated" : "full",
+                  cur->peers, cur->addresses,
+                  (unsigned long long) cur->d_setup_full.rel_value_us);
+    }
+
+    if (GNUNET_TIME_UNIT_FOREVER_REL.rel_value_us !=
+        cur->d_lp_full.rel_value_us)
+    {
+      GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+                  "Total time to solve %s LP for %u peers %u addresses: %llu us\n",
+                  (GNUNET_YES == cur->update) ? "updated" : "full",
+                  cur->peers,
+                  cur->addresses,
+                  (unsigned long long ) cur->d_lp_full.rel_value_us);
+    }
+
+    if (GNUNET_TIME_UNIT_FOREVER_REL.rel_value_us !=
+        cur->d_mlp_full.rel_value_us)
+    {
+      GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+                  "Total time to solve %s MLP for %u peers %u addresses: %llu us\n",
+                  (GNUNET_YES == cur->update) ? "updated" : "full",
+                  cur->peers, cur->addresses,
+                  (unsigned long long ) cur->d_mlp_full.rel_value_us);
+    }
+  }
+}
+
+
+static unsigned int
+get_connectivity_cb (void *cls,
+                     const struct GNUNET_PeerIdentity *peer)
+{
+  return GNUNET_CONTAINER_multipeermap_contains (ph.addresses,
+                                                 peer);
+}
+
+
+/**
+ * Evaluate average results for all iterations
+ */
+static void
+write_all_iterations (void)
+{
+  int c_iteration;
+  int c_peer;
+
+  struct GNUNET_DISK_FileHandle *f_full;
+  struct GNUNET_DISK_FileHandle *f_update;
+  char *data_fn_full;
+  char *data_fn_update;
+  char *data;
+
+  f_full = NULL;
+  f_update = NULL;
+
+  data_fn_full = NULL;
+
+  if (GNUNET_NO == ph.create_datafile)
+    return;
+
+  GNUNET_asprintf (&data_fn_full,
+                   "perf_%s_full_%u-%u_%u_%u.data",
+                   ph.ats_string,
+                   ph.total_iterations,
+                   ph.N_peers_start,
+                   ph.N_peers_end,
+                   ph.N_address);
+  GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+              "Using data file `%s'\n",
+              data_fn_full);
+
+  f_full = GNUNET_DISK_file_open (data_fn_full,
+                                  GNUNET_DISK_OPEN_WRITE
+                                  | GNUNET_DISK_OPEN_CREATE,
+                                  GNUNET_DISK_PERM_USER_EXEC
+                                  | GNUNET_DISK_PERM_USER_READ
+                                  | GNUNET_DISK_PERM_USER_WRITE);
+  if (NULL == f_full)
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                "Cannot open data file `%s'\n",
+                data_fn_full);
+    GNUNET_free (data_fn_full);
+    return;
+  }
+
+  data =
+    "#peers;addresses;time total in us;#time setup in us;#time lp in us;#time mlp in us;\n";
+  if (GNUNET_SYSERR == GNUNET_DISK_file_write (f_full, data, strlen (data)))
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                "Cannot write data to log file `%s'\n",
+                data_fn_full);
+
+  data_fn_update = NULL;
+  if (GNUNET_YES == ph.measure_updates)
+  {
+    GNUNET_asprintf (&data_fn_update, "perf_%s_update_%u-%u_%u_%u.data",
+                     ph.ats_string,
+                     ph.total_iterations,
+                     ph.N_peers_start,
+                     ph.N_peers_end,
+                     ph.N_address);
+    f_update = GNUNET_DISK_file_open (data_fn_update,
+                                      GNUNET_DISK_OPEN_WRITE
+                                      | GNUNET_DISK_OPEN_CREATE,
+                                      GNUNET_DISK_PERM_USER_EXEC
+                                      | GNUNET_DISK_PERM_USER_READ
+                                      | GNUNET_DISK_PERM_USER_WRITE);
+    if (NULL == f_update)
+    {
+      GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                  "Cannot open gnuplot file `%s'\n", data_fn_update);
+      GNUNET_free (data_fn_update);
+      if (NULL != f_full)
+        GNUNET_DISK_file_close (f_full);
+      GNUNET_free (data_fn_full);
+      return;
+    }
+
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                "Using update data file `%s'\n",
+                data_fn_update);
+
+    data =
+      "#peers;addresses;time total in us;#time setup in us;#time lp in us;#time mlp in us;\n";
+    if (GNUNET_SYSERR == GNUNET_DISK_file_write (f_update, data, strlen (data)))
+      GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                  "Cannot write data to log file `%s'\n",
+                  data_fn_update);
+  }
+
+  for (c_peer = ph.N_peers_start; c_peer <= ph.N_peers_end; c_peer++)
+  {
+    char *data_str;
+    char *data_tmp;
+    char *data_upd_str;
+    char *data_upd_tmp;
+    GNUNET_asprintf (&data_str, "%u;%u", c_peer, ph.N_address);
+    if (ph.measure_updates)
+      GNUNET_asprintf (&data_upd_str, "%u;%u", c_peer, ph.N_address);
+    for (c_iteration = 0; c_iteration < ph.total_iterations; c_iteration++)
+    {
+      struct Result *cur_full_res;
+      struct Result *cur_upd_res;
+
+
+      // fprintf (stderr, "P: %u I: %u  == %p \n", c_peer, c_iteration, cur_res);
+      cur_full_res = ph.iterations_results[c_iteration].results_array[c_peer];
+      if (c_peer == 0)
+        continue;
+      if (NULL == cur_full_res)
+        continue;
+
+      if (ph.measure_updates)
+      {
+        cur_upd_res =
+          ph.iterations_results[c_iteration].update_results_array[c_peer];
+        data_upd_tmp = GNUNET_strdup (data_upd_str);
+        GNUNET_free (data_upd_str);
+        if (GNUNET_YES == cur_full_res->valid)
+        {
+          GNUNET_asprintf (&data_upd_str, "%s;%llu", data_upd_tmp,
+                           (NULL == cur_upd_res) ? 0 :
+                           cur_upd_res->d_total_full.rel_value_us);
+        }
+        else
+        {
+          GNUNET_asprintf (&data_upd_str, "%s;", data_upd_tmp);
+        }
+        GNUNET_free (data_upd_tmp);
+      }
+
+      // fprintf (stderr, "P: %u I: %u: P %i  A %i\n", c_peer, c_iteration, cur_res->peers, cur_res->addresses);
+      // fprintf (stderr, "D total: %llu\n", (long long unsigned int) cur_res->d_total.rel_value_us);
+
+      data_tmp = GNUNET_strdup (data_str);
+      GNUNET_free (data_str);
+      if (GNUNET_YES == cur_full_res->valid)
+      {
+        GNUNET_asprintf (&data_str, "%s;%llu", data_tmp,
+                         cur_full_res->d_total_full.rel_value_us);
+      }
+      else
+      {
+        GNUNET_asprintf (&data_str, "%s;", data_tmp);
+      }
+
+      GNUNET_free (data_tmp);
+    }
+    data_tmp = GNUNET_strdup (data_str);
+    GNUNET_free (data_str);
+    GNUNET_asprintf (&data_str, "%s\n", data_tmp);
+    GNUNET_free (data_tmp);
+
+    fprintf (stderr, "Result full solution: %s\n", data_str);
+    if (GNUNET_SYSERR == GNUNET_DISK_file_write (f_full, data_str, strlen (
+                                                   data_str)))
+      GNUNET_break (0);
+    GNUNET_free (data_str);
+
+    if (ph.measure_updates)
+    {
+      data_upd_tmp = GNUNET_strdup (data_upd_str);
+      GNUNET_free (data_upd_str);
+      GNUNET_asprintf (&data_upd_str, "%s\n", data_upd_tmp);
+      GNUNET_free (data_upd_tmp);
+
+      fprintf (stderr, "Result updated solution: `%s'\n", data_upd_str);
+      if (GNUNET_SYSERR == GNUNET_DISK_file_write (f_update, data_upd_str,
+                                                   strlen (data_upd_str)))
+        GNUNET_break (0);
+      GNUNET_free (data_upd_str);
+    }
+  }
+
+  if ((NULL != f_full) && (GNUNET_SYSERR == GNUNET_DISK_file_close (f_full)))
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Cannot close log file `%s'\n",
+                data_fn_full);
+  GNUNET_free (data_fn_full);
+
+  if ((NULL != f_update) && (GNUNET_SYSERR == GNUNET_DISK_file_close (
+                               f_update)))
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Cannot close log file `%s'\n",
+                data_fn_update);
+  GNUNET_free (data_fn_update);
+}
+
+
+static int
+do_delete_address (void *cls,
+                   const struct GNUNET_PeerIdentity *pid,
+                   void *value)
+{
+  struct ATS_Address *cur = value;
+
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "Deleting addresses for peer %u\n",
+              pid);
+  GNUNET_assert (GNUNET_OK ==
+                 GNUNET_CONTAINER_multipeermap_remove (ph.addresses,
+                                                       pid,
+                                                       cur));
+  ph.sf->s_del (ph.sf->cls, cur);
+  GNUNET_free (cur->atsi);
+  GNUNET_free (cur);
+  return GNUNET_OK;
+}
+
+
+/**
+ * Run a performance iteration
+ */
+static void
+perf_run_iteration (void)
+{
+  int cp;
+  int ca;
+  int count_p = ph.N_peers_end;
+  int count_a = ph.N_address;
+  struct ATS_Address *cur_addr;
+  uint32_t net;
+
+  ph.iterations_results[ph.current_iteration - 1].results_array =
+    GNUNET_malloc ((count_p + 1) * sizeof(struct Result *));
+  if (ph.measure_updates)
+    ph.iterations_results[ph.current_iteration - 1].update_results_array =
+      GNUNET_malloc ((count_p + 1) * sizeof(struct Result *));
+  ph.peers = GNUNET_malloc ((count_p) * sizeof(struct PerfPeer));
+  for (cp = 0; cp < count_p; cp++)
+    perf_create_peer (cp);
+  GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+              "Iteration %u of %u, added %u peers\n", ph.current_iteration,
+              ph.total_iterations, cp);
+
+  for (cp = 0; cp < count_p; cp++)
+  {
+    fprintf (stderr, "%u..", cp);
+    if (GNUNET_NO == ph.bulk_running)
+    {
+      ph.bulk_running = GNUNET_YES;
+      ph.sf->s_bulk_start (ph.sf->cls);
+    }
+    ph.current_p = cp + 1;
+    for (ca = 0; ca < count_a; ca++)
+    {
+      cur_addr = perf_create_address (cp, ca);
+      /* Add address */
+
+      /* Random network selection */
+      // net = 1 + GNUNET_CRYPTO_random_u32(GNUNET_CRYPTO_QUALITY_WEAK, GNUNET_NT_COUNT - 1);
+      /* Random equally distributed network selection */
+      net = 1 + (ca % (GNUNET_NT_COUNT - 1));
+      /* fprintf (stderr, "Network: %u `%s'\n",
+       * mod_net , GNUNET_NT_to_string(mod_net)); */
+
+      cur_addr->atsi = GNUNET_new (struct GNUNET_ATS_Information);
+      cur_addr->atsi_count = 1;
+      cur_addr->atsi[0].type = htonl (GNUNET_ATS_NETWORK_TYPE);
+      cur_addr->atsi[0].value = htonl (net);
+      ph.sf->s_add (ph.sf->cls, cur_addr, net);
+
+      ph.current_a = ca + 1;
+      perf_address_initial_update (NULL, ph.addresses, cur_addr);
+      GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+                  "Adding address for peer %u address %u in network %s\n", cp,
+                  ca,
+                  GNUNET_NT_to_string (net));
+    }
+    /* Notify solver about request */
+    ph.sf->s_get (ph.sf->cls, &ph.peers[cp].id);
+
+    if (cp + 1 >= ph.N_peers_start)
+    {
+      /* Disable bulk to solve the problem */
+      if (GNUNET_YES == ph.bulk_running)
+      {
+        ph.expecting_solution = GNUNET_YES;
+        ph.bulk_running = GNUNET_NO;
+        ph.sf->s_bulk_stop (ph.sf->cls);
+      }
+      else
+        GNUNET_break (0);
+
+      /* Problem is solved by the solver here due to unlocking */
+      ph.expecting_solution = GNUNET_NO;
+
+      /* Update the problem */
+      if ((0 < ph.opt_update_percent) && (GNUNET_YES == ph.measure_updates))
+      {
+        /* Update */
+        GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+                    "Updating problem with %u peers and %u addresses\n", cp + 1,
+                    ca);
+
+        ph.expecting_solution = GNUNET_YES;
+        ph.performed_update = GNUNET_YES;
+        if (GNUNET_NO == ph.bulk_running)
+        {
+          ph.bulk_running = GNUNET_YES;
+          ph.sf->s_bulk_start (ph.sf->cls);
+        }
+        perf_update_all_addresses (cp + 1, ca, ph.opt_update_percent);
+        ph.bulk_running = GNUNET_NO;
+        ph.sf->s_bulk_stop (ph.sf->cls);
+        /* Problem is solved by the solver here due to unlocking */
+        ph.performed_update = GNUNET_NO;
+        ph.expecting_solution = GNUNET_NO;
+      }
+      GNUNET_assert (GNUNET_NO == ph.bulk_running);
+    }
+  }
+  fprintf (stderr, "\n");
+  GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+              "Done, cleaning up addresses\n");
+  if (GNUNET_NO == ph.bulk_running)
+  {
+    ph.sf->s_bulk_start (ph.sf->cls);
+    ph.bulk_running = GNUNET_YES;
+  }
+
+  for (cp = 0; cp < count_p; cp++)
+  {
+    GNUNET_CONTAINER_multipeermap_get_multiple (ph.addresses,
+                                                &ph.peers[cp].id,
+                                                &do_delete_address,
+                                                NULL);
+  }
+  if (GNUNET_NO == ph.bulk_running)
+  {
+    ph.sf->s_bulk_stop (ph.sf->cls);
+    ph.bulk_running = GNUNET_NO;
+  }
+
+  GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+              "Iteration done\n");
+  GNUNET_free (ph.peers);
+}
+
+
+static void
+run (void *cls, char *const *args, const char *cfgfile,
+     const struct GNUNET_CONFIGURATION_Handle *cfg)
+{
+  GNUNET_log_setup ("perf-ats-solver", "WARNING", NULL);
+  char *sep;
+  char *src_filename = GNUNET_strdup (__FILE__);
+  char *test_filename = cls;
+  char *solver;
+  char *plugin;
+  struct GNUNET_CONFIGURATION_Handle *solver_cfg;
+  unsigned long long quotas_in[GNUNET_NT_COUNT];
+  unsigned long long quotas_out[GNUNET_NT_COUNT];
+  int c;
+  int c2;
+
+  /* Extract test name */
+  if (NULL == (sep = (strstr (src_filename, ".c"))))
+  {
+    GNUNET_free (src_filename);
+    GNUNET_break (0);
+    ret = 1;
+    return;
+  }
+  sep[0] = '\0';
+
+  if (NULL != (sep = strstr (test_filename, ".exe")))
+    sep[0] = '\0';
+
+  if (NULL == (solver = strstr (test_filename, src_filename)))
+  {
+    GNUNET_free (src_filename);
+    GNUNET_break (0);
+    ret = 1;
+    return;
+  }
+  solver += strlen (src_filename) + 1;
+
+  if (0 == strcmp (solver, "proportional"))
+  {
+    ph.ats_string = "proportional";
+  }
+  else if (0 == strcmp (solver, "mlp"))
+  {
+    ph.ats_string = "mlp";
+  }
+  else if ((0 == strcmp (solver, "ril")))
+  {
+    ph.ats_string = "ril";
+  }
+  else
+  {
+    GNUNET_free (src_filename);
+    GNUNET_break (0);
+    ret = 1;
+    return;
+  }
+  GNUNET_free (src_filename);
+
+  /* Calculcate peers */
+  if ((0 == ph.N_peers_start) && (0 == ph.N_peers_end))
+  {
+    ph.N_peers_start = DEFAULT_PEERS_START;
+    ph.N_peers_end = DEFAULT_PEERS_END;
+  }
+  if (0 == ph.N_address)
+    ph.N_address = DEFAULT_ADDRESSES;
+
+
+  if (ph.N_peers_start != ph.N_peers_end)
+    fprintf (stderr,
+             "Benchmarking solver `%s' with %u to %u peers and %u addresses in %u iterations\n",
+             ph.ats_string, ph.N_peers_start, ph.N_peers_end, ph.N_address,
+             ph.total_iterations);
+  else
+    fprintf (stderr,
+             "Benchmarking solver `%s' with %u peers and %u addresses in %u iterations\n",
+             ph.ats_string, ph.N_peers_end, ph.N_address, ph.total_iterations);
+
+  if (0 == ph.opt_update_percent)
+    ph.opt_update_percent = DEFAULT_UPDATE_PERCENTAGE;
+
+  /* Load quotas */
+  solver_cfg = GNUNET_CONFIGURATION_create ();
+  if ((NULL == solver_cfg) || (GNUNET_SYSERR == (GNUNET_CONFIGURATION_load (
+                                                   solver_cfg,
+                                                   "perf_ats_solver.conf"))))
+  {
+    GNUNET_break (0);
+    end_now (1);
+    return;
+  }
+  if (GNUNET_NT_COUNT != load_quotas (solver_cfg,
+                                      quotas_out, quotas_in, GNUNET_NT_COUNT))
+  {
+    GNUNET_break (0);
+    end_now (1);
+    return;
+  }
+
+  /* Create array of DLL to store results for iterations */
+  ph.iterations_results = GNUNET_malloc (sizeof(struct Iteration)
+                                         * ph.total_iterations);
+
+  /* Load solver */
+  ph.env.cfg = solver_cfg;
+  ph.stat = GNUNET_STATISTICS_create ("ats", cfg);
+  ph.env.stats = ph.stat;
+  ph.addresses = GNUNET_CONTAINER_multipeermap_create (128, GNUNET_NO);
+  ph.env.addresses = ph.addresses;
+  ph.env.bandwidth_changed_cb = bandwidth_changed_cb;
+  ph.env.get_connectivity = &get_connectivity_cb;
+  ph.env.get_preferences = &get_preferences_cb;
+  ph.env.network_count = GNUNET_NT_COUNT;
+  ph.env.info_cb = &solver_info_cb;
+
+  for (c = 0; c < GNUNET_NT_COUNT; c++)
+  {
+    ph.env.out_quota[c] = quotas_out[c];
+    ph.env.in_quota[c] = quotas_in[c];
+    GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+                "Loading network quotas: `%s' %llu %llu \n",
+                GNUNET_NT_to_string (c),
+                ph.env.out_quota[c],
+                ph.env.in_quota[c]);
+  }
+  GAS_normalization_start ();
+  GAS_preference_init ();
+
+  GNUNET_asprintf (&plugin,
+                   "libgnunet_plugin_ats_%s",
+                   ph.ats_string);
+  GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+              _ ("Initializing solver `%s'\n"),
+              ph.ats_string);
+  if (NULL == (ph.sf = GNUNET_PLUGIN_load (plugin, &ph.env)))
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                _ ("Failed to initialize solver `%s'!\n"),
+                plugin);
+    ret = 1;
+    return;
+  }
+
+  /* Do the benchmark */
+  for (ph.current_iteration = 1; ph.current_iteration <= ph.total_iterations;
+       ph.current_iteration++)
+  {
+    fprintf (stderr,
+             "Iteration %u of %u starting\n",
+             ph.current_iteration,
+             ph.total_iterations);
+    perf_run_iteration ();
+    evaluate (ph.current_iteration);
+    fprintf (stderr,
+             "Iteration %u of %u done\n",
+             ph.current_iteration,
+             ph.total_iterations);
+  }
+  if (ph.create_datafile)
+    write_all_iterations ();
+
+  /* Unload solver*/
+  GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+              _ ("Unloading solver `%s'\n"),
+              ph.ats_string);
+  GNUNET_PLUGIN_unload (plugin, ph.sf);
+  ph.sf = NULL;
+  GNUNET_free (plugin);
+  for (c = 0; c < ph.total_iterations; c++)
+  {
+    for (c2 = ph.N_peers_start; c2 < ph.N_peers_end; c2++)
+    {
+      if (0 == c2)
+        continue;
+      if (ph.measure_updates)
+        GNUNET_free (
+          ph.iterations_results[c].update_results_array[c2]);
+      GNUNET_free (ph.iterations_results[c].results_array[c2]);
+    }
+    if (ph.measure_updates)
+      GNUNET_free (ph.iterations_results[c].update_results_array);
+    GNUNET_free (ph.iterations_results[c].results_array);
+  }
+  GNUNET_free (ph.iterations_results);
+
+  GNUNET_CONFIGURATION_destroy (solver_cfg);
+  GNUNET_STATISTICS_destroy (ph.stat, GNUNET_NO);
+}
+
+
+/**
+ * Main function of the benchmark
+ *
+ * @param argc argument count
+ * @param argv argument values
+ */
+int
+main (int argc, char *argv[])
+{
+  /* extract command line arguments */
+  ph.opt_update_percent = 0;
+  ph.N_peers_start = 0;
+  ph.N_peers_end = 0;
+  ph.N_address = 0;
+  ph.ats_string = NULL;
+  ph.create_datafile = GNUNET_NO;
+  ph.measure_updates = GNUNET_NO;
+  ph.total_iterations = 1;
+
+  static struct GNUNET_GETOPT_CommandLineOption options[] = {
+    GNUNET_GETOPT_option_uint ('a',
+                               "addresses",
+                               gettext_noop ("addresses to use"),
+                               &ph.N_address),
+
+    GNUNET_GETOPT_option_uint ('s',
+                               "start",
+                               gettext_noop ("start with peer"),
+                               &ph.N_peers_start),
+
+    GNUNET_GETOPT_option_uint ('e',
+                               "end",
+                               gettext_noop ("end with peer"),
+                               &ph.N_peers_end),
+
+    GNUNET_GETOPT_option_uint ('i',
+                               "iterations",
+                               gettext_noop (
+                                 "number of iterations used for averaging (default: 1)"),
+                               &ph.total_iterations),
+
+    GNUNET_GETOPT_option_uint ('p',
+                               "percentage",
+                               gettext_noop (
+                                 "update a fix percentage of addresses"),
+                               &ph.opt_update_percent),
+
+    GNUNET_GETOPT_option_flag ('d',
+                               "data",
+                               gettext_noop ("create data file"),
+                               &ph.create_datafile),
+
+    GNUNET_GETOPT_option_flag ('u',
+                               "update",
+                               gettext_noop ("measure updates"),
+                               &ph.measure_updates),
+
+    GNUNET_GETOPT_OPTION_END
+  };
+
+  GNUNET_PROGRAM_run (argc, argv, argv[0], NULL, options, &run, argv[0]);
+  return ret;
+}
+
+
+/* end of file perf_ats_solver.c */
diff --git a/src/ats/perf_ats_solver.conf b/src/ats/perf_ats_solver.conf
new file mode 100644
index 0000000000000000000000000000000000000000..00657d895a18f296021a854e13b363f8b112e164
--- /dev/null
+++ b/src/ats/perf_ats_solver.conf
@@ -0,0 +1,77 @@
+[ats]
+# Network specific inbound/outbound quotas
+UNSPECIFIED_QUOTA_IN = 1000000
+UNSPECIFIED_QUOTA_OUT = 1000000
+# LOOPBACK
+LOOPBACK_QUOTA_IN = 10000000
+LOOPBACK_QUOTA_OUT = 10000000
+# LAN
+LAN_QUOTA_IN = 10000000
+LAN_QUOTA_OUT = 10000000
+# WAN
+WAN_QUOTA_IN = 10000000
+WAN_QUOTA_OUT = 10000000
+# WLAN
+WLAN_QUOTA_IN = 10000000
+WLAN_QUOTA_OUT = 10000000
+# BLUETOOTH
+BLUETOOTH_QUOTA_IN = 10000000
+BLUETOOTH_QUOTA_OUT = 10000000
+
+# Proportional specific settings
+# How proportional to preferences is bandwidth distribution in a network
+# 1: Fair with respect to addresses without preferences
+# > 10: The bigger, the more respect is payed to preferences 
+PROP_PROPORTIONALITY_FACTOR = 2.00
+# Should we stick to existing connections are prefer to switch?
+# [10...200], lower value prefers to switch, bigger value is more tolerant
+PROP_STABILITY_FACTOR = 1.25
+
+# MLP specific settings
+# MLP defaults
+
+# Maximum duration for a solution process
+# MLP_MAX_DURATION = 30 s
+
+# Maximum number of iterations for a solution process
+# MLP_MAX_ITERATIONS = 1024
+# Tolerated MIP Gap [0.0 .. 1.0], default 0.025
+MLP_MAX_MIP_GAP = 0.025
+# Tolerated LP/MIP Gap [0.0 .. 1.0], default 0.025
+MLP_MAX_LP_MIP_GAP = 0.025
+
+# MLP_COEFFICIENT_D = 1.0
+# MLP_COEFFICIENT_U = 1.0
+# MLP_COEFFICIENT_R = 1.0
+MLP_MIN_BANDWIDTH = 10
+# MLP_MIN_CONNECTIONS = 4
+# MLP_DBG_FEASIBILITY_ONLY = YES
+MLP_DBG_AUTOSCALE_PROBLEM = YES
+# MLP_DBG_INTOPT_PRESOLVE = YES
+# Print GLPK output
+# MLP_DBG_GLPK_VERBOSE = YES
+
+#MLP_DBG_OPTIMIZE_UTILITY = NO
+#MLP_DBG_OPTIMIZE_QUALITY = NO
+#MLP_DBG_OPTIMIZE_RELATIVITY = NO
+#DLP_DBG_OPTIMIZE_DIVERSITY = NO
+
+MLP_LOG_FORMAT = CPLEX
+
+# MLP Log settings
+# Dump all problems to disk
+# MLP_DUMP_PROBLEM_ALL = YES
+# Dump all solution to disk
+# MLP_DUMP_SOLUTION_ALL = YES
+
+# RIL specifc settings
+RIL_STEP_TIME_MIN = 1 ms
+RIL_STEP_TIME_MAX = 10 ms
+
+RIL_ALGORITHM = Q
+RIL_DISCOUNT_BETA = 0.7
+RIL_GRADIENT_STEP_SIZE = 0.3
+RIL_TRACE_DECAY = 0.2
+RIL_EXPLORE_RATIO = 0.1
+RIL_GLOBAL_REWARD_SHARE = 1
+
diff --git a/src/ats/perf_ats_solver_proportional.conf b/src/ats/perf_ats_solver_proportional.conf
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git a/src/ats/test_ats_api_delayed.conf b/src/ats/test_ats_api_delayed.conf
new file mode 100644
index 0000000000000000000000000000000000000000..3aac88cf9510cbca0408de20af948d2f0677c905
--- /dev/null
+++ b/src/ats/test_ats_api_delayed.conf
@@ -0,0 +1,36 @@
+@INLINE@ ../../contrib/conf/gnunet/no_forcestart.conf
+
+[PATHS]
+GNUNET_TEST_HOME = $GNUNET_TMP/test-ats-api-scheduling/
+
+[ats]
+PREFIX = ./test_delay -t 10 --
+# Enable MLP mode (default: NO)
+#MODE = ril
+MODE = mlp
+# Network specific inbound/outbound quotas
+# UNSPECIFIED
+UNSPECIFIED_QUOTA_IN = 64 KiB
+UNSPECIFIED_QUOTA_OUT = 64 KiB
+# LOOPBACK
+LOOPBACK_QUOTA_IN = unlimited
+LOOPBACK_QUOTA_OUT = unlimited
+# LAN
+LAN_QUOTA_IN = unlimited
+LAN_QUOTA_OUT = unlimited
+# WAN
+WAN_QUOTA_IN = 64 KiB
+WAN_QUOTA_OUT = 64 KiB
+# WLAN
+WLAN_QUOTA_IN = 512
+WLAN_QUOTA_OUT = 512
+
+# ATS extended options
+DUMP_MLP = NO
+DUMP_SOLUTION = NO
+DUMP_OVERWRITE = NO
+DUMP_MIN_PEERS = 0
+DUMP_MIN_ADDRS = 0
+DUMP_OVERWRITE = NO
+ATS_MIN_INTERVAL = 15000
+ATS_EXEC_INTERVAL = 30000
diff --git a/src/ats/test_ats_solver_default.conf b/src/ats/test_ats_solver_default.conf
new file mode 100644
index 0000000000000000000000000000000000000000..2d8927abdad8f9f0f047bac26695f8cc881d9871
--- /dev/null
+++ b/src/ats/test_ats_solver_default.conf
@@ -0,0 +1,2 @@
+@INLINE@ ../../contrib/conf/gnunet/no_forcestart.conf
+
diff --git a/src/ats/test_ats_solver_delayed_proportional.conf b/src/ats/test_ats_solver_delayed_proportional.conf
new file mode 100644
index 0000000000000000000000000000000000000000..fdfeb90b8ff16462f05301fa9286f022ec38579e
--- /dev/null
+++ b/src/ats/test_ats_solver_delayed_proportional.conf
@@ -0,0 +1,20 @@
+@INLINE@ test_ats_solver_default.conf
+
+[ats]
+PREFIX = ./test_delay -t 10 --
+MODE = proportional
+# UNSPECIFIED
+UNSPECIFIED_QUOTA_IN = 64 KiB
+UNSPECIFIED_QUOTA_OUT = 64 KiB
+# LOOPBACK
+LOOPBACK_QUOTA_IN = unlimited
+LOOPBACK_QUOTA_OUT = unlimited
+# LAN
+LAN_QUOTA_IN = unlimited
+LAN_QUOTA_OUT = unlimited
+# WAN
+WAN_QUOTA_IN = 64 KiB
+WAN_QUOTA_OUT = 64 KiB
+# WLAN
+WLAN_QUOTA_IN = 512
+WLAN_QUOTA_OUT = 512
diff --git a/src/ats/test_ats_solver_proportional.conf b/src/ats/test_ats_solver_proportional.conf
new file mode 100644
index 0000000000000000000000000000000000000000..49815134bee665effc9a0045e2a9bc380efbf953
--- /dev/null
+++ b/src/ats/test_ats_solver_proportional.conf
@@ -0,0 +1,19 @@
+@INLINE@ test_ats_solver_default.conf
+
+[ats]
+MODE = proportional
+# UNSPECIFIED
+UNSPECIFIED_QUOTA_IN = 64 KiB
+UNSPECIFIED_QUOTA_OUT = 64 KiB
+# LOOPBACK
+LOOPBACK_QUOTA_IN = unlimited
+LOOPBACK_QUOTA_OUT = unlimited
+# LAN
+LAN_QUOTA_IN = unlimited
+LAN_QUOTA_OUT = unlimited
+# WAN
+WAN_QUOTA_IN = 64 KiB
+WAN_QUOTA_OUT = 64 KiB
+# WLAN
+WLAN_QUOTA_IN = 512
+WLAN_QUOTA_OUT = 512
diff --git a/src/auction/.gitignore b/src/auction/.gitignore
new file mode 100644
index 0000000000000000000000000000000000000000..5c3ec20cb67ed40def80882469a77a221bacbd0a
--- /dev/null
+++ b/src/auction/.gitignore
@@ -0,0 +1,5 @@
+gnunet-auction-create
+gnunet-auction-info
+gnunet-auction-join
+gnunet-service-auction
+test_auction_api
diff --git a/src/cadet/.gitignore b/src/cadet/.gitignore
new file mode 100644
index 0000000000000000000000000000000000000000..b556fa4c8bc8c72b6a62282a50793c9a5044eb87
--- /dev/null
+++ b/src/cadet/.gitignore
@@ -0,0 +1,26 @@
+gnunet-service-cadet
+gnunet-cadet
+gnunet-cadet-profiler
+test_cadet_2_forward
+test_cadet_2_keepalive
+test_cadet_2_signal
+test_cadet_2_speed
+test_cadet_2_speed_ack
+test_cadet_2_speed_backwards
+test_cadet_2_speed_reliable
+test_cadet_2_speed_reliable_backwards
+test_cadet_5_forward
+test_cadet_5_keepalive
+test_cadet_5_signal
+test_cadet_5_speed
+test_cadet_5_speed_ack
+test_cadet_5_speed_backwards
+test_cadet_5_speed_reliable
+test_cadet_5_speed_reliable_backwards
+test_cadet_local
+test_cadet_single
+gnunet-service-cadet-new
+test_cadet_local_mq
+test_cadet_*_newtest_cadet_2_reopen
+test_cadet_5_reopen
+test_cadet_2_reopen
diff --git a/src/cadet/cadet.h b/src/cadet/cadet.h
index d17eab1d65e1fe3e12b6d48b9213c7def1ec1fc9..31dad41178d513af1a0de3e75b5f263e77653c81 100644
--- a/src/cadet/cadet.h
+++ b/src/cadet/cadet.h
@@ -325,7 +325,7 @@ struct GNUNET_CADET_RequestDropCadetMessage
    * Type: #GNUNET_MESSAGE_TYPE_CADET_DROP_CADET_MESSAGE
    */
   struct GNUNET_MessageHeader header;
-  
+
   /**
    * Type of the message this handler covers, in host byte order.
    */
@@ -337,7 +337,7 @@ struct GNUNET_CADET_RequestDropCadetMessage
   struct GNUNET_CADET_ClientChannelNumber ccn;
 
 };
-  
+
 /**
  * Message to inform the client about channels in the service.
  */
diff --git a/src/cadet/cadet_api.c b/src/cadet/cadet_api.c
index 67f6571c5c4535e762f68d832287b1b82779082c..45cc508a69797d5a37b75cbdabd4612e20f8fc6b 100644
--- a/src/cadet/cadet_api.c
+++ b/src/cadet/cadet_api.c
@@ -1001,8 +1001,8 @@ GNUNET_CADET_open_port (struct GNUNET_CADET_Handle *h,
   p->window_changes = window_changes;
   p->disconnects = disconnects;
   p->handlers = (NULL == pd->agpl_url)
-    ? GNUNET_MQ_copy_handlers (handlers)
-    : GNUNET_MQ_copy_handlers2 (handlers, &return_agpl, NULL);
+                ? GNUNET_MQ_copy_handlers (handlers)
+                : GNUNET_MQ_copy_handlers2 (handlers, &return_agpl, NULL);
 
   GNUNET_assert (GNUNET_OK == open_port_cb (h, &p->id, p));
   return p;
diff --git a/src/cadet/cadet_api_drop_message.c b/src/cadet/cadet_api_drop_message.c
index d9f7e003ea0c9d335a14f97fae673bd84edbb604..2b031b5c08615f96ddf06467140df6a91b2cf1cc 100644
--- a/src/cadet/cadet_api_drop_message.c
+++ b/src/cadet/cadet_api_drop_message.c
@@ -11,7 +11,7 @@
      WITHOUT ANY WARRANTY; without even the implied warranty of
      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      Affero General Public License for more details.
-    
+
      You should have received a copy of the GNU Affero General Public License
      along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
@@ -35,8 +35,8 @@
  */
 void
 GNUNET_CADET_drop_message (struct GNUNET_MQ_Handle *mq,
-			   struct GNUNET_CADET_ClientChannelNumber ccn,
-			   uint16_t type)
+                           struct GNUNET_CADET_ClientChannelNumber ccn,
+                           uint16_t type)
 {
   struct GNUNET_CADET_RequestDropCadetMessage *message;
   struct GNUNET_MQ_Envelope *env;
@@ -45,15 +45,15 @@ GNUNET_CADET_drop_message (struct GNUNET_MQ_Handle *mq,
 
   message->ccn = ccn;
   message->type = type;
-  
+
   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
-              "Dropping message for channel of type %s (%d)\n", type == GNUNET_MESSAGE_TYPE_CADET_CHANNEL_DESTROY ? "GNUNET_MESSAGE_TYPE_CADET_CHANNEL_DESTROY" : "UNKNOWN", type);
+              "Dropping message for channel of type %s (%d)\n", type ==
+              GNUNET_MESSAGE_TYPE_CADET_CHANNEL_DESTROY ?
+              "GNUNET_MESSAGE_TYPE_CADET_CHANNEL_DESTROY" : "UNKNOWN", type);
 
   GNUNET_MQ_send (mq, env);
-  
-}
-
 
+}
 
 
 /* end of cadet_api_drop_message.c */
diff --git a/src/cadet/cadet_protocol.h b/src/cadet/cadet_protocol.h
index 08298e2240c4f06e0b3bb669d908ec5b5bf9599d..117a7922e3f643de3c995da7d4e92d60d816d89d 100644
--- a/src/cadet/cadet_protocol.h
+++ b/src/cadet/cadet_protocol.h
@@ -85,11 +85,11 @@ struct GNUNET_CADET_ConnectionCreateMessage
   uint32_t options GNUNET_PACKED;
 
   /**
-   * This flag indicates the peer sending the connection create 
+   * This flag indicates the peer sending the connection create
    * meassage likes to trigger a KX handshake.
    */
   int has_monotime;
-  
+
   /**
    *  This monotonic time is set, if a peer likes to trigger a KX, but is not
    *  the peer that should start the KX. (xrs,t3ss)
diff --git a/src/cadet/desirability_table.c b/src/cadet/desirability_table.c
new file mode 100644
index 0000000000000000000000000000000000000000..829c618af9408a1f68ec06deb5db0ea2c581426e
--- /dev/null
+++ b/src/cadet/desirability_table.c
@@ -0,0 +1,33 @@
+/* This file is in the public domain. */
+
+/**
+ * @brief Program to simulate results from #GCP_get_desirability_of_path()
+ * for various plausible inputs.
+ * @author Christian Grothoff
+ */
+#include <stdio.h>
+
+int
+main ()
+{
+  for (unsigned int num_alts = 1; num_alts < 10; num_alts++)
+    for (unsigned int off = 0; off < 10; off++)
+      for (double delta = -(int) off; delta <= 5; delta += 0.25)
+      {
+        double weight_alts;
+
+        if (delta <= -1.0)
+          weight_alts = -1.0 * num_alts / delta;   /* discount alternative paths */
+        else if (delta >= 1.0)
+          weight_alts = 1.0 * num_alts * delta;   /* overcount alternative paths */
+        else
+          weight_alts = 1.0 * num_alts;   /* count alternative paths normally */
+
+        fprintf (stderr,
+                 "Paths: %u  Offset: %u  Delta: %5.2f  SCORE: %f\n",
+                 num_alts,
+                 off,
+                 delta,
+                 ((off + 1.0) / (weight_alts * weight_alts)));
+      }
+}
diff --git a/src/cadet/gnunet-cadet-profiler.c b/src/cadet/gnunet-cadet-profiler.c
new file mode 100644
index 0000000000000000000000000000000000000000..c3a19a399d52f1016e692e253126b07eeb52eeb4
--- /dev/null
+++ b/src/cadet/gnunet-cadet-profiler.c
@@ -0,0 +1,1159 @@
+/*
+     This file is part of GNUnet.
+     Copyright (C) 2011 GNUnet e.V.
+
+     GNUnet is free software: you can redistribute it and/or modify it
+     under the terms of the GNU Affero General Public License as published
+     by the Free Software Foundation, either version 3 of the License,
+     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
+     Affero General Public License for more details.
+
+     You should have received a copy of the GNU Affero General Public License
+     along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+     SPDX-License-Identifier: AGPL3.0-or-later
+ */
+/**
+ * @file cadet/gnunet-cadet-profiler.c
+ *
+ * @brief Profiler for cadet experiments.
+ */
+#include <stdio.h>
+#include "platform.h"
+#include "cadet_test_lib.h"
+#include "gnunet_cadet_service.h"
+#include "gnunet_statistics_service.h"
+
+
+#define PING 1
+#define PONG 2
+
+
+/**
+ * Paximum ping period in milliseconds. Real period = rand (0, PING_PERIOD)
+ */
+#define PING_PERIOD 500
+
+/**
+ * How long until we give up on connecting the peers?
+ */
+#define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 120)
+
+/**
+ * Time to wait for stuff that should be rather fast
+ */
+#define SHORT_TIME GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 300)
+
+/**
+ * Total number of rounds.
+ */
+#define number_rounds sizeof(rounds) / sizeof(rounds[0])
+
+/**
+ * Ratio of peers active. First round always is 1.0.
+ */
+static float rounds[] = { 0.8, 0.6, 0.8, 0.5, 0.3, 0.8, 0.0 };
+
+/**
+ * Message type for pings.
+ */
+struct CadetPingMessage
+{
+  /**
+   * Header. Type PING/PONG.
+   */
+  struct GNUNET_MessageHeader header;
+
+  /**
+   * Message number.
+   */
+  uint32_t counter;
+
+  /**
+   * Time the message was sent.
+   */
+  struct GNUNET_TIME_AbsoluteNBO timestamp;
+
+  /**
+   * Round number.
+   */
+  uint32_t round_number;
+};
+
+/**
+ * Peer description.
+ */
+struct CadetPeer
+{
+  /**
+   * Testbed Operation (to get peer id, etc).
+   */
+  struct GNUNET_TESTBED_Operation *op;
+
+  /**
+   * Peer ID.
+   */
+  struct GNUNET_PeerIdentity id;
+
+  /**
+   * Cadet handle for the root peer
+   */
+  struct GNUNET_CADET_Handle *cadet;
+
+  /**
+   * Channel handle for the root peer
+   */
+  struct GNUNET_CADET_Channel *ch;
+
+  /**
+   * Channel handle for the dest peer
+   */
+  struct GNUNET_CADET_Channel *incoming_ch;
+
+  /**
+   * Channel handle for a warmup channel.
+   */
+  struct GNUNET_CADET_Channel *warmup_ch;
+
+  /**
+   * Number of payload packes sent
+   */
+  int data_sent;
+
+  /**
+   * Number of payload packets received
+   */
+  int data_received;
+
+  /**
+   * Is peer up?
+   */
+  int up;
+
+  /**
+   * Destinaton to ping.
+   */
+  struct CadetPeer *dest;
+
+  /**
+   * Incoming channel for pings.
+   */
+  struct CadetPeer *incoming;
+
+  /**
+   * Task to do the next ping.
+   */
+  struct GNUNET_SCHEDULER_Task *ping_task;
+
+  /**
+   * NTR operation for the next ping.
+   */
+  struct GNUNET_CADET_TransmitHandle *ping_ntr;
+
+  float mean[number_rounds];
+  float var[number_rounds];
+  unsigned int pongs[number_rounds];
+  unsigned int pings[number_rounds];
+};
+
+/**
+ * Duration of each round.
+ */
+static struct GNUNET_TIME_Relative round_time;
+
+/**
+ * GNUNET_PeerIdentity -> CadetPeer
+ */
+static struct GNUNET_CONTAINER_MultiPeerMap *ids;
+
+/**
+ * Testbed peer handles.
+ */
+static struct GNUNET_TESTBED_Peer **testbed_handles;
+
+/**
+ * Testbed Operation (to get stats).
+ */
+static struct GNUNET_TESTBED_Operation *stats_op;
+
+/**
+ * Operation to get peer ids.
+ */
+static struct CadetPeer *peers;
+
+/**
+ * Peer ids counter.
+ */
+static unsigned int p_ids;
+
+/**
+ * Total number of peers.
+ */
+static unsigned long long peers_total;
+
+/**
+ * Number of currently running peers.
+ */
+static unsigned long long peers_running;
+
+/**
+ * Number of peers doing pings.
+ */
+static unsigned long long peers_pinging;
+
+/**
+ * Test context (to shut down).
+ */
+static struct GNUNET_CADET_TEST_Context *test_ctx;
+
+/**
+ * Task called to disconnect peers, before shutdown.
+ */
+static struct GNUNET_SCHEDULER_Task *disconnect_task;
+
+/**
+ * Task to perform tests
+ */
+static struct GNUNET_SCHEDULER_Task *test_task;
+
+/**
+ * Round number.
+ */
+static unsigned int current_round;
+
+/**
+ * Do preconnect? (Each peer creates a tunnel to one other peer).
+ */
+static int do_warmup;
+
+/**
+ * Warmup progress.
+ */
+static unsigned int peers_warmup;
+
+/**
+ * Flag to notify callbacks not to generate any new traffic anymore.
+ */
+static int test_finished;
+
+/**
+ * Task running each round of the benchmark.
+ */
+static struct GNUNET_SCHEDULER_Task *round_task;
+
+
+/**
+ * START THE TEST ITSELF, AS WE ARE CONNECTED TO THE CADET SERVICES.
+ *
+ * Testcase continues when the root receives confirmation of connected peers,
+ * on callback funtion ch.
+ *
+ * @param cls Closure (unsued).
+ */
+static void
+start_test (void *cls);
+
+
+/**
+ * Calculate a random delay.
+ *
+ * @param max Exclusive maximum, in ms.
+ *
+ * @return A time between 0 a max-1 ms.
+ */
+static struct GNUNET_TIME_Relative
+delay_ms_rnd (unsigned int max)
+{
+  unsigned int rnd;
+
+  rnd = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, max);
+  return GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MILLISECONDS, rnd);
+}
+
+
+/**
+ * Get the index of a peer in the peers array.
+ *
+ * @param peer Peer whose index to get.
+ *
+ * @return Index of peer in peers.
+ */
+static unsigned int
+get_index (struct CadetPeer *peer)
+{
+  return peer - peers;
+}
+
+
+/**
+ * Show the results of the test (banwidth acheived) and log them to GAUGER
+ */
+static void
+show_end_data (void)
+{
+  struct CadetPeer *peer;
+  unsigned int i;
+  unsigned int j;
+
+  for (i = 0; i < number_rounds; i++)
+  {
+    for (j = 0; j < peers_pinging; j++)
+    {
+      peer = &peers[j];
+      fprintf (stdout,
+               "ROUND %3u PEER %3u: %10.2f / %10.2f, PINGS: %3u, PONGS: %3u\n",
+               i, j, peer->mean[i], sqrt (peer->var[i] / (peer->pongs[i] - 1)),
+               peer->pings[i], peer->pongs[i]);
+    }
+  }
+}
+
+
+/**
+ * Disconnect from cadet services af all peers, call shutdown.
+ *
+ * @param cls Closure (unused).
+ */
+static void
+disconnect_cadet_peers (void *cls)
+{
+  long line = (long) cls;
+  unsigned int i;
+
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "disconnecting cadet service, called from line %ld\n",
+              line);
+  disconnect_task = NULL;
+  for (i = 0; i < peers_total; i++)
+  {
+    if (NULL != peers[i].op)
+      GNUNET_TESTBED_operation_done (peers[i].op);
+
+    if (peers[i].up != GNUNET_YES)
+      continue;
+
+    if (NULL != peers[i].ch)
+    {
+      GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+                  "%u: channel %p\n", i, peers[i].ch);
+      GNUNET_CADET_channel_destroy (peers[i].ch);
+    }
+    if (NULL != peers[i].warmup_ch)
+    {
+      GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+                  "%u: warmup channel %p\n",
+                  i, peers[i].warmup_ch);
+      GNUNET_CADET_channel_destroy (peers[i].warmup_ch);
+    }
+    if (NULL != peers[i].incoming_ch)
+    {
+      GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+                  "%u: incoming channel %p\n",
+                  i, peers[i].incoming_ch);
+      GNUNET_CADET_channel_destroy (peers[i].incoming_ch);
+    }
+  }
+  GNUNET_CADET_TEST_cleanup (test_ctx);
+  GNUNET_SCHEDULER_shutdown ();
+}
+
+
+/**
+ * Shut down peergroup, clean up.
+ *
+ * @param cls Closure (unused).
+ */
+static void
+shutdown_task (void *cls)
+{
+  GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+              "Ending test.\n");
+  if (NULL != disconnect_task)
+  {
+    GNUNET_SCHEDULER_cancel (disconnect_task);
+    disconnect_task = GNUNET_SCHEDULER_add_now (&disconnect_cadet_peers,
+                                                (void *) __LINE__);
+  }
+  if (NULL != round_task)
+  {
+    GNUNET_SCHEDULER_cancel (round_task);
+    round_task = NULL;
+  }
+  if (NULL != test_task)
+  {
+    GNUNET_SCHEDULER_cancel (test_task);
+    test_task = NULL;
+  }
+}
+
+
+/**
+ * Finish test normally: schedule disconnect and shutdown
+ *
+ * @param line Line in the code the abort is requested from (__LINE__).
+ */
+static void
+abort_test (long line)
+{
+  if (disconnect_task != NULL)
+  {
+    GNUNET_SCHEDULER_cancel (disconnect_task);
+    disconnect_task = GNUNET_SCHEDULER_add_now (&disconnect_cadet_peers,
+                                                (void *) line);
+  }
+}
+
+
+/**
+ * Stats callback. Finish the stats testbed operation and when all stats have
+ * been iterated, shutdown the test.
+ *
+ * @param cls closure
+ * @param op the operation that has been finished
+ * @param emsg error message in case the operation has failed; will be NULL if
+ *          operation has executed successfully.
+ */
+static void
+stats_cont (void *cls, struct GNUNET_TESTBED_Operation *op, const char *emsg)
+{
+  GNUNET_log (GNUNET_ERROR_TYPE_INFO, "... collecting statistics done.\n");
+  GNUNET_TESTBED_operation_done (stats_op);
+
+  if (NULL != disconnect_task)
+    GNUNET_SCHEDULER_cancel (disconnect_task);
+  disconnect_task = GNUNET_SCHEDULER_add_now (&disconnect_cadet_peers,
+                                              (void *) __LINE__);
+}
+
+
+/**
+ * Process statistic values.
+ *
+ * @param cls closure
+ * @param peer the peer the statistic belong to
+ * @param subsystem name of subsystem that created the statistic
+ * @param name the name of the datum
+ * @param value the current value
+ * @param is_persistent #GNUNET_YES if the value is persistent, #GNUNET_NO if not
+ * @return #GNUNET_OK to continue, #GNUNET_SYSERR to abort iteration
+ */
+static int
+stats_iterator (void *cls,
+                const struct GNUNET_TESTBED_Peer *peer,
+                const char *subsystem,
+                const char *name,
+                uint64_t value,
+                int is_persistent)
+{
+  uint32_t i;
+
+  i = GNUNET_TESTBED_get_index (peer);
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              " STATS %u - %s [%s]: %llu\n",
+              i, subsystem, name,
+              (unsigned long long) value);
+
+  return GNUNET_OK;
+}
+
+
+/**
+ * Task check that keepalives were sent and received.
+ *
+ * @param cls Closure (NULL).
+ */
+static void
+collect_stats (void *cls)
+{
+  GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+              "Start collecting statistics...\n");
+  stats_op = GNUNET_TESTBED_get_statistics (peers_total,
+                                            testbed_handles,
+                                            NULL, NULL,
+                                            &stats_iterator,
+                                            &stats_cont, NULL);
+}
+
+
+/**
+ * @brief Finish profiler normally. Signal finish and start collecting stats.
+ *
+ * @param cls Closure (unused).
+ */
+static void
+finish_profiler (void *cls)
+{
+  test_finished = GNUNET_YES;
+  show_end_data ();
+  GNUNET_SCHEDULER_add_now (&collect_stats, NULL);
+}
+
+
+/**
+ * Set the total number of running peers.
+ *
+ * @param target Desired number of running peers.
+ */
+static void
+adjust_running_peers (unsigned int target)
+{
+  struct GNUNET_TESTBED_Operation *op;
+  unsigned int delta;
+  unsigned int run;
+  unsigned int i;
+  unsigned int r;
+
+  GNUNET_assert (target <= peers_total);
+
+  GNUNET_log (GNUNET_ERROR_TYPE_INFO, "adjust peers to %u\n", target);
+  if (target > peers_running)
+  {
+    delta = target - peers_running;
+    run = GNUNET_YES;
+  }
+  else
+  {
+    delta = peers_running - target;
+    run = GNUNET_NO;
+  }
+
+  for (i = 0; i < delta; i++)
+  {
+    do
+    {
+      r = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK,
+                                    peers_total - peers_pinging);
+      r += peers_pinging;
+    }
+    while (peers[r].up == run || NULL != peers[r].incoming);
+    GNUNET_log (GNUNET_ERROR_TYPE_INFO, "St%s peer %u: %s\n",
+                run ? "arting" : "opping", r, GNUNET_i2s (&peers[r].id));
+
+    if (NULL != peers[r].ping_task)
+    {
+      GNUNET_SCHEDULER_cancel (peers[r].ping_task);
+      peers[r].ping_task = NULL;
+    }
+    if (NULL != peers[r].ping_ntr)
+    {
+      GNUNET_CADET_notify_transmit_ready_cancel (peers[r].ping_ntr);
+      peers[r].ping_ntr = NULL;
+    }
+    peers[r].up = run;
+
+    if (NULL != peers[r].ch)
+      GNUNET_CADET_channel_destroy (peers[r].ch);
+    peers[r].ch = NULL;
+    if (NULL != peers[r].dest)
+    {
+      if (NULL != peers[r].dest->incoming_ch)
+        GNUNET_CADET_channel_destroy (peers[r].dest->incoming_ch);
+      peers[r].dest->incoming_ch = NULL;
+    }
+
+    op = GNUNET_TESTBED_peer_manage_service (&peers[r], testbed_handles[r],
+                                             "cadet", NULL, NULL, run);
+    GNUNET_break (NULL != op);
+    peers_running += run ? 1 : -1;
+    GNUNET_assert (peers_running > 0);
+  }
+}
+
+
+/**
+ * @brief Move to next round.
+ *
+ * @param cls Closure (round #).
+ */
+static void
+next_rnd (void *cls)
+{
+  GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+              "ROUND %u\n",
+              current_round);
+  if (0.0 == rounds[current_round])
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Finishing\n");
+    GNUNET_SCHEDULER_add_now (&finish_profiler, NULL);
+    return;
+  }
+  adjust_running_peers (rounds[current_round] * peers_total);
+  current_round++;
+
+  round_task = GNUNET_SCHEDULER_add_delayed (round_time,
+                                             &next_rnd,
+                                             NULL);
+}
+
+
+/**
+ * Transmit ping callback.
+ *
+ * @param cls Closure (peer for PING, NULL for PONG).
+ * @param size Size of the tranmist buffer.
+ * @param buf Pointer to the beginning of the buffer.
+ *
+ * @return Number of bytes written to buf.
+ */
+static size_t
+tmt_rdy_ping (void *cls, size_t size, void *buf);
+
+
+/**
+ * Transmit pong callback.
+ *
+ * @param cls Closure (copy of PING message, to be freed).
+ * @param size Size of the buffer we have.
+ * @param buf Buffer to copy data to.
+ */
+static size_t
+tmt_rdy_pong (void *cls, size_t size, void *buf)
+{
+  struct CadetPingMessage *ping = cls;
+  struct CadetPingMessage *pong;
+
+  if ((0 == size) || (NULL == buf))
+  {
+    GNUNET_free (ping);
+    return 0;
+  }
+  pong = (struct CadetPingMessage *) buf;
+  GNUNET_memcpy (pong, ping, sizeof(*ping));
+  pong->header.type = htons (PONG);
+
+  GNUNET_free (ping);
+  return sizeof(*ping);
+}
+
+
+/**
+ * @brief Send a ping to destination
+ *
+ * @param cls Closure (peer).
+ */
+static void
+ping (void *cls)
+{
+  struct CadetPeer *peer = cls;
+
+  peer->ping_task = NULL;
+  if (GNUNET_YES == test_finished)
+    return;
+  GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+              "%u -> %u (%u)\n",
+              get_index (peer),
+              get_index (peer->dest),
+              peer->data_sent);
+  peer->ping_ntr = GNUNET_CADET_notify_transmit_ready (peer->ch, GNUNET_NO,
+                                                       GNUNET_TIME_UNIT_FOREVER_REL,
+                                                       sizeof(struct
+                                                              CadetPingMessage),
+                                                       &tmt_rdy_ping, peer);
+}
+
+
+/**
+ * @brief Reply with a pong to origin.
+ *
+ * @param cls Closure (peer).
+ * @param tc Task context.
+ */
+static void
+pong (struct GNUNET_CADET_Channel *channel,
+      const struct CadetPingMessage *ping)
+{
+  struct CadetPingMessage *copy;
+
+  copy = GNUNET_new (struct CadetPingMessage);
+  *copy = *ping;
+  GNUNET_CADET_notify_transmit_ready (channel, GNUNET_NO,
+                                      GNUNET_TIME_UNIT_FOREVER_REL,
+                                      sizeof(struct CadetPingMessage),
+                                      &tmt_rdy_pong, copy);
+}
+
+
+/**
+ * Transmit ping callback
+ *
+ * @param cls Closure (peer).
+ * @param size Size of the buffer we have.
+ * @param buf Buffer to copy data to.
+ */
+static size_t
+tmt_rdy_ping (void *cls, size_t size, void *buf)
+{
+  struct CadetPeer *peer = cls;
+  struct CadetPingMessage *msg = buf;
+
+  peer->ping_ntr = NULL;
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "tmt_rdy called, filling buffer\n");
+  if ((size < sizeof(struct CadetPingMessage)) || (NULL == buf))
+  {
+    GNUNET_break (GNUNET_YES == test_finished);
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                "size %u, buf %p, data_sent %u, data_received %u\n",
+                (unsigned int) size,
+                buf,
+                peer->data_sent,
+                peer->data_received);
+
+    return 0;
+  }
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "Sending: msg %d\n",
+              peer->data_sent);
+  msg->header.size = htons (size);
+  msg->header.type = htons (PING);
+  msg->counter = htonl (peer->data_sent++);
+  msg->round_number = htonl (current_round);
+  msg->timestamp = GNUNET_TIME_absolute_hton (GNUNET_TIME_absolute_get ());
+  peer->pings[current_round]++;
+  peer->ping_task = GNUNET_SCHEDULER_add_delayed (delay_ms_rnd (PING_PERIOD),
+                                                  &ping, peer);
+
+  return sizeof(struct CadetPingMessage);
+}
+
+
+/**
+ * Function is called whenever a PING message is received.
+ *
+ * @param cls closure (peer #, set from GNUNET_CADET_connect)
+ * @param channel connection to the other end
+ * @param channel_ctx place to store local state associated with the channel
+ * @param message the actual message
+ * @return GNUNET_OK to keep the connection open,
+ *         GNUNET_SYSERR to close it (signal serious error)
+ */
+int
+ping_handler (void *cls, struct GNUNET_CADET_Channel *channel,
+              void **channel_ctx,
+              const struct GNUNET_MessageHeader *message)
+{
+  long n = (long) cls;
+
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "%u got PING\n",
+              (unsigned int) n);
+  GNUNET_CADET_receive_done (channel);
+  if (GNUNET_NO == test_finished)
+    pong (channel, (struct CadetPingMessage *) message);
+
+  return GNUNET_OK;
+}
+
+
+/**
+ * Function is called whenever a PONG message is received.
+ *
+ * @param cls closure (peer #, set from GNUNET_CADET_connect)
+ * @param channel connection to the other end
+ * @param channel_ctx place to store local state associated with the channel
+ * @param message the actual message
+ * @return GNUNET_OK to keep the connection open,
+ *         GNUNET_SYSERR to close it (signal serious error)
+ */
+int
+pong_handler (void *cls, struct GNUNET_CADET_Channel *channel,
+              void **channel_ctx,
+              const struct GNUNET_MessageHeader *message)
+{
+  long n = (long) cls;
+  struct CadetPeer *peer;
+  struct CadetPingMessage *msg;
+  struct GNUNET_TIME_Absolute send_time;
+  struct GNUNET_TIME_Relative latency;
+  unsigned int r /* Ping round */;
+  float delta;
+
+  GNUNET_CADET_receive_done (channel);
+  peer = &peers[n];
+
+  msg = (struct CadetPingMessage *) message;
+
+  send_time = GNUNET_TIME_absolute_ntoh (msg->timestamp);
+  latency = GNUNET_TIME_absolute_get_duration (send_time);
+  r = ntohl (msg->round_number);
+  GNUNET_log (GNUNET_ERROR_TYPE_INFO, "%u <- %u (%u) latency: %s\n",
+              get_index (peer),
+              get_index (peer->dest),
+              (uint32_t) ntohl (msg->counter),
+              GNUNET_STRINGS_relative_time_to_string (latency, GNUNET_NO));
+
+  /* Online variance calculation */
+  peer->pongs[r]++;
+  delta = latency.rel_value_us - peer->mean[r];
+  peer->mean[r] = peer->mean[r] + delta / peer->pongs[r];
+  peer->var[r] += delta * (latency.rel_value_us - peer->mean[r]);
+
+  return GNUNET_OK;
+}
+
+
+/**
+ * Handlers, for diverse services
+ */
+static struct GNUNET_CADET_MessageHandler handlers[] = {
+  { &ping_handler, PING, sizeof(struct CadetPingMessage) },
+  { &pong_handler, PONG, sizeof(struct CadetPingMessage) },
+  { NULL, 0, 0 }
+};
+
+
+/**
+ * Method called whenever another peer has added us to a channel
+ * the other peer initiated.
+ *
+ * @param cls Closure.
+ * @param channel New handle to the channel.
+ * @param initiator Peer that started the channel.
+ * @param port Port this channel is connected to.
+ * @param options channel option flags
+ * @return Initial channel context for the channel
+ *         (can be NULL -- that's not an error).
+ */
+static void *
+incoming_channel (void *cls, struct GNUNET_CADET_Channel *channel,
+                  const struct GNUNET_PeerIdentity *initiator,
+                  const struct GNUNET_HashCode *port,
+                  enum GNUNET_CADET_ChannelOption options)
+{
+  long n = (long) cls;
+  struct CadetPeer *peer;
+
+  peer = GNUNET_CONTAINER_multipeermap_get (ids, initiator);
+  GNUNET_assert (NULL != peer);
+  if (NULL == peers[n].incoming)
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+                "WARMUP %3u: %u <= %u\n",
+                peers_warmup,
+                (unsigned int) n,
+                get_index (peer));
+    peers_warmup++;
+    if (peers_warmup < peers_total)
+      return NULL;
+    if (NULL != test_task)
+    {
+      GNUNET_SCHEDULER_cancel (test_task);
+      test_task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_SECONDS,
+                                                &start_test, NULL);
+    }
+    return NULL;
+  }
+  GNUNET_assert (peer == peers[n].incoming);
+  GNUNET_assert (peer->dest == &peers[n]);
+  GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+              "%u <= %u %p\n",
+              (unsigned int) n,
+              get_index (peer),
+              channel);
+  peers[n].incoming_ch = channel;
+
+  return NULL;
+}
+
+
+/**
+ * Function called whenever an inbound channel is destroyed.  Should clean up
+ * any associated state.
+ *
+ * @param cls closure (set from GNUNET_CADET_connect)
+ * @param channel connection to the other end (henceforth invalid)
+ * @param channel_ctx place where local state associated
+ *                   with the channel is stored
+ */
+static void
+channel_cleaner (void *cls,
+                 const struct GNUNET_CADET_Channel *channel,
+                 void *channel_ctx)
+{
+  long n = (long) cls;
+  struct CadetPeer *peer = &peers[n];
+
+  GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+              "Channel %p disconnected at peer %ld\n", channel, n);
+  if (peer->ch == channel)
+    peer->ch = NULL;
+}
+
+
+/**
+ * Select a random peer that has no incoming channel
+ *
+ * @param peer ID of the peer connecting. NULL if irrelevant (warmup).
+ *
+ * @return Random peer not yet connected to.
+ */
+static struct CadetPeer *
+select_random_peer (struct CadetPeer *peer)
+{
+  unsigned int r;
+
+  do
+  {
+    r = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, peers_total);
+  }
+  while (NULL != peers[r].incoming);
+  peers[r].incoming = peer;
+
+  return &peers[r];
+}
+
+
+/**
+ * START THE TEST ITSELF, AS WE ARE CONNECTED TO THE CADET SERVICES.
+ *
+ * Testcase continues when the root receives confirmation of connected peers,
+ * on callback funtion ch.
+ *
+ * @param cls Closure (unsued).
+ */
+static void
+start_test (void *cls)
+{
+  unsigned long i;
+
+  test_task = NULL;
+  GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Start profiler\n");
+
+
+  for (i = 0; i < peers_pinging; i++)
+  {
+    peers[i].dest = select_random_peer (&peers[i]);
+    peers[i].ch = GNUNET_CADET_channel_create (peers[i].cadet, NULL,
+                                               &peers[i].dest->id,
+                                               GC_u2h (1));
+    if (NULL == peers[i].ch)
+    {
+      GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Channel %lu failed\n", i);
+      GNUNET_CADET_TEST_cleanup (test_ctx);
+      return;
+    }
+    GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+                "%lu => %u %p\n",
+                i,
+                get_index (peers[i].dest),
+                peers[i].ch);
+    peers[i].ping_task = GNUNET_SCHEDULER_add_delayed (delay_ms_rnd (2000),
+                                                       &ping, &peers[i]);
+  }
+  peers_running = peers_total;
+  if (NULL != disconnect_task)
+    GNUNET_SCHEDULER_cancel (disconnect_task);
+  disconnect_task =
+    GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply (round_time,
+                                                                 number_rounds
+                                                                 + 1),
+                                  &disconnect_cadet_peers,
+                                  (void *) __LINE__);
+  round_task = GNUNET_SCHEDULER_add_delayed (round_time,
+                                             &next_rnd,
+                                             NULL);
+}
+
+
+/**
+ * Do warmup: create some channels to spread information about the topology.
+ */
+static void
+warmup (void)
+{
+  struct CadetPeer *peer;
+  unsigned int i;
+
+  for (i = 0; i < peers_total; i++)
+  {
+    peer = select_random_peer (NULL);
+    GNUNET_log (GNUNET_ERROR_TYPE_INFO, "WARMUP %u => %u\n",
+                i, get_index (peer));
+    peers[i].warmup_ch =
+      GNUNET_CADET_channel_create (peers[i].cadet, NULL, &peer->id,
+                                   GC_u2h (1));
+    if (NULL == peers[i].warmup_ch)
+    {
+      GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Warmup %u failed\n", i);
+      GNUNET_CADET_TEST_cleanup (test_ctx);
+      return;
+    }
+  }
+}
+
+
+/**
+ * Callback to be called when the requested peer information is available
+ *
+ * @param cls the closure from GNUNET_TESTBED_peer_get_information()
+ * @param op the operation this callback corresponds to
+ * @param pinfo the result; will be NULL if the operation has failed
+ * @param emsg error message if the operation has failed;
+ *             NULL if the operation is successfull
+ */
+static void
+peer_id_cb (void *cls,
+            struct GNUNET_TESTBED_Operation *op,
+            const struct GNUNET_TESTBED_PeerInformation *pinfo,
+            const char *emsg)
+{
+  long n = (long) cls;
+
+  if ((NULL == pinfo) || (NULL != emsg))
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "pi_cb: %s\n", emsg);
+    abort_test (__LINE__);
+    return;
+  }
+  peers[n].id = *(pinfo->result.id);
+  GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+              "%ld  id: %s\n",
+              n,
+              GNUNET_i2s (&peers[n].id));
+  GNUNET_break (GNUNET_OK ==
+                GNUNET_CONTAINER_multipeermap_put (ids, &peers[n].id, &peers[n],
+                                                   GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST));
+
+  GNUNET_TESTBED_operation_done (peers[n].op);
+  peers[n].op = NULL;
+
+  p_ids++;
+  if (p_ids < peers_total)
+    return;
+  GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Got all IDs, starting profiler\n");
+  if (do_warmup)
+  {
+    struct GNUNET_TIME_Relative delay;
+
+    warmup ();
+    delay = GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MILLISECONDS,
+                                           100 * peers_total);
+    test_task = GNUNET_SCHEDULER_add_delayed (delay, &start_test, NULL);
+    return;   /* start_test from incoming_channel */
+  }
+  GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Starting in a second...\n");
+  test_task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_SECONDS,
+                                            &start_test, NULL);
+}
+
+
+/**
+ * test main: start test when all peers are connected
+ *
+ * @param cls Closure.
+ * @param ctx Argument to give to GNUNET_CADET_TEST_cleanup on test end.
+ * @param num_peers Number of peers that are running.
+ * @param testbed_peers Array of peers.
+ * @param cadetes Handle to each of the CADETs of the peers.
+ */
+static void
+tmain (void *cls,
+       struct GNUNET_CADET_TEST_Context *ctx,
+       unsigned int num_peers,
+       struct GNUNET_TESTBED_Peer **testbed_peers,
+       struct GNUNET_CADET_Handle **cadetes)
+{
+  unsigned long i;
+
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "test main\n");
+  test_ctx = ctx;
+  GNUNET_assert (peers_total == num_peers);
+  peers_running = num_peers;
+  testbed_handles = testbed_peers;
+  disconnect_task = GNUNET_SCHEDULER_add_delayed (SHORT_TIME,
+                                                  &disconnect_cadet_peers,
+                                                  (void *) __LINE__);
+  GNUNET_SCHEDULER_add_shutdown (&shutdown_task, NULL);
+  for (i = 0; i < peers_total; i++)
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                "requesting id %ld\n",
+                i);
+    peers[i].up = GNUNET_YES;
+    peers[i].cadet = cadetes[i];
+    peers[i].op =
+      GNUNET_TESTBED_peer_get_information (testbed_handles[i],
+                                           GNUNET_TESTBED_PIT_IDENTITY,
+                                           &peer_id_cb, (void *) i);
+  }
+  GNUNET_log (GNUNET_ERROR_TYPE_INFO, "requested peer ids\n");
+  /* Continues from pi_cb -> do_test */
+}
+
+
+/**
+ * Main: start profiler.
+ */
+int
+main (int argc, char *argv[])
+{
+  static const struct GNUNET_HashCode *ports[2];
+  const char *config_file;
+
+  config_file = ".profiler.conf";
+
+  if (4 > argc)
+  {
+    fprintf (stderr,
+             "usage: %s ROUND_TIME PEERS PINGS [DO_WARMUP]\n",
+             argv[0]);
+    fprintf (stderr,
+             "example: %s 30s 16 1 Y\n",
+             argv[0]);
+    return 1;
+  }
+
+  if (GNUNET_OK !=
+      GNUNET_STRINGS_fancy_time_to_relative (argv[1],
+                                             &round_time))
+  {
+    fprintf (stderr,
+             "%s is not a valid time\n",
+             argv[1]);
+    return 1;
+  }
+
+  peers_total = atoll (argv[2]);
+  if (2 > peers_total)
+  {
+    fprintf (stderr,
+             "%s peers is not valid (> 2)\n",
+             argv[1]);
+    return 1;
+  }
+  peers = GNUNET_new_array (peers_total,
+                            struct CadetPeer);
+  peers_pinging = atoll (argv[3]);
+
+  if (peers_total < 2 * peers_pinging)
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                "not enough peers, total should be > 2 * peers_pinging\n");
+    return 1;
+  }
+
+  do_warmup = (5 > argc || argv[4][0] != 'N');
+
+  ids = GNUNET_CONTAINER_multipeermap_create (2 * peers_total,
+                                              GNUNET_YES);
+  GNUNET_assert (NULL != ids);
+  p_ids = 0;
+  test_finished = GNUNET_NO;
+  ports[0] = GC_u2h (1);
+  ports[1] = 0;
+  GNUNET_CADET_TEST_run ("cadet-profiler", config_file, peers_total,
+                         &tmain, NULL, /* tmain cls */
+                         &incoming_channel, &channel_cleaner,
+                         handlers, ports);
+  GNUNET_free (peers);
+
+  return 0;
+}
+
+
+/* end of gnunet-cadet-profiler.c */
diff --git a/src/cadet/gnunet-service-cadet.c b/src/cadet/gnunet-service-cadet.c
index f3767fb019ab2d68bae2f3c13f3efbd3bc1ed25a..2d3b548dd80337a3433f29a6723017123d80e19c 100644
--- a/src/cadet/gnunet-service-cadet.c
+++ b/src/cadet/gnunet-service-cadet.c
@@ -1010,6 +1010,7 @@ handle_info_tunnels (void *cls,
   GNUNET_SERVICE_client_continue (c->client);
 }
 
+
 /**
  * Handler for client's #GNUNET_MESSAGE_TYPE_CADET_DROP_CADET_MESSAGE request.
  *
@@ -1026,11 +1027,12 @@ handle_drop_message (void *cls,
   ch = lookup_channel (c,
                        message->ccn);
 
-  GCCH_assign_type_to_drop(ch, message);
-  
+  GCCH_assign_type_to_drop (ch, message);
+
   GNUNET_SERVICE_client_continue (c->client);
 }
 
+
 /**
  * Callback called when a client connects to the service.
  *
@@ -1327,52 +1329,52 @@ run (void *cls,
  * Define "main" method using service macro.
  */
 GNUNET_SERVICE_MAIN
-("cadet",
- GNUNET_SERVICE_OPTION_NONE,
- &run,
- &client_connect_cb,
- &client_disconnect_cb,
- NULL,
- GNUNET_MQ_hd_fixed_size (port_open,
-                          GNUNET_MESSAGE_TYPE_CADET_LOCAL_PORT_OPEN,
-                          struct GNUNET_CADET_PortMessage,
-                          NULL),
- GNUNET_MQ_hd_fixed_size (port_close,
-                          GNUNET_MESSAGE_TYPE_CADET_LOCAL_PORT_CLOSE,
-                          struct GNUNET_CADET_PortMessage,
-                          NULL),
- GNUNET_MQ_hd_fixed_size (channel_create,
-                          GNUNET_MESSAGE_TYPE_CADET_LOCAL_CHANNEL_CREATE,
-                          struct GNUNET_CADET_LocalChannelCreateMessage,
-                          NULL),
- GNUNET_MQ_hd_fixed_size (channel_destroy,
-                          GNUNET_MESSAGE_TYPE_CADET_LOCAL_CHANNEL_DESTROY,
-                          struct GNUNET_CADET_LocalChannelDestroyMessage,
-                          NULL),
- GNUNET_MQ_hd_var_size (local_data,
-                        GNUNET_MESSAGE_TYPE_CADET_LOCAL_DATA,
-                        struct GNUNET_CADET_LocalData,
-                        NULL),
- GNUNET_MQ_hd_fixed_size (local_ack,
-                          GNUNET_MESSAGE_TYPE_CADET_LOCAL_ACK,
-                          struct GNUNET_CADET_LocalAck,
-                          NULL),
- GNUNET_MQ_hd_fixed_size (get_peers,
-                          GNUNET_MESSAGE_TYPE_CADET_LOCAL_REQUEST_INFO_PEERS,
-                          struct GNUNET_MessageHeader,
-                          NULL),
- GNUNET_MQ_hd_fixed_size (show_path,
-                          GNUNET_MESSAGE_TYPE_CADET_LOCAL_REQUEST_INFO_PATH,
-                          struct GNUNET_CADET_RequestPathInfoMessage,
-                          NULL),
- GNUNET_MQ_hd_fixed_size (info_tunnels,
-                          GNUNET_MESSAGE_TYPE_CADET_LOCAL_REQUEST_INFO_TUNNELS,
-                          struct GNUNET_MessageHeader,
-                          NULL),
- GNUNET_MQ_hd_fixed_size (drop_message,
-                          GNUNET_MESSAGE_TYPE_CADET_DROP_CADET_MESSAGE,
-                          struct GNUNET_CADET_RequestDropCadetMessage,
-                          NULL),
- GNUNET_MQ_handler_end ());
+  ("cadet",
+  GNUNET_SERVICE_OPTION_NONE,
+  &run,
+  &client_connect_cb,
+  &client_disconnect_cb,
+  NULL,
+  GNUNET_MQ_hd_fixed_size (port_open,
+                           GNUNET_MESSAGE_TYPE_CADET_LOCAL_PORT_OPEN,
+                           struct GNUNET_CADET_PortMessage,
+                           NULL),
+  GNUNET_MQ_hd_fixed_size (port_close,
+                           GNUNET_MESSAGE_TYPE_CADET_LOCAL_PORT_CLOSE,
+                           struct GNUNET_CADET_PortMessage,
+                           NULL),
+  GNUNET_MQ_hd_fixed_size (channel_create,
+                           GNUNET_MESSAGE_TYPE_CADET_LOCAL_CHANNEL_CREATE,
+                           struct GNUNET_CADET_LocalChannelCreateMessage,
+                           NULL),
+  GNUNET_MQ_hd_fixed_size (channel_destroy,
+                           GNUNET_MESSAGE_TYPE_CADET_LOCAL_CHANNEL_DESTROY,
+                           struct GNUNET_CADET_LocalChannelDestroyMessage,
+                           NULL),
+  GNUNET_MQ_hd_var_size (local_data,
+                         GNUNET_MESSAGE_TYPE_CADET_LOCAL_DATA,
+                         struct GNUNET_CADET_LocalData,
+                         NULL),
+  GNUNET_MQ_hd_fixed_size (local_ack,
+                           GNUNET_MESSAGE_TYPE_CADET_LOCAL_ACK,
+                           struct GNUNET_CADET_LocalAck,
+                           NULL),
+  GNUNET_MQ_hd_fixed_size (get_peers,
+                           GNUNET_MESSAGE_TYPE_CADET_LOCAL_REQUEST_INFO_PEERS,
+                           struct GNUNET_MessageHeader,
+                           NULL),
+  GNUNET_MQ_hd_fixed_size (show_path,
+                           GNUNET_MESSAGE_TYPE_CADET_LOCAL_REQUEST_INFO_PATH,
+                           struct GNUNET_CADET_RequestPathInfoMessage,
+                           NULL),
+  GNUNET_MQ_hd_fixed_size (info_tunnels,
+                           GNUNET_MESSAGE_TYPE_CADET_LOCAL_REQUEST_INFO_TUNNELS,
+                           struct GNUNET_MessageHeader,
+                           NULL),
+  GNUNET_MQ_hd_fixed_size (drop_message,
+                           GNUNET_MESSAGE_TYPE_CADET_DROP_CADET_MESSAGE,
+                           struct GNUNET_CADET_RequestDropCadetMessage,
+                           NULL),
+  GNUNET_MQ_handler_end ());
 
 /* end of gnunet-service-cadet-new.c */
diff --git a/src/cadet/gnunet-service-cadet.h b/src/cadet/gnunet-service-cadet.h
index ff216f8c3045caa7633ac4870bf245b87a0ba703..6da0950f1e313dca81273e7597095d1cd47a3ed6 100644
--- a/src/cadet/gnunet-service-cadet.h
+++ b/src/cadet/gnunet-service-cadet.h
@@ -325,5 +325,4 @@ const char *
 GSC_2s (struct CadetClient *c);
 
 
-
 #endif
diff --git a/src/cadet/gnunet-service-cadet_channel.c b/src/cadet/gnunet-service-cadet_channel.c
index e6fce562f80639d341ebba13b04679a3cbb30f3e..dab53b8c4c4fbda03861a5bedc972cc891fa8831 100644
--- a/src/cadet/gnunet-service-cadet_channel.c
+++ b/src/cadet/gnunet-service-cadet_channel.c
@@ -385,29 +385,32 @@ struct CadetChannel
    * Type of message to be droped. See GCT_send.
    */
   uint16_t type GNUNET_PACKED;
-  
+
 };
 
 /**
  * Assign type of message to drop.
- * @param ch CadetChannel to assign type to drop. 
+ * @param ch CadetChannel to assign type to drop.
  * @param message GNUNET_CADET_RequestDropCadetMessage to get the type from.
  */
 void
-GCCH_assign_type_to_drop(struct CadetChannel *ch, const struct GNUNET_CADET_RequestDropCadetMessage *message)
+GCCH_assign_type_to_drop (struct CadetChannel *ch, const struct
+                          GNUNET_CADET_RequestDropCadetMessage *message)
 {
 
   ch->type = message->type;
-  
+
 }
 
+
 /**
  * Check if type of message is the one to drop.
- * @param ch CadetChannel to check for message type to drop. 
+ * @param ch CadetChannel to check for message type to drop.
  * @param message GNUNET_MessageHeader to compare the type with.
  */
 int
-GCCH_is_type_to_drop(struct CadetChannel *ch, const struct GNUNET_MessageHeader *message)
+GCCH_is_type_to_drop (struct CadetChannel *ch, const struct
+                      GNUNET_MessageHeader *message)
 {
 
   if (ch->type == message->type)
@@ -419,6 +422,7 @@ GCCH_is_type_to_drop(struct CadetChannel *ch, const struct GNUNET_MessageHeader
     return GNUNET_NO;
 }
 
+
 /**
  * Get the static string for identification of the channel.
  *
@@ -854,7 +858,8 @@ send_channel_data_ack (struct CadetChannel *ch)
        GCCH_2s (ch));
   if (NULL != ch->last_control_qe)
     GCT_send_cancel (ch->last_control_qe);
-  ch->last_control_qe = GCT_send (ch->t, &msg.header, &send_ack_cb, ch, &msg.ctn);
+  ch->last_control_qe = GCT_send (ch->t, &msg.header, &send_ack_cb, ch,
+                                  &msg.ctn);
 }
 
 
@@ -881,7 +886,8 @@ send_open_ack (void *cls)
   msg.port = ch->port;
   if (NULL != ch->last_control_qe)
     GCT_send_cancel (ch->last_control_qe);
-  ch->last_control_qe = GCT_send (ch->t, &msg.header, &send_ack_cb, ch, &msg.ctn);
+  ch->last_control_qe = GCT_send (ch->t, &msg.header, &send_ack_cb, ch,
+                                  &msg.ctn);
 }
 
 
@@ -1513,7 +1519,8 @@ retry_transmission (void *cls)
        "Retrying transmission on %s of message %u\n",
        GCCH_2s (ch),
        (unsigned int) ntohl (crm->data_message->mid.mid));
-  crm->qe = GCT_send (ch->t, &crm->data_message->header, &data_sent_cb, crm, &crm->data_message->ctn);
+  crm->qe = GCT_send (ch->t, &crm->data_message->header, &data_sent_cb, crm,
+                      &crm->data_message->ctn);
   GNUNET_assert (NULL == ch->retry_data_task);
 }
 
@@ -1901,7 +1908,8 @@ GCCH_handle_local_data (struct CadetChannel *ch,
     GNUNET_SCHEDULER_cancel (ch->retry_data_task);
     ch->retry_data_task = NULL;
   }
-  crm->qe = GCT_send (ch->t, &crm->data_message->header, &data_sent_cb, crm, &crm->data_message->ctn);
+  crm->qe = GCT_send (ch->t, &crm->data_message->header, &data_sent_cb, crm,
+                      &crm->data_message->ctn);
   GNUNET_assert (NULL == ch->retry_data_task);
   return GNUNET_OK;
 }
diff --git a/src/cadet/gnunet-service-cadet_connection.c b/src/cadet/gnunet-service-cadet_connection.c
index a7c1d9fb07c438eddce86c1912019ca0eb548918..3e1f779ade0bc89f1694513bc9290e3e577fc96f 100644
--- a/src/cadet/gnunet-service-cadet_connection.c
+++ b/src/cadet/gnunet-service-cadet_connection.c
@@ -614,6 +614,7 @@ set_monotime_sig (struct GNUNET_CADET_ConnectionCreateMessage *msg)
 
 }
 
+
 /**
  * Send a #GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE message to the
  * first hop.
@@ -641,7 +642,7 @@ send_create (void *cls)
 
   // check for tunnel state and set signed monotime (xrs,t3ss)
   t = GCP_get_tunnel (cc->destination, GNUNET_YES);
-  if ((NULL != t)&& (GCT_get_estate (t) == CADET_TUNNEL_KEY_UNINITIALIZED) &&
+  if ((NULL != t) && (GCT_get_estate (t) == CADET_TUNNEL_KEY_UNINITIALIZED) &&
       (GCT_alice_or_betty (GCP_get_id (cc->destination)) == GNUNET_NO))
   {
     create_msg->has_monotime = GNUNET_YES;
diff --git a/src/cadet/gnunet-service-cadet_core.c b/src/cadet/gnunet-service-cadet_core.c
index db47c8a9060b093ccde50bb13bf4304c1fdabd1a..9a83fa31d1374ac81fcebb8cc34e8504e44ce915 100644
--- a/src/cadet/gnunet-service-cadet_core.c
+++ b/src/cadet/gnunet-service-cadet_core.c
@@ -826,9 +826,9 @@ handle_connection_create (
 
     // Check for CADET state in case the other side has lost the tunnel (xrs,t3ss)
     if ((GNUNET_YES == msg->has_monotime) &&
-        (GNUNET_YES == GCP_check_and_update_monotime(origin, msg->monotime)) &&
-        ( GNUNET_OK == GCP_check_monotime_sig(origin, msg)) &&
-         (CADET_TUNNEL_KEY_OK == GCT_get_estate(t)))
+        (GNUNET_YES == GCP_check_and_update_monotime (origin, msg->monotime)) &&
+        (GNUNET_OK == GCP_check_monotime_sig (origin, msg)) &&
+        (CADET_TUNNEL_KEY_OK == GCT_get_estate (t)))
     {
       GCT_change_estate (t, CADET_TUNNEL_KEY_UNINITIALIZED);
     }
diff --git a/src/cadet/gnunet-service-cadet_peer.c b/src/cadet/gnunet-service-cadet_peer.c
index e5885278b4395658692764b013ac5c23a9f08fc7..221364c5d7babff24682747183415edbf5f89029 100644
--- a/src/cadet/gnunet-service-cadet_peer.c
+++ b/src/cadet/gnunet-service-cadet_peer.c
@@ -245,7 +245,7 @@ GCP_2s (const struct CadetPeer *cp)
   char *ret;
 
   if ((NULL == cp) ||
-      (0 == GNUNET_is_zero (&cp->pid.public_key)))
+      (GNUNET_YES == GNUNET_is_zero (&cp->pid.public_key)))
     return "NULL";
 
   ret = GNUNET_CRYPTO_eddsa_public_key_to_string (&cp->pid.public_key);
@@ -1552,6 +1552,7 @@ GCP_send_ooo (struct CadetPeer *cp,
                   env);
 }
 
+
 /**
  * Checking if a monotime value is newer than the last monotime value received from a peer. If the time value is newer it will be stored at the peer.
  *
@@ -1574,6 +1575,7 @@ GCP_check_and_update_monotime (struct CadetPeer *peer,
   return GNUNET_NO;
 }
 
+
 /**
  * Checking the signature for a monotime of a GNUNET_CADET_ConnectionCreateMessage.
  *
diff --git a/src/cadet/gnunet-service-cadet_tunnels.c b/src/cadet/gnunet-service-cadet_tunnels.c
index 66e7d5b1eda44a2bed1c08b5f353c14abd7c6781..2ca46b5aaead5bf2059a155770a764ff6c3cab86 100644
--- a/src/cadet/gnunet-service-cadet_tunnels.c
+++ b/src/cadet/gnunet-service-cadet_tunnels.c
@@ -3476,7 +3476,7 @@ GCT_send (struct CadetTunnel *t,
   {
     ch = lookup_channel (t,
                          *ctn);
-    if ((NULL != ch)&& GCCH_is_type_to_drop (ch, message))
+    if ((NULL != ch) && GCCH_is_type_to_drop (ch, message))
     {
       GNUNET_break (0);
       return NULL;
diff --git a/src/cadet/gnunet-service-cadet_tunnels.h b/src/cadet/gnunet-service-cadet_tunnels.h
index 147f2e56f13eab232f35e6a6960e566b3f825757..075cd03f8cd0fc6c03eb21fc7f4d2cb9d2fc482e 100644
--- a/src/cadet/gnunet-service-cadet_tunnels.h
+++ b/src/cadet/gnunet-service-cadet_tunnels.h
@@ -235,7 +235,7 @@ GCT_send (struct CadetTunnel *t,
           const struct GNUNET_MessageHeader *message,
           GCT_SendContinuation cont,
           void *cont_cls,
-	  struct GNUNET_CADET_ChannelTunnelNumber *ctn);
+          struct GNUNET_CADET_ChannelTunnelNumber *ctn);
 
 
 /**
diff --git a/src/cadet/loopcheck.sh b/src/cadet/loopcheck.sh
new file mode 100755
index 0000000000000000000000000000000000000000..9b867e95b796d5baf0eb3102b9d157b5cd1b49b5
--- /dev/null
+++ b/src/cadet/loopcheck.sh
@@ -0,0 +1,57 @@
+#!/usr/bin/env bash
+# This script is in the public domain
+# POSIX shell solution for named pipes and pipestatus,
+# http://shell.cfajohnson.com/cus-faq-2.html#Q11
+# run() {
+#     j=1
+#     while eval "\${pipestatus_$j+:} false"; do
+#         unset pipestatus_$j
+#         j=$(($j+1))
+#     done
+#     j=1 com= k=1 l=
+#     for a; do
+#         if [ "x$a" = 'x|' ]; then
+#             com="$com { $l "'3>&-
+#                          echo "pipestatus_'$j'=$?" >&3
+#                        } 4>&- |'
+#             j=$(($j+1)) l=
+#         else
+#             l="$l \"\$$k\""
+#         fi
+#         k=$(($k+1))
+#     done
+#     com="$com $l"' 3>&- >&4 4>&-
+#                     echo "pipestatus_'$j'=$?"'
+#     exec 4>&1
+#     eval "$(exec 3>&1; eval "$com")"
+#     exec 4>&-
+#     j=1
+#     while eval "\${pipestatus_$j+:} false"; do
+#         eval "[ \$pipestatus_$j -eq 0 ]" || return 1
+#         j=$(($j+1))
+#     done
+#     return 0
+# }
+
+# # https://mywiki.wooledge.org/Bashism has another solution:
+# # mkfifo fifo; command2 <fifo & command1 >fifo; echo "$?"
+
+while true; do
+    if [ "$1" = "" ]; then
+	echo All
+	taskset 1 make check || break;
+    else
+	echo One
+	LOGFILE="test_`date "+%m.%d-%H:%M:%S"`.log"
+	taskset 01 $1 2>&1 | tee $LOGFILE | grep -v DEBUG;
+        # TODO: Replace $PIPESTATUS with more portable code
+	if [ "${PIPESTATUS[0]}" != "0" ]; then
+	    echo "Failed";
+	    date;
+	    break;
+	fi
+    fi
+    grep cadet test_*.log | grep -B 10 ERROR && break
+    grep cadet test_*.log | grep -B 10 Assert && break
+    ls core* > /dev/null 2>&1 && break
+done
diff --git a/src/cadet/profiler.conf b/src/cadet/profiler.conf
new file mode 100644
index 0000000000000000000000000000000000000000..7ce28387037ae50c38c9513afc105a629872a917
--- /dev/null
+++ b/src/cadet/profiler.conf
@@ -0,0 +1,19 @@
+@INLINE@ test_cadet.conf
+
+[testbed]
+OVERLAY_TOPOLOGY = RANDOM
+OVERLAY_RANDOM_LINKS = %LINKS%
+MAX_PARALLEL_SERVICE_CONNECTIONS=4000
+SETUP_TIMEOUT = 60 m
+
+[transport]
+#MANIPULATE_DELAY_IN = 50 ms
+MANIPULATE_DELAY_OUT = 10 ms
+
+[cadet]
+REFRESH_CONNECTION_TIME = 1 h
+DISABLE_TRY_CONNECT = YES
+ID_ANNOUNCE_TIME = 5 s
+
+[dht]
+FORCE_NSE = %NSE%
diff --git a/src/cadet/run_profiler.sh b/src/cadet/run_profiler.sh
new file mode 100755
index 0000000000000000000000000000000000000000..4273dcd273eb90597224950c9ab26b42dc772045
--- /dev/null
+++ b/src/cadet/run_profiler.sh
@@ -0,0 +1,25 @@
+#!/bin/sh
+
+if [ "$#" -lt "3" ]; then
+    echo "usage: $0 ROUND_TIME PEERS PINGING_PEERS";
+    echo "example: $0 30s 16 1";
+    exit 1;
+fi
+
+ROUNDTIME=$1
+PEERS=$2
+PINGS=$3
+
+if [ $PEERS -eq 1 ]; then
+    echo "cannot run 1 peer";
+    exit 1;
+fi
+
+LINKS=`echo "l($PEERS) * l($PEERS) * $PEERS / 2" | bc -l`
+LINKS=`printf "%.0f" $LINKS`
+NSE=`echo "l($PEERS)/l(2)" | bc -l`
+echo "using $PEERS peers, $LINKS links";
+    
+sed -e "s/%LINKS%/$LINKS/;s/%NSE%/$NSE/" profiler.conf > .profiler.conf
+
+./gnunet-cadet-profiler $ROUNDTIME $PEERS $PINGS $4 2>&1 | tee log | grep -v DEBUG
diff --git a/src/cadet/small.dat b/src/cadet/small.dat
new file mode 100644
index 0000000000000000000000000000000000000000..c3805ee804c53e2449b52236f7e8b4eb477157e9
--- /dev/null
+++ b/src/cadet/small.dat
@@ -0,0 +1,21 @@
+16
+1:2
+1:9
+2:3
+3:4
+3:11
+4:5
+5:6
+5:13
+6:7
+7:8
+7:15
+8:9
+9:10
+10:11
+11:12
+12:13
+13:14
+14:15
+15:16
+16:1
diff --git a/src/cadet/test_cadet.c b/src/cadet/test_cadet.c
index 779d3bc9f1114911632e900ca4f6c24913b31f76..23f2ccbe3ba0d7e9229a485eb711ebfaa56f80c6 100644
--- a/src/cadet/test_cadet.c
+++ b/src/cadet/test_cadet.c
@@ -550,6 +550,7 @@ get_from_p_ids ()
   }
 }
 
+
 static struct GNUNET_CADET_Handle *
 get_from_cadets ()
 {
@@ -568,6 +569,7 @@ get_from_cadets ()
 
 }
 
+
 static unsigned int
 get_peer_nr (int outgoing)
 {
@@ -581,6 +583,7 @@ get_peer_nr (int outgoing)
   }
 }
 
+
 /**
  * Task to reconnect to other peer.
  *
@@ -626,6 +629,7 @@ reconnect_op (void *cls)
   send_test_message (outgoing_ch);
 }
 
+
 void
 reopen_channel ()
 {
@@ -659,6 +663,7 @@ reopen_channel ()
   send_test_message (outgoing_ch);
 }
 
+
 static void
 peers_callback (void *cls, const struct GNUNET_CADET_PeerListEntry *ple);
 
@@ -676,6 +681,7 @@ get_peers (void *cls)
 
 }
 
+
 /**
  * Method called to retrieve information about all peers in CADET, called
  * once per peer.
@@ -712,7 +718,7 @@ peers_callback (void *cls, const struct GNUNET_CADET_PeerListEntry *ple)
               "p_id %s\n",
               GNUNET_i2s_full (p_id));
 
-  if ((0 == GNUNET_memcmp (&ple->peer, p_id))&& ple->have_tunnel)
+  if ((0 == GNUNET_memcmp (&ple->peer, p_id)) && ple->have_tunnel)
   {
 
     GNUNET_log (GNUNET_ERROR_TYPE_INFO,
@@ -733,6 +739,7 @@ peers_callback (void *cls, const struct GNUNET_CADET_PeerListEntry *ple)
   }
 }
 
+
 /**
  * Function called whenever an MQ-channel is destroyed, unless the destruction
  * was requested by #GNUNET_CADET_channel_destroy.
@@ -1169,7 +1176,7 @@ connect_handler (void *cls,
 
   if (peer == get_peer_nr (GNUNET_NO))
   {
-    if ((DESTROY != test)&&(NULL != incoming_ch))
+    if ((DESTROY != test) && (NULL != incoming_ch))
     {
       GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
                   "Duplicate incoming channel for client %lu\n",
diff --git a/src/cadet/test_cadet_flow.c b/src/cadet/test_cadet_flow.c
new file mode 100644
index 0000000000000000000000000000000000000000..2fbdd8d5028a3c8a4db821313e66c7c6a3fd1f48
--- /dev/null
+++ b/src/cadet/test_cadet_flow.c
@@ -0,0 +1,891 @@
+/*
+     This file is part of GNUnet.
+     Copyright (C) 2011, 2017 GNUnet e.V.
+
+     GNUnet is free software: you can redistribute it and/or modify it
+     under the terms of the GNU Affero General Public License as published
+     by the Free Software Foundation, either version 3 of the License,
+     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
+     Affero General Public License for more details.
+
+     You should have received a copy of the GNU Affero General Public License
+     along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+     SPDX-License-Identifier: AGPL3.0-or-later
+ */
+/**
+ * @file cadet/test_cadet_flow.c
+ * @author Bart Polot
+ * @author Christian Grothoff
+ * @brief Test for flow control of CADET service
+ */
+#include <stdio.h>
+#include "platform.h"
+#include "cadet_test_lib.h"
+#include "gnunet_cadet_service.h"
+#include "gnunet_statistics_service.h"
+#include <gauger.h>
+
+
+/**
+ * Ugly workaround to unify data handlers on incoming and outgoing channels.
+ */
+struct CadetTestChannelWrapper
+{
+  /**
+   * Channel pointer.
+   */
+  struct GNUNET_CADET_Channel *ch;
+};
+
+/**
+ * How many messages to send by default.
+ */
+#define TOTAL_PACKETS_DEFAULT 500
+
+/**
+ * How long until we give up on connecting the peers?
+ */
+#define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 120)
+
+/**
+ * Time to wait by default  for stuff that should be rather fast.
+ */
+#define SHORT_TIME GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 20)
+
+/**
+ * How fast do we send messages?
+ */
+#define SEND_INTERVAL GNUNET_TIME_relative_multiply ( \
+    GNUNET_TIME_UNIT_MILLISECONDS, 10)
+
+
+/**
+ * How many packets to send.
+ */
+static unsigned int total_packets = TOTAL_PACKETS_DEFAULT;
+
+/**
+ * Time to wait for fast operations.
+ */
+static struct GNUNET_TIME_Relative short_time;
+
+/**
+ * Size of each test packet's payload
+ */
+static size_t size_payload = sizeof(uint32_t);
+
+/**
+ * Operation to get peer ids.
+ */
+static struct GNUNET_TESTBED_Operation *t_op[2];
+
+/**
+ * Peer ids.
+ */
+static struct GNUNET_PeerIdentity *p_id[2];
+
+/**
+ * Port ID
+ */
+static struct GNUNET_HashCode port;
+
+/**
+ * Peer ids counter.
+ */
+static unsigned int p_ids;
+
+/**
+ * Is the setup initialized?
+ */
+static int initialized;
+
+/**
+ * Number of payload packes sent.
+ */
+static int data_sent;
+
+/**
+ * Number of payload packets received.
+ */
+static int data_received;
+
+/**
+ * Number of payload packed acknowledgements sent.
+ */
+static int ack_sent;
+
+/**
+ * Number of payload packed explicitly (app level) acknowledged.
+ */
+static int ack_received;
+
+/**
+ * Total number of peers asked to run.
+ */
+static unsigned int peers_requested = 2;
+
+/**
+ * Number of currently running peers (should be same as @c peers_requested).
+ */
+static unsigned int peers_running;
+
+/**
+ * Test context (to shut down).
+ */
+struct GNUNET_CADET_TEST_Context *test_ctx;
+
+/**
+ * Task called to disconnect peers.
+ */
+static struct GNUNET_SCHEDULER_Task *disconnect_task;
+
+/**
+ * Task To perform tests
+ */
+static struct GNUNET_SCHEDULER_Task *test_task;
+
+/**
+ * Task runnining #send_next_msg().
+ */
+static struct GNUNET_SCHEDULER_Task *send_next_msg_task;
+
+/**
+ * Cadet handle for the root peer
+ */
+static struct GNUNET_CADET_Handle *h1;
+
+/**
+ * Cadet handle for the first leaf peer
+ */
+static struct GNUNET_CADET_Handle *h2;
+
+/**
+ * Channel handle for the root peer
+ */
+static struct GNUNET_CADET_Channel *outgoing_ch;
+
+/**
+ * Channel handle for the dest peer
+ */
+static struct GNUNET_CADET_Channel *incoming_ch;
+
+/**
+ * Time we started the data transmission (after channel has been established
+ * and initilized).
+ */
+static struct GNUNET_TIME_Absolute start_time;
+
+/**
+ * Peers handle.
+ */
+static struct GNUNET_TESTBED_Peer **testbed_peers;
+
+/**
+ * Statistics operation handle.
+ */
+static struct GNUNET_TESTBED_Operation *stats_op;
+
+/**
+ * Keepalives sent.
+ */
+static unsigned int ka_sent;
+
+/**
+ * Keepalives received.
+ */
+static unsigned int ka_received;
+
+/**
+ * How many messages were dropped by CADET because of full buffers?
+ */
+static unsigned int msg_dropped;
+
+
+/**
+ * Show the results of the test (banwidth acheived) and log them to GAUGER
+ */
+static void
+show_end_data (void)
+{
+  static struct GNUNET_TIME_Absolute end_time;
+  static struct GNUNET_TIME_Relative total_time;
+
+  end_time = GNUNET_TIME_absolute_get ();
+  total_time = GNUNET_TIME_absolute_get_difference (start_time, end_time);
+  fprintf (stderr,
+           "\nResults of test \"%s\"\n",
+           test_name);
+  fprintf (stderr,
+           "Test time %s\n",
+           GNUNET_STRINGS_relative_time_to_string (total_time, GNUNET_YES));
+  fprintf (stderr,
+           "Test bandwidth: %f kb/s\n",
+           4 * total_packets * 1.0 / (total_time.rel_value_us / 1000));    // 4bytes * ms
+  fprintf (stderr,
+           "Test throughput: %f packets/s\n\n",
+           total_packets * 1000.0 / (total_time.rel_value_us / 1000));     // packets * ms
+  GAUGER ("CADET",
+          test_name,
+          total_packets * 1000.0 / (total_time.rel_value_us / 1000),
+          "packets/s");
+}
+
+
+/**
+ * Shut down peergroup, clean up.
+ *
+ * @param cls Closure (unused).
+ * @param tc Task Context.
+ */
+static void
+shutdown_task (void *cls)
+{
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "Ending test.\n");
+  if (NULL != send_next_msg_task)
+  {
+    GNUNET_SCHEDULER_cancel (send_next_msg_task);
+    send_next_msg_task = NULL;
+  }
+  if (NULL != test_task)
+  {
+    GNUNET_SCHEDULER_cancel (test_task);
+    test_task = NULL;
+  }
+  for (unsigned int i = 0; i < 2; i++)
+    GNUNET_TESTBED_operation_done (t_op[i]);
+  if (NULL != outgoing_ch)
+  {
+    GNUNET_CADET_channel_destroy (outgoing_ch);
+    outgoing_ch = NULL;
+  }
+  if (NULL != incoming_ch)
+  {
+    GNUNET_CADET_channel_destroy (incoming_ch);
+    incoming_ch = NULL;
+  }
+  GNUNET_CADET_TEST_cleanup (test_ctx);
+}
+
+
+/**
+ * Stats callback. Finish the stats testbed operation and when all stats have
+ * been iterated, shutdown the test.
+ *
+ * @param cls Closure (line number from which termination was requested).
+ * @param op the operation that has been finished
+ * @param emsg error message in case the operation has failed; will be NULL if
+ *          operation has executed successfully.
+ */
+static void
+stats_cont (void *cls,
+            struct GNUNET_TESTBED_Operation *op,
+            const char *emsg)
+{
+  GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+              "KA sent: %u, KA received: %u\n",
+              ka_sent,
+              ka_received);
+  if ((KEEPALIVE == test) && ((ka_sent < 2) || (ka_sent > ka_received + 1)))
+  {
+    GNUNET_break (0);
+    ok--;
+  }
+  GNUNET_TESTBED_operation_done (stats_op);
+
+  if (NULL != disconnect_task)
+    GNUNET_SCHEDULER_cancel (disconnect_task);
+  disconnect_task = GNUNET_SCHEDULER_add_now (&disconnect_cadet_peers,
+                                              cls);
+}
+
+
+/**
+ * Process statistic values.
+ *
+ * @param cls closure (line number, unused)
+ * @param peer the peer the statistic belong to
+ * @param subsystem name of subsystem that created the statistic
+ * @param name the name of the datum
+ * @param value the current value
+ * @param is_persistent #GNUNET_YES if the value is persistent, #GNUNET_NO if not
+ * @return #GNUNET_OK to continue, #GNUNET_SYSERR to abort iteration
+ */
+static int
+stats_iterator (void *cls,
+                const struct GNUNET_TESTBED_Peer *peer,
+                const char *subsystem,
+                const char *name,
+                uint64_t value,
+                int is_persistent)
+{
+  static const char *s_sent = "# keepalives sent";
+  static const char *s_recv = "# keepalives received";
+  static const char *rdrops = "# messages dropped due to full buffer";
+  static const char *cdrops = "# messages dropped due to slow client";
+  uint32_t i;
+
+  i = GNUNET_TESTBED_get_index (peer);
+  GNUNET_log (GNUNET_ERROR_TYPE_INFO, "STATS PEER %u - %s [%s]: %llu\n", i,
+              subsystem, name, (unsigned long long) value);
+  if ((0 == strncmp (s_sent, name, strlen (s_sent))) && (0 == i))
+    ka_sent = value;
+  if ((0 == strncmp (s_recv, name, strlen (s_recv))) && (peers_requested - 1 ==
+                                                         i) )
+    ka_received = value;
+  if (0 == strncmp (rdrops, name, strlen (rdrops)))
+    msg_dropped += value;
+  if (0 == strncmp (cdrops, name, strlen (cdrops)))
+    msg_dropped += value;
+
+  return GNUNET_OK;
+}
+
+
+/**
+ * Task to gather all statistics.
+ *
+ * @param cls Closure (line from which the task was scheduled).
+ */
+static void
+gather_stats_and_exit (void *cls)
+{
+  long l = (long) cls;
+
+  disconnect_task = NULL;
+  GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+              "gathering statistics from line %ld\n",
+              l);
+  if (NULL != outgoing_ch)
+  {
+    GNUNET_CADET_channel_destroy (outgoing_ch);
+    outgoing_ch = NULL;
+  }
+  stats_op = GNUNET_TESTBED_get_statistics (peers_running,
+                                            testbed_peers,
+                                            "cadet",
+                                            NULL,
+                                            &stats_iterator,
+                                            stats_cont,
+                                            cls);
+}
+
+
+/**
+ * Abort test: schedule disconnect and shutdown immediately
+ *
+ * @param line Line in the code the abort is requested from (__LINE__).
+ */
+static void
+abort_test (long line)
+{
+  if (NULL != disconnect_task)
+  {
+    GNUNET_SCHEDULER_cancel (disconnect_task);
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                "Aborting test from %ld\n",
+                line);
+    disconnect_task =
+      GNUNET_SCHEDULER_add_now (&disconnect_cadet_peers,
+                                (void *) line);
+  }
+}
+
+
+/**
+ * Send a message on the channel with the appropriate size and payload.
+ *
+ * Update the appropriate *_sent counter.
+ *
+ * @param channel Channel to send the message on.
+ */
+static void
+send_test_message (struct GNUNET_CADET_Channel *channel)
+{
+  struct GNUNET_MQ_Envelope *env;
+  struct GNUNET_MessageHeader *msg;
+  uint32_t *data;
+  int payload;
+  int size;
+
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "Sending test message on channel %p\n",
+              channel);
+  size = size_payload;
+  if (GNUNET_NO == initialized)
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending INITIALIZER\n");
+    size += 1000;
+    payload = data_sent;
+    if (SPEED_ACK == test)   // FIXME unify SPEED_ACK with an initializer
+      data_sent++;
+  }
+  else if ((SPEED == test) || (SPEED_ACK == test))
+  {
+    if (get_target_channel () == channel)
+    {
+      payload = ack_sent;
+      size += ack_sent;
+      ack_sent++;
+      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                  "Sending ACK %u [%d bytes]\n",
+                  payload, size);
+    }
+    else
+    {
+      payload = data_sent;
+      size += data_sent;
+      data_sent++;
+      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                  "Sending DATA %u [%d bytes]\n",
+                  data_sent, size);
+    }
+  }
+  else if (FORWARD == test)
+  {
+    payload = ack_sent;
+  }
+  else if (P2P_SIGNAL == test)
+  {
+    payload = data_sent;
+  }
+  else
+  {
+    GNUNET_assert (0);
+  }
+  env = GNUNET_MQ_msg_extra (msg, size, GNUNET_MESSAGE_TYPE_DUMMY);
+
+  data = (uint32_t *) &msg[1];
+  *data = htonl (payload);
+  GNUNET_MQ_send (GNUNET_CADET_get_mq (channel), env);
+}
+
+
+/**
+ * Task to request a new data transmission in a SPEED test, without waiting
+ * for previous messages to be sent/arrrive.
+ *
+ * @param cls Closure (unused).
+ */
+static void
+send_next_msg (void *cls)
+{
+  struct GNUNET_CADET_Channel *channel;
+
+  send_next_msg_task = NULL;
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "Sending next message: %d\n",
+              data_sent);
+
+  channel = GNUNET_YES == test_backwards ? incoming_ch : outgoing_ch;
+  GNUNET_assert (NULL != channel);
+  GNUNET_assert (SPEED == test);
+  send_test_message (channel);
+  if (data_sent < total_packets)
+  {
+    /* SPEED test: Send all messages as soon as possible */
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                "Scheduling message %d\n",
+                data_sent + 1);
+    send_next_msg_task =
+      GNUNET_SCHEDULER_add_delayed (SEND_INTERVAL,
+                                    &send_next_msg,
+                                    NULL);
+  }
+}
+
+
+/**
+ * Check if payload is sane (size contains payload).
+ *
+ * @param cls should match #ch
+ * @param message The actual message.
+ * @return #GNUNET_OK to keep the channel open,
+ *         #GNUNET_SYSERR to close it (signal serious error).
+ */
+static int
+check_data (void *cls,
+            const struct GNUNET_MessageHeader *message)
+{
+  return GNUNET_OK;             /* all is well-formed */
+}
+
+
+/**
+ * Function is called whenever a message is received.
+ *
+ * @param cls closure (set from GNUNET_CADET_connect(), peer number)
+ * @param message the actual message
+ */
+static void
+handle_data (void *cls,
+             const struct GNUNET_MessageHeader *message)
+{
+  struct CadetTestChannelWrapper *ch = cls;
+  struct GNUNET_CADET_Channel *channel = ch->ch;
+  uint32_t *data;
+  uint32_t payload;
+  int *counter;
+
+  GNUNET_CADET_receive_done (channel);
+  counter = get_target_channel () == channel ? &data_received : &ack_received;
+  if (channel == outgoing_ch)
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+                "Root client got a message.\n");
+  }
+  else if (channel == incoming_ch)
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+                "Leaf client got a message.\n");
+  }
+  else
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                "Unknown channel %p.\n",
+                channel);
+    GNUNET_assert (0);
+  }
+
+  data = (uint32_t *) &message[1];
+  payload = ntohl (*data);
+  if (payload == *counter)
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+                "Payload as expected: %u\n",
+                payload);
+  }
+  else
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                "Received payload %u, expected: %u\n",
+                payload, *counter);
+  }
+  (*counter)++;
+  if (get_target_channel () == channel)  /* Got "data" */
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+                " received data %u\n",
+                data_received);
+    if (data_received < total_packets)
+      return;
+  }
+  else /* Got "ack" */
+  {
+    if ((SPEED_ACK == test) || (SPEED == test) )
+    {
+      GNUNET_log (GNUNET_ERROR_TYPE_INFO, " received ack %u\n", ack_received);
+      /* Send more data */
+      send_test_message (channel);
+      if ((ack_received < total_packets) && (SPEED != test) )
+        return;
+      if ((ok == 2) && (SPEED == test) )
+        return;
+      show_end_data ();
+    }
+    if (test == P2P_SIGNAL)
+    {
+      GNUNET_CADET_channel_destroy (incoming_ch);
+      incoming_ch = NULL;
+    }
+    else
+    {
+      GNUNET_CADET_channel_destroy (outgoing_ch);
+      outgoing_ch = NULL;
+    }
+  }
+}
+
+
+/**
+ * Method called whenever a peer connects to a port in MQ-based CADET.
+ *
+ * @param cls Closure from #GNUNET_CADET_open_port (peer # as long).
+ * @param channel New handle to the channel.
+ * @param source Peer that started this channel.
+ * @return Closure for the incoming @a channel. It's given to:
+ *         - The #GNUNET_CADET_DisconnectEventHandler (given to
+ *           #GNUNET_CADET_open_port) when the channel dies.
+ *         - Each the #GNUNET_MQ_MessageCallback handlers for each message
+ *           received on the @a channel.
+ */
+static void *
+connect_handler (void *cls,
+                 struct GNUNET_CADET_Channel *channel,
+                 const struct GNUNET_PeerIdentity *source)
+{
+  struct CadetTestChannelWrapper *ch;
+  long peer = (long) cls;
+
+  GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+              "Incoming channel from %s to %ld: %p\n",
+              GNUNET_i2s (source),
+              peer,
+              channel);
+  if (peer == peers_requested - 1)
+  {
+    if (NULL != incoming_ch)
+    {
+      GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                  "Duplicate incoming channel for client %lu\n",
+                  (long) cls);
+      GNUNET_assert (0);
+    }
+    incoming_ch = channel;
+  }
+  else
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+                "Incoming channel for unexpected peer #%lu\n",
+                (long) cls);
+    GNUNET_assert (0);
+  }
+  ch = GNUNET_new (struct CadetTestChannelWrapper);
+  ch->ch = channel;
+
+  return ch;
+}
+
+
+/**
+ * Function called whenever an MQ-channel is destroyed, even if the destruction
+ * was requested by #GNUNET_CADET_channel_destroy.
+ * It must NOT call #GNUNET_CADET_channel_destroy on the channel.
+ *
+ * It should clean up any associated state, including cancelling any pending
+ * transmission on this channel.
+ *
+ * @param cls Channel closure (channel wrapper).
+ * @param channel Connection to the other end (henceforth invalid).
+ */
+static void
+disconnect_handler (void *cls,
+                    const struct GNUNET_CADET_Channel *channel)
+{
+  struct CadetTestChannelWrapper *ch_w = cls;
+
+  GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+              "Channel disconnected at %d\n",
+              ok);
+  GNUNET_assert (ch_w->ch == channel);
+  if (channel == incoming_ch)
+    incoming_ch = NULL;
+  else if (outgoing_ch == channel)
+    outgoing_ch = NULL;
+  else
+    GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+                "Disconnect on unknown channel %p\n",
+                channel);
+  if (NULL != disconnect_task)
+    GNUNET_SCHEDULER_cancel (disconnect_task);
+  disconnect_task = GNUNET_SCHEDULER_add_now (&gather_stats_and_exit,
+                                              (void *) __LINE__);
+  GNUNET_free (ch_w);
+}
+
+
+/**
+ * Start the testcase, we know the peers and have handles to CADET.
+ *
+ * Testcase continues when the root receives confirmation of connected peers,
+ * on callback function ch.
+ *
+ * @param cls Closure (unused).
+ */
+static void
+start_test (void *cls)
+{
+  struct GNUNET_MQ_MessageHandler handlers[] = {
+    GNUNET_MQ_hd_var_size (data,
+                           GNUNET_MESSAGE_TYPE_DUMMY,
+                           struct GNUNET_MessageHeader,
+                           NULL),
+    GNUNET_MQ_handler_end ()
+  };
+  struct CadetTestChannelWrapper *ch;
+  enum GNUNET_CADET_ChannelOption flags;
+
+  test_task = NULL;
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "In start_test\n");
+  start_time = GNUNET_TIME_absolute_get ();
+  ch = GNUNET_new (struct CadetTestChannelWrapper);
+  outgoing_ch = GNUNET_CADET_channel_create (h1,
+                                             ch,
+                                             p_id[1],
+                                             &port,
+                                             flags,
+                                             NULL,
+                                             &disconnect_handler,
+                                             handlers);
+  ch->ch = outgoing_ch;
+  GNUNET_assert (NULL == disconnect_task);
+  disconnect_task
+    = GNUNET_SCHEDULER_add_delayed (short_time,
+                                    &gather_stats_and_exit,
+                                    (void *) __LINE__);
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "Sending data initializer on channel %p...\n",
+              outgoing_ch);
+  send_test_message (outgoing_ch);
+}
+
+
+/**
+ * Callback to be called when the requested peer information is available
+ *
+ * @param cls the closure from GNUNET_TESTBED_peer_get_information()
+ * @param op the operation this callback corresponds to
+ * @param pinfo the result; will be NULL if the operation has failed
+ * @param emsg error message if the operation has failed;
+ *             NULL if the operation is successfull
+ */
+static void
+pi_cb (void *cls,
+       struct GNUNET_TESTBED_Operation *op,
+       const struct GNUNET_TESTBED_PeerInformation *pinfo,
+       const char *emsg)
+{
+  long i = (long) cls;
+
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "ID callback for %ld\n",
+              i);
+  if ((NULL == pinfo) ||
+      (NULL != emsg))
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                "pi_cb: %s\n",
+                emsg);
+    abort_test (__LINE__);
+    return;
+  }
+  p_id[i] = pinfo->result.id;
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "id: %s\n",
+              GNUNET_i2s (p_id[i]));
+  p_ids++;
+  if (p_ids < 2)
+    return;
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "Got all IDs, starting test\n");
+  test_task = GNUNET_SCHEDULER_add_now (&start_test,
+                                        NULL);
+}
+
+
+/**
+ * test main: start test when all peers are connected
+ *
+ * @param cls Closure.
+ * @param ctx Argument to give to GNUNET_CADET_TEST_cleanup on test end.
+ * @param num_peers Number of peers that are running.
+ * @param peers Array of peers.
+ * @param cadets Handle to each of the CADETs of the peers.
+ */
+static void
+tmain (void *cls,
+       struct GNUNET_CADET_TEST_Context *ctx,
+       unsigned int num_peers,
+       struct GNUNET_TESTBED_Peer **peers,
+       struct GNUNET_CADET_Handle **cadets)
+{
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "test main\n");
+  test_ctx = ctx;
+  peers_running = num_peers;
+  GNUNET_assert (peers_running == peers_requested);
+  testbed_peers = peers;
+  h1 = cadets[0];
+  h2 = cadets[num_peers - 1];
+  GNUNET_SCHEDULER_add_shutdown (&shutdown_task,
+                                 NULL);
+  p_ids = 0;
+  t_op[0] = GNUNET_TESTBED_peer_get_information (peers[0],
+                                                 GNUNET_TESTBED_PIT_IDENTITY,
+                                                 &pi_cb,
+                                                 (void *) 0L);
+  t_op[1] = GNUNET_TESTBED_peer_get_information (peers[num_peers - 1],
+                                                 GNUNET_TESTBED_PIT_IDENTITY,
+                                                 &pi_cb,
+                                                 (void *) 1L);
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "requested peer ids\n");
+}
+
+
+/**
+ * Main: start test
+ */
+int
+main (int argc,
+      char *argv[])
+{
+  static const struct GNUNET_HashCode *ports[2];
+  struct GNUNET_MQ_MessageHandler handlers[] = {
+    GNUNET_MQ_hd_var_size (data,
+                           GNUNET_MESSAGE_TYPE_DUMMY,
+                           struct GNUNET_MessageHeader,
+                           NULL),
+    GNUNET_MQ_handler_end ()
+  };
+  const char *config_file = "test_cadet.conf";
+  char port_id[] = "test port";
+  struct GNUNET_GETOPT_CommandLineOption options[] = {
+    GNUNET_GETOPT_option_relative_time ('t',
+                                        "time",
+                                        "short_time",
+                                        gettext_noop ("set short timeout"),
+                                        &short_time),
+    GNUNET_GETOPT_option_uint ('m',
+                               "messages",
+                               "NUM_MESSAGES",
+                               gettext_noop ("set number of messages to send"),
+                               &total_packets),
+    GNUNET_GETOPT_option_uint ('p',
+                               "peers",
+                               "NUM_PEERS",
+                               gettext_noop ("number of peers to launch"),
+                               &peers_requested),
+    GNUNET_GETOPT_OPTION_END
+  };
+
+  GNUNET_log_setup ("test-cadet-flow",
+                    "DEBUG",
+                    NULL);
+  total_packets = TOTAL_PACKETS;
+  short_time = SHORT_TIME;
+  if (-1 == GNUNET_GETOPT_run (argv[0],
+                               options,
+                               argc,
+                               argv))
+  {
+    fprintf (stderr,
+             "test failed: problem with CLI parameters\n");
+    return 1;
+  }
+  GNUNET_CRYPTO_hash (port_id,
+                      sizeof(port_id),
+                      &port);
+  ports[0] = &port;
+  ports[1] = NULL;
+  GNUNET_CADET_TEST_ruN ("test_cadet_flow",
+                         config_file,
+                         peers_requested,
+                         &tmain,
+                         NULL,        /* tmain cls */
+                         &connect_handler,
+                         NULL,
+                         &disconnect_handler,
+                         handlers,
+                         ports);
+  return 0;
+}
+
+
+/* end of test_cadet_flow.c */
diff --git a/src/cadet/valgrind-cadet.supp b/src/cadet/valgrind-cadet.supp
new file mode 100644
index 0000000000000000000000000000000000000000..fecd5185bbb95c9e71ae02b487edf5a97855fd58
--- /dev/null
+++ b/src/cadet/valgrind-cadet.supp
@@ -0,0 +1,116 @@
+{
+   logsetup_addr
+   Memcheck:Addr8
+   obj:/lib/libc-2.14.1.so
+   ...
+   fun:get_type
+   fun:GNUNET_log_setup
+   fun:GNUNET_SERVICE_run
+   fun:main
+}
+
+{
+   scanf_addr
+   Memcheck:Addr8
+   obj:/lib/libc-2.14.1.so
+   ...
+   fun:vsscanf
+   fun:sscanf
+   fun:GNUNET_CONFIGURATION_get_value_number
+   fun:GNUNET_SERVICE_get_server_addresses
+   fun:setup_service
+   fun:GNUNET_SERVICE_run
+   fun:main
+}
+
+{
+   mylog_addr
+   Memcheck:Addr8
+   obj:/lib/libc-2.14.1.so
+   ...
+   fun:service_task
+   fun:GNUNET_SCHEDULER_run
+   fun:GNUNET_SERVICE_run
+   fun:main
+}
+
+{
+   mylog_uninit
+   Memcheck:Value8
+   obj:/lib/libc-2.14.1.so
+   ...
+   fun:mylog
+   fun:GNUNET_log_from_nocheck
+   fun:service_task
+   ...
+   fun:GNUNET_SCHEDULER_run
+   fun:GNUNET_SERVICE_run
+   fun:main
+}
+
+{
+   mylog_from_cond
+   Memcheck:Cond
+   obj:/lib/libc-2.14.1.so
+   ...
+   fun:mylog
+   fun:GNUNET_log_from_nocheck
+   ...
+   fun:service_task
+   fun:GNUNET_SCHEDULER_run
+   fun:GNUNET_SERVICE_run
+   fun:main
+}
+
+{
+   mylog_cond
+   Memcheck:Cond
+   obj:/lib/libc-2.14.1.so
+   ...
+   fun:mylog
+   fun:GNUNET_log_nocheck
+   ...
+   fun:service_task
+   fun:GNUNET_SCHEDULER_run
+   fun:GNUNET_SERVICE_run
+   fun:main
+}
+
+{
+   inet_ntop_cond
+   Memcheck:Cond
+   obj:/lib/libc-2.14.1.so
+   ...
+   fun:inet_ntop
+   fun:GNUNET_a2s
+   ...
+   fun:service_task
+   fun:GNUNET_SCHEDULER_run
+   fun:GNUNET_SERVICE_run
+   fun:main
+}
+
+{
+   create_key_from_file
+   Memcheck:Addr8
+   obj:/lib/libc-2.14.1.so
+   ...
+   fun:GNUNET_CRYPTO_rsa_key_create_from_file
+   fun:run
+   fun:service_task
+   fun:GNUNET_SCHEDULER_run
+   fun:GNUNET_SERVICE_run
+   fun:main
+}
+
+{
+   main_notify_handler
+   Memcheck:Addr8
+   obj:/lib/libc-2.14.1.so
+   ...
+   fun:main_notify_handler
+   fun:receive_ready
+   fun:GNUNET_SCHEDULER_run
+   fun:GNUNET_SERVICE_run
+   fun:main
+}
\ No newline at end of file
diff --git a/src/consensus/.gitignore b/src/consensus/.gitignore
new file mode 100644
index 0000000000000000000000000000000000000000..8050d760efab5a155d2f617226fd9c395a868e51
--- /dev/null
+++ b/src/consensus/.gitignore
@@ -0,0 +1,6 @@
+gnunet-service-evil-consensus
+gnunet-consensus-profiler
+gnunet-service-consensus
+test_consensus_api
+resource.log.master
+consensus-simulation.py
diff --git a/src/consensus/consensus_protocol.h b/src/consensus/consensus_protocol.h
index a40162fb8a9a0e511204ffe4087967336fc1b23d..0afd56b27e062abdb78d5a51125b4df919f8cb86 100644
--- a/src/consensus/consensus_protocol.h
+++ b/src/consensus/consensus_protocol.h
@@ -124,6 +124,7 @@ struct ConsensusSizeElement
   uint8_t sender_index;
 };
 
+
 struct ConsensusStuffedElement
 {
   struct ConsensusElement ce;
diff --git a/src/consensus/gnunet-service-consensus.c b/src/consensus/gnunet-service-consensus.c
index 13fa0d0e718053ff283f88d48cca84c8b0e04e2b..371b7f67f62e2096fe27996f58b44ebdfda6ebd4 100644
--- a/src/consensus/gnunet-service-consensus.c
+++ b/src/consensus/gnunet-service-consensus.c
@@ -1,6 +1,6 @@
 /*
       This file is part of GNUnet
-      Copyright (C) 2012, 2013, 2017 GNUnet e.V.
+      Copyright (C) 2012, 2013, 2017, 2020 GNUnet e.V.
 
       GNUnet is free software: you can redistribute it and/or modify it
       under the terms of the GNU Affero General Public License as published
@@ -17,13 +17,11 @@
 
      SPDX-License-Identifier: AGPL3.0-or-later
  */
-
 /**
  * @file consensus/gnunet-service-consensus.c
  * @brief multi-peer set reconciliation
  * @author Florian Dold <flo@dold.me>
  */
-
 #include "platform.h"
 #include "gnunet_util_lib.h"
 #include "gnunet_block_lib.h"
@@ -62,11 +60,57 @@ enum EarlyStoppingPhase
 };
 
 
+enum PhaseKind
+{
+  PHASE_KIND_ALL_TO_ALL,
+  PHASE_KIND_ALL_TO_ALL_2,
+  PHASE_KIND_GRADECAST_LEADER,
+  PHASE_KIND_GRADECAST_ECHO,
+  PHASE_KIND_GRADECAST_ECHO_GRADE,
+  PHASE_KIND_GRADECAST_CONFIRM,
+  PHASE_KIND_GRADECAST_CONFIRM_GRADE,
+  /**
+   * Apply a repetition of the all-to-all
+   * gradecast to the current set.
+   */
+  PHASE_KIND_APPLY_REP,
+  PHASE_KIND_FINISH,
+};
+
+
+enum SetKind
+{
+  SET_KIND_NONE = 0,
+  SET_KIND_CURRENT,
+  /**
+   * Last result set from a gradecast
+   */
+  SET_KIND_LAST_GRADECAST,
+  SET_KIND_LEADER_PROPOSAL,
+  SET_KIND_ECHO_RESULT,
+};
+
+enum DiffKind
+{
+  DIFF_KIND_NONE = 0,
+  DIFF_KIND_LEADER_PROPOSAL,
+  DIFF_KIND_LEADER_CONSENSUS,
+  DIFF_KIND_GRADECAST_RESULT,
+};
+
+enum RfnKind
+{
+  RFN_KIND_NONE = 0,
+  RFN_KIND_ECHO,
+  RFN_KIND_CONFIRM,
+  RFN_KIND_GRADECAST_RESULT
+};
+
+
 GNUNET_NETWORK_STRUCT_BEGIN
 
 /**
- * Tuple of integers that together
- * identify a task uniquely.
+ * Tuple of integers that together identify a task uniquely.
  */
 struct TaskKey
 {
@@ -102,8 +146,14 @@ struct TaskKey
 
 struct SetKey
 {
-  int set_kind GNUNET_PACKED;
+  enum SetKind set_kind GNUNET_PACKED;
+  /**
+   * Repetition counter.
+   */
   int k1 GNUNET_PACKED;
+  /**
+   * Leader (or 0).
+   */
   int k2 GNUNET_PACKED;
 };
 
@@ -112,9 +162,9 @@ struct SetEntry
 {
   struct SetKey key;
   struct GNUNET_SET_Handle *h;
+
   /**
-   * GNUNET_YES if the set resulted
-   * from applying a referendum with contested
+   * #GNUNET_YES if the set resulted from applying a referendum with contested
    * elements.
    */
   int is_contested;
@@ -123,14 +173,16 @@ struct SetEntry
 
 struct DiffKey
 {
-  int diff_kind GNUNET_PACKED;
+  enum DiffKind diff_kind GNUNET_PACKED;
+
   int k1 GNUNET_PACKED;
+
   int k2 GNUNET_PACKED;
 };
 
 struct RfnKey
 {
-  int rfn_kind GNUNET_PACKED;
+  enum RfnKind rfn_kind GNUNET_PACKED;
   int k1 GNUNET_PACKED;
   int k2 GNUNET_PACKED;
 };
@@ -138,52 +190,6 @@ struct RfnKey
 
 GNUNET_NETWORK_STRUCT_END
 
-enum PhaseKind
-{
-  PHASE_KIND_ALL_TO_ALL,
-  PHASE_KIND_ALL_TO_ALL_2,
-  PHASE_KIND_GRADECAST_LEADER,
-  PHASE_KIND_GRADECAST_ECHO,
-  PHASE_KIND_GRADECAST_ECHO_GRADE,
-  PHASE_KIND_GRADECAST_CONFIRM,
-  PHASE_KIND_GRADECAST_CONFIRM_GRADE,
-  /**
-   * Apply a repetition of the all-to-all
-   * gradecast to the current set.
-   */
-  PHASE_KIND_APPLY_REP,
-  PHASE_KIND_FINISH,
-};
-
-
-enum SetKind
-{
-  SET_KIND_NONE = 0,
-  SET_KIND_CURRENT,
-  /**
-   * Last result set from a gradecast
-   */
-  SET_KIND_LAST_GRADECAST,
-  SET_KIND_LEADER_PROPOSAL,
-  SET_KIND_ECHO_RESULT,
-};
-
-enum DiffKind
-{
-  DIFF_KIND_NONE = 0,
-  DIFF_KIND_LEADER_PROPOSAL,
-  DIFF_KIND_LEADER_CONSENSUS,
-  DIFF_KIND_GRADECAST_RESULT,
-};
-
-enum RfnKind
-{
-  RFN_KIND_NONE = 0,
-  RFN_KIND_ECHO,
-  RFN_KIND_CONFIRM,
-  RFN_KIND_GRADECAST_RESULT
-};
-
 
 struct SetOpCls
 {
@@ -216,9 +222,13 @@ union TaskFuncCls
   struct FinishCls finish;
 };
 
+
 struct TaskEntry;
 
-typedef void (*TaskFunc) (struct TaskEntry *task);
+
+typedef void
+(*TaskFunc) (struct TaskEntry *task);
+
 
 /*
  * Node in the consensus task graph.
@@ -277,14 +287,12 @@ struct Step
   unsigned int subordinates_cap;
 
   /**
-   * Counter for the prerequisites of
-   * this step.
+   * Counter for the prerequisites of this step.
    */
   size_t pending_prereq;
 
-  /*
-   * Task that will run this step despite
-   * any pending prerequisites.
+  /**
+   * Task that will run this step despite any pending prerequisites.
    */
   struct GNUNET_SCHEDULER_Task *timeout_task;
 
@@ -292,28 +300,23 @@ struct Step
 
   unsigned int is_finished;
 
-  /*
-   * Synchrony round of the task.
-   * Determines the deadline for the task.
+  /**
+   * Synchrony round of the task.  Determines the deadline for the task.
    */
   unsigned int round;
 
   /**
-   * Human-readable name for
-   * the task, used for debugging.
+   * Human-readable name for the task, used for debugging.
    */
   char *debug_name;
 
   /**
-   * When we're doing an early finish, how should this step be
-   * treated?
-   * If GNUNET_YES, the step will be marked as finished
-   * without actually running its tasks.
-   * Otherwise, the step will still be run even after
-   * an early finish.
+   * When we're doing an early finish, how should this step be treated?  If
+   * #GNUNET_YES, the step will be marked as finished without actually running
+   * its tasks.  Otherwise, the step will still be run even after an early
+   * finish.
    *
-   * Note that a task may never be finished early if
-   * it is already running.
+   * Note that a task may never be finished early if it is already running.
    */
   int early_finishable;
 };
@@ -323,14 +326,13 @@ struct RfnElementInfo
 {
   const struct GNUNET_SET_Element *element;
 
-  /*
-   * GNUNET_YES if the peer votes for the proposal.
+  /**
+   * #GNUNET_YES if the peer votes for the proposal.
    */
   int *votes;
 
   /**
-   * Proposal for this element,
-   * can only be VOTE_ADD or VOTE_REMOVE.
+   * Proposal for this element, can only be #VOTE_ADD or #VOTE_REMOVE.
    */
   enum ReferendumVote proposal;
 };
@@ -638,7 +640,7 @@ debug_str_element (const struct GNUNET_SET_Element *el)
 
 
 static const char *
-debug_str_task_key (struct TaskKey *tk)
+debug_str_task_key (const struct TaskKey *tk)
 {
   static char buf[256];
 
@@ -652,7 +654,7 @@ debug_str_task_key (struct TaskKey *tk)
 
 
 static const char *
-debug_str_diff_key (struct DiffKey *dk)
+debug_str_diff_key (const struct DiffKey *dk)
 {
   static char buf[256];
 
@@ -671,8 +673,9 @@ debug_str_set_key (const struct SetKey *sk)
 
   snprintf (buf, sizeof(buf),
             "SetKey kind=%s, k1=%d, k2=%d",
-            setname (sk->set_kind), sk->k1, sk->k2);
-
+            setname (sk->set_kind),
+            sk->k1,
+            sk->k2);
   return buf;
 }
 
@@ -684,8 +687,9 @@ debug_str_rfn_key (const struct RfnKey *rk)
 
   snprintf (buf, sizeof(buf),
             "RfnKey kind=%s, k1=%d, k2=%d",
-            rfnname (rk->rfn_kind), rk->k1, rk->k2);
-
+            rfnname (rk->rfn_kind),
+            rk->k1,
+            rk->k2);
   return buf;
 }
 
@@ -730,13 +734,15 @@ send_to_client_iter (void *cls,
                 session->local_peer_idx,
                 debug_str_element (element));
 
-    ev = GNUNET_MQ_msg_extra (m, element->size - sizeof(struct
-                                                        ConsensusElement),
+    ev = GNUNET_MQ_msg_extra (m,
+                              element->size - sizeof(struct ConsensusElement),
                               GNUNET_MESSAGE_TYPE_CONSENSUS_CLIENT_RECEIVED_ELEMENT);
     m->element_type = ce->payload_type;
-    GNUNET_memcpy (&m[1], &ce[1], element->size - sizeof(struct
-                                                         ConsensusElement));
-    GNUNET_MQ_send (session->client_mq, ev);
+    GNUNET_memcpy (&m[1],
+                   &ce[1],
+                   element->size - sizeof(struct ConsensusElement));
+    GNUNET_MQ_send (session->client_mq,
+                    ev);
   }
   else
   {
@@ -745,14 +751,16 @@ send_to_client_iter (void *cls,
                 session->local_peer_idx);
     ev = GNUNET_MQ_msg_header (
       GNUNET_MESSAGE_TYPE_CONSENSUS_CLIENT_CONCLUDE_DONE);
-    GNUNET_MQ_send (session->client_mq, ev);
+    GNUNET_MQ_send (session->client_mq,
+                    ev);
   }
   return GNUNET_YES;
 }
 
 
 static struct SetEntry *
-lookup_set (struct ConsensusSession *session, struct SetKey *key)
+lookup_set (struct ConsensusSession *session,
+            const struct SetKey *key)
 {
   struct GNUNET_HashCode hash;
 
@@ -762,13 +770,17 @@ lookup_set (struct ConsensusSession *session, struct SetKey *key)
               debug_str_set_key (key));
 
   GNUNET_assert (SET_KIND_NONE != key->set_kind);
-  GNUNET_CRYPTO_hash (key, sizeof(struct SetKey), &hash);
-  return GNUNET_CONTAINER_multihashmap_get (session->setmap, &hash);
+  GNUNET_CRYPTO_hash (key,
+                      sizeof(struct SetKey),
+                      &hash);
+  return GNUNET_CONTAINER_multihashmap_get (session->setmap,
+                                            &hash);
 }
 
 
 static struct DiffEntry *
-lookup_diff (struct ConsensusSession *session, struct DiffKey *key)
+lookup_diff (struct ConsensusSession *session,
+             const struct DiffKey *key)
 {
   struct GNUNET_HashCode hash;
 
@@ -776,15 +788,18 @@ lookup_diff (struct ConsensusSession *session, struct DiffKey *key)
               "P%u: looking up diff {%s}\n",
               session->local_peer_idx,
               debug_str_diff_key (key));
-
   GNUNET_assert (DIFF_KIND_NONE != key->diff_kind);
-  GNUNET_CRYPTO_hash (key, sizeof(struct DiffKey), &hash);
-  return GNUNET_CONTAINER_multihashmap_get (session->diffmap, &hash);
+  GNUNET_CRYPTO_hash (key,
+                      sizeof(struct DiffKey),
+                      &hash);
+  return GNUNET_CONTAINER_multihashmap_get (session->diffmap,
+                                            &hash);
 }
 
 
 static struct ReferendumEntry *
-lookup_rfn (struct ConsensusSession *session, struct RfnKey *key)
+lookup_rfn (struct ConsensusSession *session,
+            const struct RfnKey *key)
 {
   struct GNUNET_HashCode hash;
 
@@ -792,10 +807,12 @@ lookup_rfn (struct ConsensusSession *session, struct RfnKey *key)
               "P%u: looking up rfn {%s}\n",
               session->local_peer_idx,
               debug_str_rfn_key (key));
-
   GNUNET_assert (RFN_KIND_NONE != key->rfn_kind);
-  GNUNET_CRYPTO_hash (key, sizeof(struct RfnKey), &hash);
-  return GNUNET_CONTAINER_multihashmap_get (session->rfnmap, &hash);
+  GNUNET_CRYPTO_hash (key,
+                      sizeof(struct RfnKey),
+                      &hash);
+  return GNUNET_CONTAINER_multihashmap_get (session->rfnmap,
+                                            &hash);
 }
 
 
@@ -829,7 +846,8 @@ diff_insert (struct DiffEntry *diff,
     di->element = GNUNET_SET_element_dup (element);
     GNUNET_assert (GNUNET_OK ==
                    GNUNET_CONTAINER_multihashmap_put (diff->changes,
-                                                      &hash, di,
+                                                      &hash,
+                                                      di,
                                                       GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST));
   }
 
@@ -860,11 +878,10 @@ rfn_contest (struct ReferendumEntry *rfn,
 static uint16_t
 rfn_noncontested (struct ReferendumEntry *rfn)
 {
-  uint16_t i;
   uint16_t ret;
 
   ret = 0;
-  for (i = 0; i < rfn->num_peers; i++)
+  for (uint16_t i = 0; i < rfn->num_peers; i++)
     if ((GNUNET_YES == rfn->peer_commited[i]) && (GNUNET_NO ==
                                                   rfn->peer_contested[i]))
       ret++;
@@ -993,7 +1010,8 @@ set_result_cb (void *cls,
 
   if (SET_KIND_NONE != setop->output_set.set_kind)
   {
-    output_set = lookup_set (session, &setop->output_set);
+    output_set = lookup_set (session,
+                             &setop->output_set);
     GNUNET_assert (NULL != output_set);
   }
 
@@ -1226,8 +1244,8 @@ struct Evilness
 
 
 static int
-parse_evilness_cram_subtype (const char *evil_subtype_str, struct
-                             Evilness *evil)
+parse_evilness_cram_subtype (const char *evil_subtype_str,
+                             struct Evilness *evil)
 {
   if (0 == strcmp ("replace", evil_subtype_str))
   {
@@ -1360,8 +1378,7 @@ cleanup:
 
 
 /**
- * Commit the appropriate set for a
- * task.
+ * Commit the appropriate set for a task.
  */
 static void
 commit_set (struct ConsensusSession *session,
@@ -1379,6 +1396,7 @@ commit_set (struct ConsensusSession *session,
   {
     struct GNUNET_SET_Element element;
     struct ConsensusElement ce = { 0 };
+
     ce.marker = CONSENSUS_MARKER_CONTESTED;
     element.data = &ce;
     element.size = sizeof(struct ConsensusElement);
@@ -1405,7 +1423,6 @@ commit_set (struct ConsensusSession *session,
 
 #ifdef EVIL
   {
-    unsigned int i;
     struct Evilness evil;
 
     get_evilness (session, &evil);
@@ -1444,7 +1461,7 @@ commit_set (struct ConsensusSession *session,
         GNUNET_SET_commit (setop->op, set->h);
         break;
       }
-      for (i = 0; i < evil.num; i++)
+      for (unsigned int i = 0; i < evil.num; i++)
       {
         struct GNUNET_SET_Element element;
         struct ConsensusStuffedElement se = {
@@ -1504,12 +1521,14 @@ commit_set (struct ConsensusSession *session,
       }
       else
       {
-        GNUNET_SET_commit (setop->op, set->h);
+        GNUNET_SET_commit (setop->op,
+                           set->h);
       }
       break;
 
     case EVILNESS_NONE:
-      GNUNET_SET_commit (setop->op, set->h);
+      GNUNET_SET_commit (setop->op,
+                         set->h);
       break;
     }
   }
@@ -1536,11 +1555,12 @@ put_diff (struct ConsensusSession *session,
 {
   struct GNUNET_HashCode hash;
 
-  GNUNET_assert (NULL != diff);
-
-  GNUNET_CRYPTO_hash (&diff->key, sizeof(struct DiffKey), &hash);
+  GNUNET_CRYPTO_hash (&diff->key,
+                      sizeof(struct DiffKey),
+                      &hash);
   GNUNET_assert (GNUNET_OK ==
-                 GNUNET_CONTAINER_multihashmap_put (session->diffmap, &hash,
+                 GNUNET_CONTAINER_multihashmap_put (session->diffmap,
+                                                    &hash,
                                                     diff,
                                                     GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
 }
@@ -1553,14 +1573,16 @@ put_set (struct ConsensusSession *session,
   struct GNUNET_HashCode hash;
 
   GNUNET_assert (NULL != set->h);
-
   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
               "Putting set %s\n",
               debug_str_set_key (&set->key));
-
-  GNUNET_CRYPTO_hash (&set->key, sizeof(struct SetKey), &hash);
+  GNUNET_CRYPTO_hash (&set->key,
+                      sizeof(struct SetKey),
+                      &hash);
   GNUNET_assert (GNUNET_SYSERR !=
-                 GNUNET_CONTAINER_multihashmap_put (session->setmap, &hash, set,
+                 GNUNET_CONTAINER_multihashmap_put (session->setmap,
+                                                    &hash,
+                                                    set,
                                                     GNUNET_CONTAINER_MULTIHASHMAPOPTION_REPLACE));
 }
 
@@ -1573,7 +1595,9 @@ put_rfn (struct ConsensusSession *session,
 
   GNUNET_CRYPTO_hash (&rfn->key, sizeof(struct RfnKey), &hash);
   GNUNET_assert (GNUNET_OK ==
-                 GNUNET_CONTAINER_multihashmap_put (session->rfnmap, &hash, rfn,
+                 GNUNET_CONTAINER_multihashmap_put (session->rfnmap,
+                                                    &hash,
+                                                    rfn,
                                                     GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
 }
 
@@ -1616,18 +1640,20 @@ apply_diff_to_rfn (struct DiffEntry *diff,
 }
 
 
-struct DiffEntry *
-diff_create ()
+static struct DiffEntry *
+diff_create (void)
 {
   struct DiffEntry *d = GNUNET_new (struct DiffEntry);
 
-  d->changes = GNUNET_CONTAINER_multihashmap_create (8, GNUNET_NO);
+  d->changes = GNUNET_CONTAINER_multihashmap_create (8,
+                                                     GNUNET_NO);
 
   return d;
 }
 
 
-struct DiffEntry *
+#if 0
+static struct DiffEntry *
 diff_compose (struct DiffEntry *diff_1,
               struct DiffEntry *diff_2)
 {
@@ -1638,22 +1664,26 @@ diff_compose (struct DiffEntry *diff_1,
   diff_new = diff_create ();
 
   iter = GNUNET_CONTAINER_multihashmap_iterator_create (diff_1->changes);
-  while (GNUNET_YES == GNUNET_CONTAINER_multihashmap_iterator_next (iter, NULL,
-                                                                    (const
-                                                                     void **) &
-                                                                    di))
+  while (GNUNET_YES ==
+         GNUNET_CONTAINER_multihashmap_iterator_next (iter,
+                                                      NULL,
+                                                      (const void **) &di))
   {
-    diff_insert (diff_new, di->weight, di->element);
+    diff_insert (diff_new,
+                 di->weight,
+                 di->element);
   }
   GNUNET_CONTAINER_multihashmap_iterator_destroy (iter);
 
   iter = GNUNET_CONTAINER_multihashmap_iterator_create (diff_2->changes);
-  while (GNUNET_YES == GNUNET_CONTAINER_multihashmap_iterator_next (iter, NULL,
-                                                                    (const
-                                                                     void **) &
-                                                                    di))
+  while (GNUNET_YES ==
+         GNUNET_CONTAINER_multihashmap_iterator_next (iter,
+                                                      NULL,
+                                                      (const void **) &di))
   {
-    diff_insert (diff_new, di->weight, di->element);
+    diff_insert (diff_new,
+                 di->weight,
+                 di->element);
   }
   GNUNET_CONTAINER_multihashmap_iterator_destroy (iter);
 
@@ -1661,6 +1691,9 @@ diff_compose (struct DiffEntry *diff_1,
 }
 
 
+#endif
+
+
 struct ReferendumEntry *
 rfn_create (uint16_t size)
 {
@@ -1701,14 +1734,13 @@ rfn_majority (const struct ReferendumEntry *rfn,
 {
   uint16_t votes_yes = 0;
   uint16_t num_commited = 0;
-  uint16_t i;
 
   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
               "Computing rfn majority for element %s of rfn {%s}\n",
               debug_str_element (ri->element),
               debug_str_rfn_key (&rfn->key));
 
-  for (i = 0; i < rfn->num_peers; i++)
+  for (uint16_t i = 0; i < rfn->num_peers; i++)
   {
     if (GNUNET_NO == rfn->peer_commited[i])
       continue;
@@ -1739,7 +1771,8 @@ struct SetCopyCls
 
 
 static void
-set_copy_cb (void *cls, struct GNUNET_SET_Handle *copy)
+set_copy_cb (void *cls,
+             struct GNUNET_SET_Handle *copy)
 {
   struct SetCopyCls *scc = cls;
   struct TaskEntry *task = scc->task;
@@ -1821,8 +1854,6 @@ set_mutation_done (void *cls)
 static void
 try_finish_step_early (struct Step *step)
 {
-  unsigned int i;
-
   if (GNUNET_YES == step->is_running)
     return;
   if (GNUNET_YES == step->is_finished)
@@ -1838,7 +1869,7 @@ try_finish_step_early (struct Step *step)
               step->debug_name);
 #endif
 
-  for (i = 0; i < step->subordinates_len; i++)
+  for (unsigned int i = 0; i < step->subordinates_len; i++)
   {
     GNUNET_assert (step->subordinates[i]->pending_prereq > 0);
     step->subordinates[i]->pending_prereq--;
@@ -1859,8 +1890,6 @@ try_finish_step_early (struct Step *step)
 static void
 finish_step (struct Step *step)
 {
-  unsigned int i;
-
   GNUNET_assert (step->finished_tasks == step->tasks_len);
   GNUNET_assert (GNUNET_YES == step->is_running);
   GNUNET_assert (GNUNET_NO == step->is_finished);
@@ -1872,7 +1901,7 @@ finish_step (struct Step *step)
               step->subordinates_len);
 #endif
 
-  for (i = 0; i < step->subordinates_len; i++)
+  for (unsigned int i = 0; i < step->subordinates_len; i++)
   {
     GNUNET_assert (step->subordinates[i]->pending_prereq > 0);
     step->subordinates[i]->pending_prereq--;
@@ -1918,7 +1947,9 @@ task_start_apply_round (struct TaskEntry *task)
   set_out = lookup_set (session, &sk_out);
   if (NULL == set_out)
   {
-    create_set_copy_for_task (task, &sk_in, &sk_out);
+    create_set_copy_for_task (task,
+                              &sk_in,
+                              &sk_out);
     return;
   }
 
@@ -2162,7 +2193,9 @@ task_start_reconcile (struct TaskEntry *task)
        we clone the input set. */
     if (NULL == lookup_set (session, &setop->output_set))
     {
-      create_set_copy_for_task (task, &setop->input_set, &setop->output_set);
+      create_set_copy_for_task (task,
+                                &setop->input_set,
+                                &setop->output_set);
       return;
     }
   }
@@ -2212,11 +2245,8 @@ task_start_reconcile (struct TaskEntry *task)
                 "P%u: Looking up set {%s} to run remote union\n",
                 session->local_peer_idx,
                 debug_str_set_key (&setop->input_set));
-
     rcm.header.type = htons (GNUNET_MESSAGE_TYPE_CONSENSUS_P2P_ROUND_CONTEXT);
-    rcm.header.size = htons (sizeof(struct
-                                    GNUNET_CONSENSUS_RoundContextMessage));
-
+    rcm.header.size = htons (sizeof(rcm));
     rcm.kind = htons (task->key.kind);
     rcm.peer1 = htons (task->key.peer1);
     rcm.peer2 = htons (task->key.peer2);
@@ -2227,8 +2257,9 @@ task_start_reconcile (struct TaskEntry *task)
     GNUNET_assert (NULL == setop->op);
     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
                 "P%u: initiating set op with P%u, our set is %s\n",
-                session->local_peer_idx, task->key.peer2, debug_str_set_key (
-                  &setop->input_set));
+                session->local_peer_idx,
+                task->key.peer2,
+                debug_str_set_key (&setop->input_set));
 
     struct GNUNET_SET_Option opts[] = {
       { GNUNET_SET_OPTION_BYZANTINE, { .num = session->lower_bound } },
@@ -2286,15 +2317,17 @@ task_start_eval_echo (struct TaskEntry *task)
   output_set = lookup_set (session, &sk_out);
   if (NULL == output_set)
   {
-    create_set_copy_for_task (task, &sk_in, &sk_out);
+    create_set_copy_for_task (task,
+                              &sk_in,
+                              &sk_out);
     return;
   }
 
-
   {
     // FIXME: should be marked as a shallow copy, so
     // we can destroy everything correctly
     struct SetEntry *last_set = GNUNET_new (struct SetEntry);
+
     last_set->h = output_set->h;
     last_set->key = (struct SetKey) { SET_KIND_LAST_GRADECAST };
     put_set (session, last_set);
@@ -2306,13 +2339,10 @@ task_start_eval_echo (struct TaskEntry *task)
 
   progress_cls = GNUNET_new (struct SetMutationProgressCls);
   progress_cls->task = task;
-
   rk_in = (struct RfnKey) { RFN_KIND_ECHO, task->key.repetition,
                             task->key.leader };
   input_rfn = lookup_rfn (session, &rk_in);
-
   GNUNET_assert (NULL != input_rfn);
-
   iter = GNUNET_CONTAINER_multihashmap_iterator_create (
     input_rfn->rfn_elements);
   GNUNET_assert (NULL != iter);
@@ -2334,7 +2364,8 @@ task_start_eval_echo (struct TaskEntry *task)
          can't simply send "nothing" for the value.  Thus we mark our 'confirm'
          reconciliation as contested.  Other peers might not know that the
          leader is faulty, thus we still re-distribute in the confirmation
-         round. */output_set->is_contested = GNUNET_YES;
+         round. *///
+      output_set->is_contested = GNUNET_YES;
     }
 
     switch (majority_vote)
@@ -2384,29 +2415,27 @@ task_start_finish (struct TaskEntry *task)
   struct SetEntry *final_set;
   struct ConsensusSession *session = task->step->session;
 
-  final_set = lookup_set (session, &task->cls.finish.input_set);
-
+  final_set = lookup_set (session,
+                          &task->cls.finish.input_set);
   GNUNET_assert (NULL != final_set);
-
-
   GNUNET_SET_iterate (final_set->h,
-                      send_to_client_iter,
+                      &send_to_client_iter,
                       task);
 }
 
 
 static void
-start_task (struct ConsensusSession *session, struct TaskEntry *task)
+start_task (struct ConsensusSession *session,
+            struct TaskEntry *task)
 {
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "P%u: starting task {%s}\n",
-              session->local_peer_idx, debug_str_task_key (&task->key));
-
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "P%u: starting task {%s}\n",
+              session->local_peer_idx,
+              debug_str_task_key (&task->key));
   GNUNET_assert (GNUNET_NO == task->is_started);
   GNUNET_assert (GNUNET_NO == task->is_finished);
   GNUNET_assert (NULL != task->start);
-
   task->start (task);
-
   task->is_started = GNUNET_YES;
 }
 
@@ -2427,8 +2456,6 @@ run_ready_steps (struct ConsensusSession *session)
     if ((GNUNET_NO == step->is_running) && (0 == step->pending_prereq) &&
         (GNUNET_NO == step->is_finished))
     {
-      size_t i;
-
       GNUNET_assert (0 == step->finished_tasks);
 
 #ifdef GNUNET_EXTRA_LOGGING
@@ -2440,7 +2467,7 @@ run_ready_steps (struct ConsensusSession *session)
 #endif
 
       step->is_running = GNUNET_YES;
-      for (i = 0; i < step->tasks_len; i++)
+      for (size_t i = 0; i < step->tasks_len; i++)
         start_task (session, step->tasks[i]);
 
       /* Sometimes there is no task to trigger finishing the step, so we have to do it here. */
@@ -2463,9 +2490,7 @@ finish_task (struct TaskEntry *task)
 {
   GNUNET_assert (GNUNET_NO == task->is_finished);
   task->is_finished = GNUNET_YES;
-
   task->step->finished_tasks++;
-
   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
               "P%u: Finishing Task {%s} (now %u/%u tasks finished in step)\n",
               task->step->session->local_peer_idx,
@@ -2486,12 +2511,10 @@ finish_task (struct TaskEntry *task)
  * @return index of peer, -1 if peer is not in session
  */
 static int
-get_peer_idx (const struct GNUNET_PeerIdentity *peer, const struct
-              ConsensusSession *session)
+get_peer_idx (const struct GNUNET_PeerIdentity *peer,
+              const struct ConsensusSession *session)
 {
-  int i;
-
-  for (i = 0; i < session->num_peers; i++)
+  for (int i = 0; i < session->num_peers; i++)
     if (0 == GNUNET_memcmp (peer, &session->peers[i]))
       return i;
   return -1;
@@ -2528,14 +2551,15 @@ compute_global_id (struct ConsensusSession *session,
 
 
 /**
- * Compare two peer identities.
+ * Compare two peer identities (for qsort()).
  *
  * @param h1 some peer identity
  * @param h2 some peer identity
  * @return 1 if h1 > h2, -1 if h1 < h2 and 0 if h1 == h2.
  */
 static int
-peer_id_cmp (const void *h1, const void *h2)
+peer_id_cmp (const void *h1,
+             const void *h2)
 {
   return memcmp (h1, h2, sizeof(struct GNUNET_PeerIdentity));
 }
@@ -2549,9 +2573,9 @@ peer_id_cmp (const void *h1, const void *h2)
  * @param join_msg join message with the list of peers participating at the end
  */
 static void
-initialize_session_peer_list (struct ConsensusSession *session,
-                              const struct
-                              GNUNET_CONSENSUS_JoinMessage *join_msg)
+initialize_session_peer_list (
+  struct ConsensusSession *session,
+  const struct GNUNET_CONSENSUS_JoinMessage *join_msg)
 {
   const struct GNUNET_PeerIdentity *msg_peers
     = (const struct GNUNET_PeerIdentity *) &join_msg[1];
@@ -2578,29 +2602,31 @@ initialize_session_peer_list (struct ConsensusSession *session,
                                      struct GNUNET_PeerIdentity);
   if (GNUNET_NO == local_peer_in_list)
     session->peers[session->num_peers - 1] = my_peer;
-
   GNUNET_memcpy (session->peers,
                  msg_peers,
-                 ntohl (join_msg->num_peers) * sizeof(struct
-                                                      GNUNET_PeerIdentity));
+                 ntohl (join_msg->num_peers)
+                 * sizeof(struct GNUNET_PeerIdentity));
   qsort (session->peers,
          session->num_peers,
-         sizeof(struct GNUNET_PeerIdentity),
+         sizeof (struct GNUNET_PeerIdentity),
          &peer_id_cmp);
 }
 
 
 static struct TaskEntry *
-lookup_task (struct ConsensusSession *session,
-             struct TaskKey *key)
+lookup_task (const struct ConsensusSession *session,
+             const struct TaskKey *key)
 {
   struct GNUNET_HashCode hash;
 
-
-  GNUNET_CRYPTO_hash (key, sizeof(struct TaskKey), &hash);
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Looking up task hash %s\n",
+  GNUNET_CRYPTO_hash (key,
+                      sizeof(struct TaskKey),
+                      &hash);
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "Looking up task hash %s\n",
               GNUNET_h2s (&hash));
-  return GNUNET_CONTAINER_multihashmap_get (session->taskmap, &hash);
+  return GNUNET_CONTAINER_multihashmap_get (session->taskmap,
+                                            &hash);
 }
 
 
@@ -2695,7 +2721,7 @@ set_listen_cb (void *cls,
   task->cls.setop.op = GNUNET_SET_accept (request,
                                           GNUNET_SET_RESULT_SYMMETRIC,
                                           opts,
-                                          set_result_cb,
+                                          &set_result_cb,
                                           task);
 
   /* If the task hasn't been started yet,
@@ -2716,11 +2742,8 @@ put_task (struct GNUNET_CONTAINER_MultiHashMap *taskmap,
   struct Step *s;
 
   GNUNET_assert (NULL != t->step);
-
   t = GNUNET_memdup (t, sizeof(struct TaskEntry));
-
   s = t->step;
-
   if (s->tasks_len == s->tasks_cap)
   {
     unsigned int target_size = 3 * (s->tasks_cap + 1) / 2;
@@ -2739,9 +2762,13 @@ put_task (struct GNUNET_CONTAINER_MultiHashMap *taskmap,
   s->tasks[s->tasks_len] = t;
   s->tasks_len++;
 
-  GNUNET_CRYPTO_hash (&t->key, sizeof(struct TaskKey), &round_hash);
+  GNUNET_CRYPTO_hash (&t->key,
+                      sizeof(struct TaskKey),
+                      &round_hash);
   GNUNET_assert (GNUNET_OK ==
-                 GNUNET_CONTAINER_multihashmap_put (taskmap, &round_hash, t,
+                 GNUNET_CONTAINER_multihashmap_put (taskmap,
+                                                    &round_hash,
+                                                    t,
                                                     GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
 }
 
@@ -2762,7 +2789,9 @@ install_step_timeouts (struct ConsensusSession *session)
  * Arrange two peers in some canonical order.
  */
 static void
-arrange_peers (uint16_t *p1, uint16_t *p2, uint16_t n)
+arrange_peers (uint16_t *p1,
+               uint16_t *p2,
+               uint16_t n)
 {
   uint16_t a;
   uint16_t b;
@@ -2800,7 +2829,8 @@ arrange_peers (uint16_t *p1, uint16_t *p2, uint16_t n)
  * Record @a dep as a dependency of @a step.
  */
 static void
-step_depend_on (struct Step *step, struct Step *dep)
+step_depend_on (struct Step *step,
+                struct Step *dep)
 {
   /* We're not checking for cyclic dependencies,
      but this is a cheap sanity check. */
@@ -2839,7 +2869,9 @@ step_depend_on (struct Step *step, struct Step *dep)
 
 
 static struct Step *
-create_step (struct ConsensusSession *session, int round, int early_finishable)
+create_step (struct ConsensusSession *session,
+             int round,
+             int early_finishable)
 {
   struct Step *step;
 
@@ -2855,8 +2887,7 @@ create_step (struct ConsensusSession *session, int round, int early_finishable)
 
 
 /**
- * Construct the task graph for a single
- * gradecast.
+ * Construct the task graph for a single gradecast.
  */
 static void
 construct_task_graph_gradecast (struct ConsensusSession *session,
@@ -2867,35 +2898,32 @@ construct_task_graph_gradecast (struct ConsensusSession *session,
 {
   uint16_t n = session->num_peers;
   uint16_t me = session->local_peer_idx;
-
   uint16_t p1;
   uint16_t p2;
-
   /* The task we're currently setting up. */
   struct TaskEntry task;
-
   struct Step *step;
   struct Step *prev_step;
-
   uint16_t round;
 
-  unsigned int k;
-
   round = step_before->round + 1;
 
   /* gcast step 1: leader disseminates */
-
-  step = create_step (session, round, GNUNET_YES);
-
+  step = create_step (session,
+                      round,
+                      GNUNET_YES);
 #ifdef GNUNET_EXTRA_LOGGING
-  GNUNET_asprintf (&step->debug_name, "disseminate leader %u rep %u", lead,
+  GNUNET_asprintf (&step->debug_name,
+                   "disseminate leader %u rep %u",
+                   lead,
                    rep);
 #endif
-  step_depend_on (step, step_before);
+  step_depend_on (step,
+                  step_before);
 
   if (lead == me)
   {
-    for (k = 0; k < n; k++)
+    for (unsigned int k = 0; k < n; k++)
     {
       if (k == me)
         continue;
@@ -2952,13 +2980,19 @@ construct_task_graph_gradecast (struct ConsensusSession *session,
   /* gcast phase 2: echo */
   prev_step = step;
   round += 1;
-  step = create_step (session, round, GNUNET_YES);
+  step = create_step (session,
+                      round,
+                      GNUNET_YES);
 #ifdef GNUNET_EXTRA_LOGGING
-  GNUNET_asprintf (&step->debug_name, "echo leader %u rep %u", lead, rep);
+  GNUNET_asprintf (&step->debug_name,
+                   "echo leader %u rep %u",
+                   lead,
+                   rep);
 #endif
-  step_depend_on (step, prev_step);
+  step_depend_on (step,
+                  prev_step);
 
-  for (k = 0; k < n; k++)
+  for (unsigned int k = 0; k < n; k++)
   {
     p1 = k;
     p2 = me;
@@ -3001,7 +3035,7 @@ construct_task_graph_gradecast (struct ConsensusSession *session,
   step_depend_on (step, prev_step);
 
   /* gcast phase 3: confirmation and grading */
-  for (k = 0; k < n; k++)
+  for (unsigned int k = 0; k < n; k++)
   {
     p1 = k;
     p2 = me;
@@ -3050,22 +3084,15 @@ construct_task_graph (struct ConsensusSession *session)
 {
   uint16_t n = session->num_peers;
   uint16_t t = n / 3;
-
   uint16_t me = session->local_peer_idx;
-
   /* The task we're currently setting up. */
   struct TaskEntry task;
-
   /* Current leader */
   unsigned int lead;
-
   struct Step *step;
   struct Step *prev_step;
-
   unsigned int round = 0;
 
-  unsigned int i;
-
   // XXX: introduce first step,
   // where we wait for all insert acks
   // from the set service
@@ -3082,7 +3109,7 @@ construct_task_graph (struct ConsensusSession *session)
   step->debug_name = GNUNET_strdup ("all to all");
 #endif
 
-  for (i = 0; i < n; i++)
+  for (unsigned int i = 0; i < n; i++)
   {
     uint16_t p1;
     uint16_t p2;
@@ -3111,7 +3138,7 @@ construct_task_graph (struct ConsensusSession *session)
   step_depend_on (step, prev_step);
 
 
-  for (i = 0; i < n; i++)
+  for (unsigned int i = 0; i < n; i++)
   {
     uint16_t p1;
     uint16_t p2;
@@ -3140,7 +3167,7 @@ construct_task_graph (struct ConsensusSession *session)
   /* Byzantine union */
 
   /* sequential repetitions of the gradecasts */
-  for (i = 0; i < t + 1; i++)
+  for (unsigned int i = 0; i < t + 1; i++)
   {
     struct Step *step_rep_start;
     struct Step *step_rep_end;
@@ -3243,9 +3270,9 @@ handle_client_join (void *cls,
        NULL != other_session;
        other_session = other_session->next)
   {
-    if ((other_session != session) &&
-        (0 == GNUNET_CRYPTO_hash_cmp (&session->global_id,
-                                      &other_session->global_id)))
+    if ( (other_session != session) &&
+         (0 == GNUNET_CRYPTO_hash_cmp (&session->global_id,
+                                       &other_session->global_id)) )
       break;
   }
 
@@ -3262,9 +3289,9 @@ handle_client_join (void *cls,
               GNUNET_h2s (&m->session_id),
               session->num_peers,
               session->local_peer_idx,
-              GNUNET_STRINGS_relative_time_to_string
-                (GNUNET_TIME_absolute_get_difference (session->conclude_start,
-                                                      session->conclude_deadline),
+              GNUNET_STRINGS_relative_time_to_string (
+                GNUNET_TIME_absolute_get_difference (session->conclude_start,
+                                                     session->conclude_deadline),
                 GNUNET_YES));
 
   session->set_listener
@@ -3309,13 +3336,6 @@ handle_client_join (void *cls,
 }
 
 
-static void
-client_insert_done (void *cls)
-{
-  // FIXME: implement
-}
-
-
 /**
  * Called when a client performs an insert operation.
  *
@@ -3352,19 +3372,13 @@ handle_client_insert (void *cls,
     GNUNET_SERVICE_client_drop (session->client);
     return;
   }
-
-  element_size = ntohs (msg->header.size) - sizeof(struct
-                                                   GNUNET_CONSENSUS_ElementMessage);
+  element_size = ntohs (msg->header.size) - sizeof(*msg);
   ce = GNUNET_malloc (sizeof(struct ConsensusElement) + element_size);
-  GNUNET_memcpy (&ce[1], &msg[1], element_size);
+  GNUNET_memcpy (&ce[1],
+                 &msg[1],
+                 element_size);
   ce->payload_type = msg->element_type;
 
-  struct GNUNET_SET_Element element = {
-    .element_type = GNUNET_BLOCK_TYPE_CONSENSUS_ELEMENT,
-    .size = sizeof(struct ConsensusElement) + element_size,
-    .data = ce,
-  };
-
   {
     struct SetKey key = { SET_KIND_CURRENT, 0, 0 };
     struct SetEntry *entry;
@@ -3376,19 +3390,25 @@ handle_client_insert (void *cls,
   }
 
   session->num_client_insert_pending++;
-  GNUNET_SET_add_element (initial_set,
-                          &element,
-                          &client_insert_done,
-                          session);
 
-#ifdef GNUNET_EXTRA_LOGGING
   {
+    struct GNUNET_SET_Element element = {
+      .element_type = GNUNET_BLOCK_TYPE_CONSENSUS_ELEMENT,
+      .size = sizeof(struct ConsensusElement) + element_size,
+      .data = ce,
+    };
+
+    GNUNET_SET_add_element (initial_set,
+                            &element,
+                            NULL,
+                            NULL);
+#ifdef GNUNET_EXTRA_LOGGING
     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
                 "P%u: element %s added\n",
                 session->local_peer_idx,
                 debug_str_element (&element));
-  }
 #endif
+  }
   GNUNET_free (ce);
   GNUNET_SERVICE_client_continue (session->client);
 }
@@ -3513,10 +3533,10 @@ client_disconnect_cb (void *cls,
   GNUNET_CONTAINER_DLL_remove (sessions_head,
                                sessions_tail,
                                session);
-
   while (session->set_handles_head)
   {
     struct SetHandle *sh = session->set_handles_head;
+
     session->set_handles_head = sh->next;
     GNUNET_SET_destroy (sh->h);
     GNUNET_free (sh);
@@ -3528,8 +3548,8 @@ client_disconnect_cb (void *cls,
 /**
  * Define "main" method using service macro.
  */
-GNUNET_SERVICE_MAIN
-  ("consensus",
+GNUNET_SERVICE_MAIN (
+  "consensus",
   GNUNET_SERVICE_OPTION_NONE,
   &run,
   &client_connect_cb,
diff --git a/src/consensus/plugin_block_consensus.c b/src/consensus/plugin_block_consensus.c
index fb6da5bcd96732d86ebbe49a36580944477edb2b..cdac12ed5984189810a87e6c326d1fa3f2f41363 100644
--- a/src/consensus/plugin_block_consensus.c
+++ b/src/consensus/plugin_block_consensus.c
@@ -58,13 +58,12 @@ block_plugin_consensus_evaluate (void *cls,
                                  const void *reply_block,
                                  size_t reply_block_size)
 {
-  if (reply_block_size < sizeof(struct ConsensusElement))
-    return GNUNET_BLOCK_EVALUATION_RESULT_INVALID;
-
   const struct ConsensusElement *ce = reply_block;
 
-  if ((0 != ce->marker) ||
-      (0 == ce->payload_type))
+  if (reply_block_size < sizeof(struct ConsensusElement))
+    return GNUNET_BLOCK_EVALUATION_RESULT_INVALID;
+  if ( (0 != ce->marker) ||
+       (0 == ce->payload_type) )
     return GNUNET_BLOCK_EVALUATION_OK_MORE;
 
   return GNUNET_BLOCK_evaluate (ctx,
@@ -75,8 +74,8 @@ block_plugin_consensus_evaluate (void *cls,
                                 xquery,
                                 xquery_size,
                                 &ce[1],
-                                reply_block_size - sizeof(struct
-                                                          ConsensusElement));
+                                reply_block_size
+                                - sizeof(struct ConsensusElement));
 }
 
 
diff --git a/src/conversation/.gitignore b/src/conversation/.gitignore
new file mode 100644
index 0000000000000000000000000000000000000000..e74e259bf2a30dcc45fa00bc4ac35daff44aeb90
--- /dev/null
+++ b/src/conversation/.gitignore
@@ -0,0 +1,8 @@
+gnunet-service-conversation
+gnunet-conversation
+gnunet-conversation-test
+gnunet-helper-audio-playback
+gnunet-helper-audio-record
+test_conversation_api
+test_conversation_api_reject
+test_conversation_api_twocalls
diff --git a/src/conversation/build_gst_test.sh b/src/conversation/build_gst_test.sh
new file mode 100644
index 0000000000000000000000000000000000000000..1feb9e1c466dfa7950691c92b276c76ad4b77bc5
--- /dev/null
+++ b/src/conversation/build_gst_test.sh
@@ -0,0 +1,9 @@
+#!/bin/bash
+
+colorgcc  -DIS_MIC -g gnunet_gst_test.c gnunet_gst.c -o gnunet-helper-audio-record-experimental `pkg-config --cflags --libs gstreamer-app-1.0 gnunetutil gnunetconversation gnunetenv  gstreamer-app-1.0 gstreamer-1.0 gstreamer-audio-1.0 gstreamer-pbutils-1.0 gstreamer-video-1.0` -O0 -march=native  -Wno-unused-parameter -Wno-unused-variable -Wno-unused-function -Wno-conversion  -Wformat -Wformat-security -fstack-protector -D_FORTIFY_SOURCE=2 -std=c99  -D_GNU_SOURCE
+
+colorgcc -DIS_SPEAKER -g gnunet_gst_test.c gnunet_gst.c -o gnunet-helper-audio-playback-experimental `pkg-config --cflags --libs gstreamer-app-1.0 gnunetutil gnunetconversation gnunetenv  gstreamer-app-1.0 gstreamer-1.0 gstreamer-audio-1.0 gstreamer-pbutils-1.0 gstreamer-video-1.0` -O0 -march=native  -Wno-unused-parameter -Wno-unused-variable -Wno-unused-function -Wno-conversion  -Wformat -Wformat-security -fstack-protector -D_FORTIFY_SOURCE=2 -std=c99  -D_GNU_SOURCE
+
+
+
+#colorgcc  -g gnunet_gst_test.c gnunet_gst.c -o gnunet_gst_test `pkg-config --cflags --libs  gstreamer-app-1.0 gstreamer-1.0 gstreamer-audio-1.0 gstreamer-pbutils-1.0 gstreamer-video-1.0` -O0 -march=native -Wall -Wextra -Wno-unused-parameter -Wno-unused-variable -Wno-unused-function -Wno-conversion -Wpedantic -Wformat -Wformat-security -fstack-protector -D_FORTIFY_SOURCE=2 -std=c99  -D_GNU_SOURCE
diff --git a/src/conversation/displaydot.sh b/src/conversation/displaydot.sh
new file mode 100644
index 0000000000000000000000000000000000000000..16ee23409ee8bfaa54834c52cfc63440e6fc0fc6
--- /dev/null
+++ b/src/conversation/displaydot.sh
@@ -0,0 +1,3 @@
+#!/bin/sh
+dot -Tpng `ls -tr1 /tmp/*rec*.dot | tail -1` | display /dev/stdin &
+dot -Tpng `ls -tr1 /tmp/*play*.dot | tail -1` | display /dev/stdin &
diff --git a/src/conversation/gnunet_gst.h b/src/conversation/gnunet_gst.h
new file mode 100644
index 0000000000000000000000000000000000000000..479ae14b3904497e638ca6bf4ea2b2c9e76cda10
--- /dev/null
+++ b/src/conversation/gnunet_gst.h
@@ -0,0 +1,62 @@
+/*
+   This file is part of GNUnet.
+   Copyright (C) 2016 GNUnet e.V.
+
+   GNUnet is free software: you can redistribute it and/or modify it
+   under the terms of the GNU Affero General Public License as published
+   by the Free Software Foundation, either version 3 of the License,
+   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
+   Affero General Public License for more details.
+
+   You should have received a copy of the GNU Affero General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+     SPDX-License-Identifier: AGPL3.0-or-later
+ */
+/**
+ * @file conversation/gnunet_gst.c
+ * @brief FIXME
+ * @author Hark
+ */
+
+// which audiobackend we use
+//
+
+/*
+   int audiobackend = JACK;
+   int dropsilence = TRUE;
+   int enough = 0;
+   int usertp = TRUE;
+ */
+
+#define gst_element_factory_make(element, name) gst_element_factory_make_debug ( \
+    element, name);
+
+extern void pl_graph ();
+
+
+extern GstElement *
+gst_element_factory_make_debug (gchar *, gchar *);
+
+extern GstBin *
+get_audiobin (GNUNET_gstData *, int);
+
+extern GstBin *
+get_coder (GNUNET_gstData *, int);
+
+
+extern gboolean
+gnunet_gst_bus_call (GstBus *bus, GstMessage *msg, gpointer data);
+
+extern void
+gg_setup_gst_bus (GNUNET_gstData *d);
+
+extern void
+gg_load_configuration (GNUNET_gstData *d);
+
+extern GstFlowReturn
+on_appsink_new_sample (GstElement *, GNUNET_gstData *);
diff --git a/src/conversation/gnunet_gst_def.h b/src/conversation/gnunet_gst_def.h
new file mode 100644
index 0000000000000000000000000000000000000000..7bfcc5e532a6c12cbf0558d090b8a53485dfb37f
--- /dev/null
+++ b/src/conversation/gnunet_gst_def.h
@@ -0,0 +1,219 @@
+/*
+   This file is part of GNUnet.
+   Copyright (C) 2016 GNUnet e.V.
+
+   GNUnet is free software: you can redistribute it and/or modify it
+   under the terms of the GNU Affero General Public License as published
+   by the Free Software Foundation, either version 3 of the License,
+   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
+   Affero General Public License for more details.
+
+   You should have received a copy of the GNU Affero General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+     SPDX-License-Identifier: AGPL3.0-or-later
+ */
+/**
+ * @file conversation/gnunet_gst_def.h
+ * @brief FIXME
+ * @author Hark
+ */
+
+#include <getopt.h>
+#include <string.h>
+#include <stdio.h>
+#include <ctype.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <time.h>
+#include <regex.h>
+
+
+#include "platform.h"
+#include "gnunet_util_lib.h"
+#include "gnunet_protocols.h"
+// #include "gnunet/conversation.h" doesn't get installed
+#include "conversation.h"
+#include "gnunet_constants.h"
+#include "gnunet_core_service.h"
+#include "gnunet_common.h"
+
+/*
+ #include <gst/gst.h>
+ #include <gst/audio/gstaudiobasesrc.h>
+ #include <gst/app/gstappsrc.h>
+ */
+
+/* huh
+ #include <glib-2.0/glib.h>
+
+ #include <gstreamer-1.0/gst/gst.h>
+ #include <gstreamer-1.0/gst/pbutils/pbutils.h>
+ #include <gstreamer-1.0/gst/video/videooverlay.h>
+ #include <gstreamer-1.0/gst/audio/gstaudiobasesrc.h>
+ #include <gstreamer-1.0/gst/app/gstappsrc.h>
+ */
+
+#include <gst/gst.h>
+#include <gst/audio/gstaudiobasesrc.h>
+#include <gst/app/gstappsrc.h>
+#include <glib.h>
+#include <gst/app/gstappsink.h>
+
+// sockets
+#if HAVE_NETINET_IN_H
+#include <netinet/in.h>
+#endif
+#include <sys/socket.h>
+#include <arpa/inet.h>
+#include <netdb.h>
+
+#include <sys/types.h>
+#include <fcntl.h>
+
+
+// glib stuff
+// #include <glib.h>
+#include <glib-2.0/glib/gprintf.h>
+// #include <glib-unix.h>
+
+// static struct AudioMessage *audio_message;
+
+
+typedef struct GNUNET_gstData GNUNET_gstData;
+struct GNUNET_gstData
+{
+  // general
+  GstPipeline *pipeline;
+
+  // things
+  struct AudioMessage *audio_message;
+  struct GNUNET_MessageStreamTokenizer *stdin_mst;
+  GstElement *appsrc;
+  GstElement *appsink;
+  // settings
+  int audiobackend;
+  int dropsilence;
+  int usertp;
+  int pure_ogg;
+  char *jack_pp_in;
+  char *jack_pp_out;
+};
+
+
+#define DEBUG_READ_PURE_OGG 1
+#define DEBUG_RECORD_PURE_OGG 1
+
+
+/**
+ * How much data to read in one go
+ */
+#define MAXLINE 4096
+
+/**
+ * Max number of microseconds to buffer in audiosink.
+ * Default is 1000
+ */
+#define BUFFER_TIME 1000
+
+/**
+ * Min number of microseconds to buffer in audiosink.
+ * Default is 1000
+ */
+#define LATENCY_TIME 1000
+
+
+/**
+ * Number of channels.
+ * Must be one of the following (from libopusenc documentation):
+ * 1, 2
+ */
+#define OPUS_CHANNELS 1
+
+/**
+ * Maximal size of a single opus packet.
+ */
+#define MAX_PAYLOAD_SIZE (1024 / OPUS_CHANNELS)
+
+/**
+ * Size of a single frame fed to the encoder, in ms.
+ * Must be one of the following (from libopus documentation):
+ * 2.5, 5, 10, 20, 40 or 60
+ */
+#define OPUS_FRAME_SIZE 40
+
+/**
+ * Expected packet loss to prepare for, in percents.
+ */
+#define PACKET_LOSS_PERCENTAGE 1
+
+/**
+ * Set to 1 to enable forward error correction.
+ * Set to 0 to disable.
+ */
+#define INBAND_FEC_MODE 1
+
+/**
+ * Max number of microseconds to buffer in audiosource.
+ * Default is 200000
+ */
+#define BUFFER_TIME 1000 /* 1ms */
+
+/**
+ * Min number of microseconds to buffer in audiosource.
+ * Default is 10000
+ */
+#define LATENCY_TIME 1000 /* 1ms */
+
+/**
+ * Maximum delay in multiplexing streams, in ns.
+ * Setting this to 0 forces page flushing, which
+ * decreases delay, but increases overhead.
+ */
+#define OGG_MAX_DELAY 0
+
+/**
+ * Maximum delay for sending out a page, in ns.
+ * Setting this to 0 forces page flushing, which
+ * decreases delay, but increases overhead.
+ */
+#define OGG_MAX_PAGE_DELAY 0
+
+#define SAMPLING_RATE 48000
+
+enum
+{
+  AUTO,
+  JACK,
+  ALSA,
+  FAKE,
+  TEST
+};
+
+enum
+{
+  SOURCE,
+  SINK
+};
+
+enum
+{
+  ENCODER,
+  DECODER
+};
+
+enum
+{
+  FAIL,
+  OK
+};
+
+enum
+{
+  SPEAKER,
+  MICROPHONE
+};
diff --git a/src/conversation/mediahelper.conf b/src/conversation/mediahelper.conf
new file mode 100644
index 0000000000000000000000000000000000000000..85c051107440044f149c9ae1871eb0dd49847df9
--- /dev/null
+++ b/src/conversation/mediahelper.conf
@@ -0,0 +1,7 @@
+[MEDIAHELPER]
+AUDIOBACKEND = JACK
+REMOVESILENCE = NO
+USERTP  = NO
+NO_GN_HEADERS = NO
+JACK_PP_IN = mocp
+JACK_PP_OUT = system
diff --git a/src/conversation/test.sh b/src/conversation/test.sh
new file mode 100644
index 0000000000000000000000000000000000000000..20e82bc887f827c877d0127f0a5323eeea6aacdb
--- /dev/null
+++ b/src/conversation/test.sh
@@ -0,0 +1,4 @@
+#!/bin/sh
+
+export GST_DEBUG_DUMP_DOT_DIR=/tmp/ 
+GST_DEBUG_DUMP_DOT_DIR=/tmp/ ./gnunet-helper-audio-record |GST_DEBUG_DUMP_DOT_DIR=/tmp/ ./gnunet-helper-audio-playback
diff --git a/src/conversation/test_conversation_api.c b/src/conversation/test_conversation_api.c
index dbb742d913332f4df3de084c0462dabf43c71e38..b51186dc80e79b64753b52e133c5090ae15c2ab1 100644
--- a/src/conversation/test_conversation_api.c
+++ b/src/conversation/test_conversation_api.c
@@ -402,7 +402,8 @@ namestore_put_cont (void *cls, int32_t success, const char *emsg)
   GNUNET_assert (GNUNET_YES == success);
   GNUNET_assert (NULL == emsg);
   GNUNET_assert (NULL == op);
-  op = GNUNET_IDENTITY_create (id, "caller-ego", NULL, &caller_ego_create_cont, NULL);
+  op = GNUNET_IDENTITY_create (id, "caller-ego", NULL, &caller_ego_create_cont,
+                               NULL);
 }
 
 
@@ -483,7 +484,8 @@ run (void *cls,
   cfg = c;
   GNUNET_SCHEDULER_add_delayed (TIMEOUT, &end_test, NULL);
   id = GNUNET_IDENTITY_connect (cfg, &identity_cb, NULL);
-  op = GNUNET_IDENTITY_create (id, "phone-ego", NULL, &phone_ego_create_cont, NULL);
+  op = GNUNET_IDENTITY_create (id, "phone-ego", NULL, &phone_ego_create_cont,
+                               NULL);
   ns = GNUNET_NAMESTORE_connect (cfg);
 }
 
diff --git a/src/conversation/test_conversation_api_reject.c b/src/conversation/test_conversation_api_reject.c
index 855b21fd72f14665ef5d239a56fd7c6c3e11ca62..69fa9f1dcd5a50dbabbe04fab43c1123d03c449a 100644
--- a/src/conversation/test_conversation_api_reject.c
+++ b/src/conversation/test_conversation_api_reject.c
@@ -255,7 +255,8 @@ namestore_put_cont (void *cls, int32_t success, const char *emsg)
   GNUNET_assert (GNUNET_YES == success);
   GNUNET_assert (NULL == emsg);
   GNUNET_assert (NULL == op);
-  op = GNUNET_IDENTITY_create (id, "caller-ego", NULL, &caller_ego_create_cont, NULL);
+  op = GNUNET_IDENTITY_create (id, "caller-ego", NULL, &caller_ego_create_cont,
+                               NULL);
 }
 
 
@@ -336,7 +337,8 @@ run (void *cls,
   cfg = c;
   GNUNET_SCHEDULER_add_delayed (TIMEOUT, &end_test, NULL);
   id = GNUNET_IDENTITY_connect (cfg, &identity_cb, NULL);
-  op = GNUNET_IDENTITY_create (id, "phone-ego", NULL, &phone_ego_create_cont, NULL);
+  op = GNUNET_IDENTITY_create (id, "phone-ego", NULL, &phone_ego_create_cont,
+                               NULL);
   ns = GNUNET_NAMESTORE_connect (cfg);
 }
 
diff --git a/src/conversation/test_conversation_api_twocalls.c b/src/conversation/test_conversation_api_twocalls.c
index 6d434a3e1d6ab9ffbadaa4a652b420f72deb288c..83e8cb55acda0941f6dca5d685ced0895ace49ec 100644
--- a/src/conversation/test_conversation_api_twocalls.c
+++ b/src/conversation/test_conversation_api_twocalls.c
@@ -524,7 +524,8 @@ namestore_put_cont (void *cls, int32_t success, const char *emsg)
   GNUNET_assert (GNUNET_YES == success);
   GNUNET_assert (NULL == emsg);
   GNUNET_assert (NULL == op);
-  op = GNUNET_IDENTITY_create (id, "caller-ego", NULL, &caller_ego_create_cont, NULL);
+  op = GNUNET_IDENTITY_create (id, "caller-ego", NULL, &caller_ego_create_cont,
+                               NULL);
 }
 
 
@@ -613,7 +614,8 @@ run (void *cls,
   timeout_task = GNUNET_SCHEDULER_add_delayed (TIMEOUT, &end_test, NULL);
   GNUNET_SCHEDULER_add_shutdown (&do_shutdown, NULL);
   id = GNUNET_IDENTITY_connect (cfg, &identity_cb, NULL);
-  op = GNUNET_IDENTITY_create (id, "phone-ego", NULL, &phone_ego_create_cont, NULL);
+  op = GNUNET_IDENTITY_create (id, "phone-ego", NULL, &phone_ego_create_cont,
+                               NULL);
   ns = GNUNET_NAMESTORE_connect (cfg);
 }
 
diff --git a/src/core/.gitignore b/src/core/.gitignore
new file mode 100644
index 0000000000000000000000000000000000000000..cdd1f93c2e932c7db05828fe26480a1aebcf541c
--- /dev/null
+++ b/src/core/.gitignore
@@ -0,0 +1,9 @@
+gnunet-service-core
+gnunet-core
+test_core_api
+test_core_api_reliability
+test_core_api_send_to_self
+test_core_api_start_only
+test_core_quota_compliance_asymmetric_recv_limited
+test_core_quota_compliance_asymmetric_send_limited
+test_core_quota_compliance_symmetric
diff --git a/src/core/gnunet-service-core_kx.c b/src/core/gnunet-service-core_kx.c
index cafe658e841ca82dca676d5de3617af515e80e18..a79ef075b37e8f33f0c24d28d894f80ed00f087b 100644
--- a/src/core/gnunet-service-core_kx.c
+++ b/src/core/gnunet-service-core_kx.c
@@ -76,119 +76,6 @@
 
 GNUNET_NETWORK_STRUCT_BEGIN
 
-/**
- * Message transmitted with the signed ephemeral key of a peer.  The
- * session key is then derived from the two ephemeral keys (ECDHE).
- */
-struct EphemeralKeyMessage
-{
-  /**
-   * Message type is #GNUNET_MESSAGE_TYPE_CORE_EPHEMERAL_KEY.
-   */
-  struct GNUNET_MessageHeader header;
-
-  /**
-   * Status of the sender (should be in `enum PeerStateMachine`), nbo.
-   */
-  int32_t sender_status GNUNET_PACKED;
-
-  /**
-   * An ECC signature of the @e origin_identity asserting the validity
-   * of the given ephemeral key.
-   */
-  struct GNUNET_CRYPTO_EddsaSignature signature;
-
-  /**
-   * Information about what is being signed.
-   */
-  struct GNUNET_CRYPTO_EccSignaturePurpose purpose;
-
-  /**
-   * At what time was this key created (beginning of validity).
-   */
-  struct GNUNET_TIME_AbsoluteNBO creation_time;
-
-  /**
-   * When does the given ephemeral key expire (end of validity).
-   */
-  struct GNUNET_TIME_AbsoluteNBO expiration_time;
-
-  /**
-   * Ephemeral public ECC key.
-   */
-  struct GNUNET_CRYPTO_EcdhePublicKey ephemeral_key;
-
-  /**
-   * Public key of the signing peer (persistent version, not the
-   * ephemeral public key).
-   */
-  struct GNUNET_PeerIdentity origin_identity;
-};
-
-
-/**
- * We're sending an (encrypted) PING to the other peer to check if it
- * can decrypt.  The other peer should respond with a PONG with the
- * same content, except this time encrypted with the receiver's key.
- */
-struct PingMessage
-{
-  /**
-   * Message type is #GNUNET_MESSAGE_TYPE_CORE_PING.
-   */
-  struct GNUNET_MessageHeader header;
-
-  /**
-   * Seed for the IV
-   */
-  uint32_t iv_seed GNUNET_PACKED;
-
-  /**
-   * Intended target of the PING, used primarily to check
-   * that decryption actually worked.
-   */
-  struct GNUNET_PeerIdentity target;
-
-  /**
-   * Random number chosen to make replay harder.
-   */
-  uint32_t challenge GNUNET_PACKED;
-};
-
-
-/**
- * Response to a PING.  Includes data from the original PING.
- */
-struct PongMessage
-{
-  /**
-   * Message type is #GNUNET_MESSAGE_TYPE_CORE_PONG.
-   */
-  struct GNUNET_MessageHeader header;
-
-  /**
-   * Seed for the IV
-   */
-  uint32_t iv_seed GNUNET_PACKED;
-
-  /**
-   * Random number to make replay attacks harder.
-   */
-  uint32_t challenge GNUNET_PACKED;
-
-  /**
-   * Reserved, always zero.
-   */
-  uint32_t reserved;
-
-  /**
-   * Intended target of the PING, used primarily to check
-   * that decryption actually worked.
-   */
-  struct GNUNET_PeerIdentity target;
-};
-
-
 /**
  * Encapsulation for encrypted messages exchanged between
  * peers.  Followed by the actual encrypted data.
diff --git a/src/core/test_core_api.c b/src/core/test_core_api.c
index dda60215dfb24bc7d8c88bf7d3b692946fc9bf5e..0649642922fa1c31e9c89d1759c876ec9d209167 100644
--- a/src/core/test_core_api.c
+++ b/src/core/test_core_api.c
@@ -251,8 +251,8 @@ setup_peer (struct PeerContext *p, const char *cfgname)
 
   binary = GNUNET_OS_get_libexec_binary_path ("gnunet-service-arm");
   p->cfg = GNUNET_CONFIGURATION_create ();
-  p->arm_proc = GNUNET_OS_start_process (GNUNET_YES,
-                                         GNUNET_OS_INHERIT_STD_OUT_AND_ERR,
+  p->arm_proc = GNUNET_OS_start_process (GNUNET_OS_INHERIT_STD_OUT_AND_ERR
+                                         | GNUNET_OS_USE_PIPE_CONTROL,
                                          NULL,
                                          NULL,
                                          NULL,
diff --git a/src/core/test_core_api_reliability.c b/src/core/test_core_api_reliability.c
index 136539ed3542a244f75b30ae9eec2fd169892391..debf808ca3f2f832f30167a9b954473661359426 100644
--- a/src/core/test_core_api_reliability.c
+++ b/src/core/test_core_api_reliability.c
@@ -419,8 +419,8 @@ setup_peer (struct PeerContext *p,
   binary = GNUNET_OS_get_libexec_binary_path ("gnunet-service-arm");
   p->cfg = GNUNET_CONFIGURATION_create ();
   p->arm_proc
-    = GNUNET_OS_start_process (GNUNET_YES,
-                               GNUNET_OS_INHERIT_STD_OUT_AND_ERR,
+    = GNUNET_OS_start_process (GNUNET_OS_INHERIT_STD_OUT_AND_ERR
+                               | GNUNET_OS_USE_PIPE_CONTROL,
                                NULL, NULL, NULL,
                                binary,
                                "gnunet-service-arm",
diff --git a/src/core/test_core_api_start_only.c b/src/core/test_core_api_start_only.c
index 3cbe50d72604b4bf9305dfe2c9511c54d06ac301..007131134f11c057e58f5377911cac6274a40d6d 100644
--- a/src/core/test_core_api_start_only.c
+++ b/src/core/test_core_api_start_only.c
@@ -118,8 +118,8 @@ setup_peer (struct PeerContext *p,
   binary = GNUNET_OS_get_libexec_binary_path ("gnunet-service-arm");
   p->cfg = GNUNET_CONFIGURATION_create ();
   p->arm_proc =
-    GNUNET_OS_start_process (GNUNET_YES,
-                             GNUNET_OS_INHERIT_STD_OUT_AND_ERR,
+    GNUNET_OS_start_process (GNUNET_OS_INHERIT_STD_OUT_AND_ERR
+                             | GNUNET_OS_USE_PIPE_CONTROL,
                              NULL, NULL, NULL,
                              binary,
                              "gnunet-service-arm",
diff --git a/src/core/test_core_quota_compliance.c b/src/core/test_core_quota_compliance.c
index 67f8bb2242ef61670c5fa8ccc76b2f21e1f203b7..cf2da3d97d3d69facd172543d827ae4a8b49545c 100644
--- a/src/core/test_core_quota_compliance.c
+++ b/src/core/test_core_quota_compliance.c
@@ -570,8 +570,8 @@ setup_peer (struct PeerContext *p,
   binary = GNUNET_OS_get_libexec_binary_path ("gnunet-service-arm");
   p->cfg = GNUNET_CONFIGURATION_create ();
   p->arm_proc =
-    GNUNET_OS_start_process (GNUNET_YES,
-                             GNUNET_OS_INHERIT_STD_OUT_AND_ERR,
+    GNUNET_OS_start_process (GNUNET_OS_INHERIT_STD_OUT_AND_ERR
+                             | GNUNET_OS_USE_PIPE_CONTROL,
                              NULL, NULL, NULL,
                              binary,
                              "gnunet-service-arm",
diff --git a/src/curl/curl.c b/src/curl/curl.c
index a63a10f3b246aff58fe19d56c97fa4ea20427252..d89c97176f6120527c7824c7c1b105d3d95ede7f 100644
--- a/src/curl/curl.c
+++ b/src/curl/curl.c
@@ -170,9 +170,92 @@ struct GNUNET_CURL_Context
    * Closure for @e cb.
    */
   void *cb_cls;
+
+  /**
+   * USERNAME:PASSWORD to use for client-authentication
+   * with all requests of this context, or NULL.
+   */
+  char *userpass;
+
+  /**
+   * Type of the TLS client certificate used, or NULL.
+   */
+  char *certtype;
+
+  /**
+   * File with the TLS client certificate, or NULL.
+   */
+  char *certfile;
+
+  /**
+   * File with the private key to authenticate the
+   * TLS client, or NULL.
+   */
+  char *keyfile;
+
+  /**
+   * Passphrase to decrypt @e keyfile, or NULL.
+   */
+  char *keypass;
+
 };
 
 
+/**
+ * Force use of the provided username and password
+ * for client authentication for all operations performed
+ * with @a ctx.
+ *
+ * @param ctx context to set authentication data for
+ * @param userpass string with "$USERNAME:$PASSWORD"
+ */
+void
+GNUNET_CURL_set_userpass (struct GNUNET_CURL_Context *ctx,
+                          const char *userpass)
+{
+  GNUNET_free (ctx->userpass);
+  if (NULL != userpass)
+    ctx->userpass = GNUNET_strdup (userpass);
+}
+
+
+/**
+ * Force use of the provided TLS client certificate
+ * for client authentication for all operations performed
+ * with @a ctx.
+ *
+ * Note that if the provided information is incorrect,
+ * the earliest operation that could fail is
+ * #GNUNET_CURL_job_add() or #GNUNET_CURL_job_add2()!
+ *
+ * @param ctx context to set authentication data for
+ * @param certtype type of the certificate
+ * @param certfile file with the certificate
+ * @param keyfile file with the private key
+ * @param keypass passphrase to decrypt @a keyfile (or NULL)
+ */
+void
+GNUNET_CURL_set_tlscert (struct GNUNET_CURL_Context *ctx,
+                         const char *certtype,
+                         const char *certfile,
+                         const char *keyfile,
+                         const char *keypass)
+{
+  GNUNET_free (ctx->certtype);
+  GNUNET_free (ctx->certfile);
+  GNUNET_free (ctx->keyfile);
+  GNUNET_free (ctx->keypass);
+  if (NULL != certtype)
+    ctx->certtype = GNUNET_strdup (certtype);
+  if (NULL != certfile)
+    ctx->certfile = GNUNET_strdup (certfile);
+  if (NULL != keyfile)
+    ctx->certtype = GNUNET_strdup (keyfile);
+  if (NULL != keypass)
+    ctx->certtype = GNUNET_strdup (keypass);
+}
+
+
 /**
  * Initialise this library.  This function should be called before using any of
  * the following functions.
@@ -388,6 +471,30 @@ setup_job (CURL *eh,
 }
 
 
+/**
+ * Add @a extra_headers to the HTTP headers for @a job.
+ *
+ * @param[in,out] job the job to modify
+ * @param extra_headers headers to append
+ */
+void
+GNUNET_CURL_extend_headers (struct GNUNET_CURL_Job *job,
+                            const struct curl_slist *extra_headers)
+{
+  struct curl_slist *all_headers = job->job_headers;
+
+  for (const struct curl_slist *curr = extra_headers;
+       NULL != curr;
+       curr = curr->next)
+  {
+    GNUNET_assert (NULL !=
+                   (all_headers = curl_slist_append (all_headers,
+                                                     curr->data)));
+  }
+  job->job_headers = all_headers;
+}
+
+
 /**
  * Schedule a CURL request to be executed and call the given @a jcc
  * upon its completion.  Note that the context will make use of the
@@ -457,6 +564,32 @@ GNUNET_CURL_job_add2 (struct GNUNET_CURL_Context *ctx,
   struct curl_slist *all_headers;
 
   GNUNET_assert (NULL != jcc);
+  if ( (NULL != ctx->userpass) &&
+       (0 != curl_easy_setopt (eh,
+                               CURLOPT_USERPWD,
+                               ctx->userpass)) )
+    return NULL;
+  if ( (NULL != ctx->certfile) &&
+       (0 != curl_easy_setopt (eh,
+                               CURLOPT_SSLCERT,
+                               ctx->certfile)) )
+    return NULL;
+  if ( (NULL != ctx->certtype) &&
+       (0 != curl_easy_setopt (eh,
+                               CURLOPT_SSLCERTTYPE,
+                               ctx->certtype)) )
+    return NULL;
+  if ( (NULL != ctx->keyfile) &&
+       (0 != curl_easy_setopt (eh,
+                               CURLOPT_SSLKEY,
+                               ctx->keyfile)) )
+    return NULL;
+  if ( (NULL != ctx->keypass) &&
+       (0 != curl_easy_setopt (eh,
+                               CURLOPT_KEYPASSWD,
+                               ctx->keypass)) )
+    return NULL;
+
   all_headers = setup_job_headers (ctx,
                                    job_headers);
   if (NULL == (job = setup_job (eh,
@@ -477,33 +610,27 @@ GNUNET_CURL_job_add2 (struct GNUNET_CURL_Context *ctx,
  * CURLOPT_PRIVATE facility of the CURL @a eh.
  *
  * This function modifies the CURL handle to add the
- * "Content-Type: application/json" header if @a add_json is set.
+ * "Content-Type: application/json" header.
  *
  * @param ctx context to execute the job in
  * @param eh curl easy handle for the request, will
  *           be executed AND cleaned up
- * @param add_json add "application/json" content type header
  * @param jcc callback to invoke upon completion
  * @param jcc_cls closure for @a jcc
  * @return NULL on error (in this case, @eh is still released!)
  */
 struct GNUNET_CURL_Job *
-GNUNET_CURL_job_add (struct GNUNET_CURL_Context *ctx,
-                     CURL *eh,
-                     int add_json,
-                     GNUNET_CURL_JobCompletionCallback jcc,
-                     void *jcc_cls)
+GNUNET_CURL_job_add_with_ct_json (struct GNUNET_CURL_Context *ctx,
+                                  CURL *eh,
+                                  GNUNET_CURL_JobCompletionCallback jcc,
+                                  void *jcc_cls)
 {
   struct GNUNET_CURL_Job *job;
   struct curl_slist *job_headers = NULL;
 
-  if (GNUNET_YES == add_json)
-  {
-    GNUNET_assert (
-      NULL != (job_headers =
-                 curl_slist_append (NULL, "Content-Type: application/json")));
-  }
-
+  GNUNET_assert (NULL != (job_headers =
+                            curl_slist_append (NULL,
+                                               "Content-Type: application/json")));
   job = GNUNET_CURL_job_add2 (ctx,
                               eh,
                               job_headers,
@@ -514,6 +641,32 @@ GNUNET_CURL_job_add (struct GNUNET_CURL_Context *ctx,
 }
 
 
+/**
+ * Schedule a CURL request to be executed and call the given @a jcc
+ * upon its completion.  Note that the context will make use of the
+ * CURLOPT_PRIVATE facility of the CURL @a eh.
+ *
+ * @param ctx context to execute the job in
+ * @param eh curl easy handle for the request, will
+ *           be executed AND cleaned up
+ * @param jcc callback to invoke upon completion
+ * @param jcc_cls closure for @a jcc
+ * @return NULL on error (in this case, @eh is still released!)
+ */
+struct GNUNET_CURL_Job *
+GNUNET_CURL_job_add (struct GNUNET_CURL_Context *ctx,
+                     CURL *eh,
+                     GNUNET_CURL_JobCompletionCallback jcc,
+                     void *jcc_cls)
+{
+  return GNUNET_CURL_job_add2 (ctx,
+                               eh,
+                               NULL,
+                               jcc,
+                               jcc_cls);
+}
+
+
 /**
  * Cancel a job.  Must only be called before the job completion
  * callback is called for the respective job.
@@ -735,7 +888,8 @@ do_benchmark (CURLMsg *cmsg)
      curl -w "foo%{size_request} -XPOST --data "ABC" $URL
      the CURLINFO_REQUEST_SIZE should be the whole size of the request
      including headers and body.
-   */GNUNET_break (size_curl <= size_long);
+  *///
+  GNUNET_break (size_curl <= size_long);
 
   urd = get_url_benchmark_data (url, (unsigned int) response_code);
   urd->count++;
@@ -899,6 +1053,11 @@ GNUNET_CURL_fini (struct GNUNET_CURL_Context *ctx)
   curl_share_cleanup (ctx->share);
   curl_multi_cleanup (ctx->multi);
   curl_slist_free_all (ctx->common_headers);
+  GNUNET_free (ctx->userpass);
+  GNUNET_free (ctx->certtype);
+  GNUNET_free (ctx->certfile);
+  GNUNET_free (ctx->keyfile);
+  GNUNET_free (ctx->keypass);
   GNUNET_free (ctx);
 }
 
diff --git a/src/datacache/.gitignore b/src/datacache/.gitignore
new file mode 100644
index 0000000000000000000000000000000000000000..8e42aa103c410f40495ee03d82cfff2396b0414b
--- /dev/null
+++ b/src/datacache/.gitignore
@@ -0,0 +1,6 @@
+test_datacache_heap
+test_datacache_postgres
+test_datacache_quota_heap
+test_datacache_quota_postgres
+test_datacache_quota_sqlite
+test_datacache_sqlite
diff --git a/src/datastore/.gitignore b/src/datastore/.gitignore
new file mode 100644
index 0000000000000000000000000000000000000000..51d3391b99fad2018875957421e0ec30d8584817
--- /dev/null
+++ b/src/datastore/.gitignore
@@ -0,0 +1,16 @@
+gnunet-service-datastore
+gnunet-datastore
+perf_datastore_api_heap
+perf_plugin_datastore_heap
+test_datastore_api_heap
+test_datastore_api_management_heap
+test_datastore_api_management_mysql
+test_datastore_api_management_postgres
+test_datastore_api_management_sqlite
+test_datastore_api_mysql
+test_datastore_api_postgres
+test_datastore_api_sqlite
+test_plugin_datastore_heap
+test_plugin_datastore_mysql
+test_plugin_datastore_postgres
+test_plugin_datastore_sqlite
diff --git a/src/datastore/selectrandom.sql b/src/datastore/selectrandom.sql
new file mode 100644
index 0000000000000000000000000000000000000000..82830a13a89247e45ba2334dc0047e14ee5ebd7e
--- /dev/null
+++ b/src/datastore/selectrandom.sql
@@ -0,0 +1,9 @@
+select *
+from (select random() as v from (values(1))) t1,
+     (select max(repl) as m from data) t2,
+     (select * from data
+      where repl=t2.m and
+            rnd>=t.v
+      order by rnd
+      limit 1)
+
diff --git a/src/dht/.gitignore b/src/dht/.gitignore
new file mode 100644
index 0000000000000000000000000000000000000000..25b1daf28fd8bf88ff317ba716099b018e979f1a
--- /dev/null
+++ b/src/dht/.gitignore
@@ -0,0 +1,12 @@
+gnunet-dht-get
+gnunet-dht-monitor
+gnunet-dht-profiler
+gnunet-dht-put
+gnunet-service-dht
+test_dht_2dtorus
+test_dht_api
+test_dht_line
+test_dht_monitor
+test_dht_multipeer
+test_dht_tools.py
+test_dht_twopeer
diff --git a/src/dht/test_dht_tools.sh b/src/dht/test_dht_tools.sh
new file mode 100755
index 0000000000000000000000000000000000000000..56cc99e157ed0a1b4acdc2924540156f977e7c39
--- /dev/null
+++ b/src/dht/test_dht_tools.sh
@@ -0,0 +1,64 @@
+#!/bin/sh
+# This file is in the public domain.
+
+out=`mktemp /tmp/test-gnunet-dht-logXXXXXXXX`
+tempcfg=`mktemp /tmp/test-dht-tools.XXXXXXXX`
+checkout="check.out"
+armexe="gnunet-arm -c $tempcfg "
+putexe="gnunet-dht-put -c $tempcfg "
+getexe="gnunet-dht-get -c $tempcfg "
+peerinfo="gnunet-peerinfo -c $tempcfg -sq"
+stop_arm()
+{
+  if ! $armexe $DEBUG -e -d > $out ; then
+    echo "FAIL: error running $armexe"
+    echo "Command output was:"
+    cat $out
+    rm -f $out $tempcfg
+    exit 1
+  fi
+  rm -f $out $tempcfg
+}
+
+cp test_dht_tools.conf $tempcfg
+
+echo -n "TEST: Starting ARM..."
+if ! $armexe $DEBUG -s > $out ; then
+  echo "FAIL: error running $armexe"
+  echo "Command output was:"
+  cat $out
+  stop_arm
+  exit 1
+fi
+echo "PASS"
+
+echo -n "TEST: Testing put..."
+if ! $putexe -k testkey -d testdata -t 8 > $out ; then
+  echo "FAIL: error running $putexe"
+  echo "Command output was:"
+  cat $out
+  stop_arm
+  exit 1
+fi
+echo "PASS"
+
+echo -n "TEST: Testing get..."
+echo "Result 0, type 8:" > $checkout
+echo "testdata" >> $checkout
+
+if ! $getexe -k testkey -T 100ms -t 8 > $out ; then
+  echo "FAIL: error running $putexe"
+  echo "Command output was:"
+  cat $out
+  stop_arm
+  exit 1
+fi
+
+if ! diff --strip-trailing-cr -q $out $checkout ; then
+  echo "FAIL: $out and $checkout differ:"
+  diff --strip-trailing-cr $out $checkout
+  stop_arm
+  exit 1
+fi
+echo "PASS"
+stop_arm
diff --git a/src/dns/.gitignore b/src/dns/.gitignore
new file mode 100644
index 0000000000000000000000000000000000000000..d3a62470edc3cb9df6bb6d09e4efa8766f2fb3fa
--- /dev/null
+++ b/src/dns/.gitignore
@@ -0,0 +1,7 @@
+gnunet-service-dns
+gnunet-dns-monitor
+gnunet-dns-redirector
+gnunet-helper-dns
+test_hexcoder
+gnunet-zoneimport
+gnunet-zonewalk
diff --git a/src/exit/.gitignore b/src/exit/.gitignore
new file mode 100644
index 0000000000000000000000000000000000000000..9b75bba9a194bc5072ff57b3f7c2c632dde6cba7
--- /dev/null
+++ b/src/exit/.gitignore
@@ -0,0 +1,2 @@
+gnunet-helper-exit
+gnunet-daemon-exit
diff --git a/src/fragmentation/.gitignore b/src/fragmentation/.gitignore
new file mode 100644
index 0000000000000000000000000000000000000000..c3293ab695d74d95ca785e3ab17e74b339a59d5d
--- /dev/null
+++ b/src/fragmentation/.gitignore
@@ -0,0 +1,2 @@
+test_fragmentation
+test_fragmentation_parallel
diff --git a/src/fs/.gitignore b/src/fs/.gitignore
new file mode 100644
index 0000000000000000000000000000000000000000..f0e2a4f7bcdbb5ada91fb25f8538572e3da4ff63
--- /dev/null
+++ b/src/fs/.gitignore
@@ -0,0 +1,43 @@
+gnunet-unindex
+gnunet-auto-share
+gnunet-daemon-fsprofiler
+gnunet-directory
+gnunet-download
+gnunet-fs
+gnunet-fs-profiler
+gnunet-helper-fs-publish
+gnunet-publish
+gnunet-search
+gnunet-service-fs
+test_fs_directory
+test_fs_download
+test_fs_download_cadet
+test_fs_download_indexed
+test_fs_download_persistence
+test_fs_file_information
+test_fs_getopt
+test_fs_list_indexed
+test_fs_namespace
+test_fs_namespace_list_updateable
+test_fs_publish
+test_fs_publish_persistence
+test_fs_search
+test_fs_search_persistence
+test_fs_search_probes
+test_fs_search_with_and
+test_fs_start_stop
+test_fs_test_lib
+test_fs_unindex
+test_fs_unindex_persistence
+test_fs_uri
+test_gnunet_fs_idx.py
+test_gnunet_fs_psd.py
+test_gnunet_fs_rec.py
+test_gnunet_service_fs_migration
+test_gnunet_service_fs_p2p
+test_gnunet_service_fs_p2p_cadet
+test_plugin_block_fs
+perf_gnunet_service_fs_p2p
+perf_gnunet_service_fs_p2p_index
+perf_gnunet_service_fs_p2p_respect
+rdir.gnd
diff --git a/src/fs/fs_namespace.c b/src/fs/fs_namespace.c
index 508f9cadca90bb752a158641a805777c6e96d940..155486be5ba654e29e9a83a2847541a1641eb51a 100644
--- a/src/fs/fs_namespace.c
+++ b/src/fs/fs_namespace.c
@@ -214,13 +214,13 @@ write_update_information_graph (struct GNUNET_FS_UpdateInformationGraph *uig)
     n = uig->update_nodes[i];
     uris = GNUNET_FS_uri_to_string (n->uri);
     struct GNUNET_BIO_WriteSpec ws[] = {
-      GNUNET_BIO_write_spec_string("fs-namespace-node-id", n->id),
-      GNUNET_BIO_write_spec_meta_data("fs-namespace-node-meta", n->md),
-      GNUNET_BIO_write_spec_string("fs-namespace-node-update", n->update),
-      GNUNET_BIO_write_spec_string("fs-namespace-uris", uris),
-      GNUNET_BIO_write_spec_end(),
+      GNUNET_BIO_write_spec_string ("fs-namespace-node-id", n->id),
+      GNUNET_BIO_write_spec_meta_data ("fs-namespace-node-meta", n->md),
+      GNUNET_BIO_write_spec_string ("fs-namespace-node-update", n->update),
+      GNUNET_BIO_write_spec_string ("fs-namespace-uris", uris),
+      GNUNET_BIO_write_spec_end (),
     };
-    if (GNUNET_OK != GNUNET_BIO_write_spec_commit(wh, ws))
+    if (GNUNET_OK != GNUNET_BIO_write_spec_commit (wh, ws))
     {
       GNUNET_free (uris);
       break;
@@ -292,11 +292,11 @@ read_update_information_graph (struct GNUNET_FS_Handle *h,
   {
     n = GNUNET_new (struct NamespaceUpdateNode);
     struct GNUNET_BIO_ReadSpec rs[] = {
-      GNUNET_BIO_read_spec_string("identifier", &n->id, 1024),
-      GNUNET_BIO_read_spec_meta_data("meta", &n->md),
-      GNUNET_BIO_read_spec_string("update-id", &n->update, 1024),
-      GNUNET_BIO_read_spec_string("uri", &uris, 1024 * 2),
-      GNUNET_BIO_read_spec_end(),
+      GNUNET_BIO_read_spec_string ("identifier", &n->id, 1024),
+      GNUNET_BIO_read_spec_meta_data ("meta", &n->md),
+      GNUNET_BIO_read_spec_string ("update-id", &n->update, 1024),
+      GNUNET_BIO_read_spec_string ("uri", &uris, 1024 * 2),
+      GNUNET_BIO_read_spec_end (),
     };
     if (GNUNET_OK != GNUNET_BIO_read_spec_commit (rh, rs))
     {
diff --git a/src/fs/gnunet-auto-share.c b/src/fs/gnunet-auto-share.c
index ee4a719e01e04043cce9d6bea3b4bff1fe8b1bea..f91e9d00d93a4c56663484472adb9c5f224fecf7 100644
--- a/src/fs/gnunet-auto-share.c
+++ b/src/fs/gnunet-auto-share.c
@@ -201,9 +201,9 @@ load_state ()
   while (n-- > 0)
   {
     struct GNUNET_BIO_ReadSpec rs[] = {
-      GNUNET_BIO_read_spec_string("filename", &fn, 1024),
-      GNUNET_BIO_read_spec_object("id", &id, sizeof(struct GNUNET_HashCode)),
-      GNUNET_BIO_read_spec_end(),
+      GNUNET_BIO_read_spec_string ("filename", &fn, 1024),
+      GNUNET_BIO_read_spec_object ("id", &id, sizeof(struct GNUNET_HashCode)),
+      GNUNET_BIO_read_spec_end (),
     };
     if (GNUNET_OK != GNUNET_BIO_read_spec_commit (rh, rs))
       goto error;
@@ -258,7 +258,8 @@ write_item (void *cls, const struct GNUNET_HashCode *key, void *value)
   struct GNUNET_BIO_WriteSpec ws[] = {
     GNUNET_BIO_write_spec_string ("auto-share-write-item-filename",
                                   wi->filename),
-    GNUNET_BIO_write_spec_object ("id", &wi->id, sizeof(struct GNUNET_HashCode)),
+    GNUNET_BIO_write_spec_object ("id", &wi->id, sizeof(struct
+                                                        GNUNET_HashCode)),
     GNUNET_BIO_write_spec_end (),
   };
   if (GNUNET_OK != GNUNET_BIO_write_spec_commit (wh, ws))
@@ -478,8 +479,7 @@ work (void *cls)
   argv[argc] = NULL;
   GNUNET_log (GNUNET_ERROR_TYPE_INFO, _ ("Publishing `%s'\n"), wi->filename);
   GNUNET_assert (NULL == publish_proc);
-  publish_proc = GNUNET_OS_start_process_vap (GNUNET_YES,
-                                              0,
+  publish_proc = GNUNET_OS_start_process_vap (GNUNET_OS_USE_PIPE_CONTROL,
                                               NULL,
                                               NULL,
                                               NULL,
@@ -748,7 +748,7 @@ main (int argc, char *const *argv)
 
   if (GNUNET_OK != GNUNET_STRINGS_get_utf8_args (argc, argv, &argc, &argv))
     return 2;
-  sigpipe = GNUNET_DISK_pipe (GNUNET_NO, GNUNET_NO, GNUNET_NO, GNUNET_NO);
+  sigpipe = GNUNET_DISK_pipe (GNUNET_DISK_PF_NONE);
   GNUNET_assert (NULL != sigpipe);
   shc_chld =
     GNUNET_SIGNAL_handler_install (GNUNET_SIGCHLD, &sighandler_child_death);
diff --git a/src/fs/test_fs.c b/src/fs/test_fs.c
new file mode 100644
index 0000000000000000000000000000000000000000..7a57e98b07ebd8692c883aab21239a1e53894a54
--- /dev/null
+++ b/src/fs/test_fs.c
@@ -0,0 +1,262 @@
+/*
+     This file is part of GNUnet.
+     Copyright (C) 2004, 2005, 2006, 2008 GNUnet e.V.
+
+     GNUnet is free software: you can redistribute it and/or modify it
+     under the terms of the GNU Affero General Public License as published
+     by the Free Software Foundation, either version 3 of the License,
+     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
+     Affero General Public License for more details.
+
+     You should have received a copy of the GNU Affero General Public License
+     along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+     SPDX-License-Identifier: AGPL3.0-or-later
+ */
+
+/**
+ * @file fs/test_fs.c
+ * @brief testcase for FS (upload-search-download-unindex)
+ * @author Christian Grothoff
+ */
+
+#include "platform.h"
+#include "gnunet_util.h"
+#include "gnunet_fsui_lib.h"
+
+#define DEBUG_VERBOSE GNUNET_NO
+
+#define CHECK(a) if (! (a)) { ok = GNUNET_NO; GNUNET_GE_BREAK (NULL, 0); \
+                              goto FAILURE; }
+
+static char *
+makeName (unsigned int i)
+{
+  char *fn;
+
+  fn = GNUNET_malloc (strlen ("/tmp/gnunet-basic_fsui_test/BASIC_FSUI_TEST")
+                      + 14);
+  GNUNET_snprintf (fn,
+                   strlen ("/tmp/gnunet-basic_fsui_test/BASIC_FSUI_TEST") + 14,
+                   "/tmp/gnunet-basic_fsui_test/BASIC_FSUI_TEST%u", i);
+  GNUNET_disk_directory_create_for_file (NULL, fn);
+  return fn;
+}
+
+
+static enum GNUNET_FSUI_EventType lastEvent;
+
+static struct GNUNET_MetaData *search_meta;
+
+static struct GNUNET_ECRS_URI *search_uri;
+
+static struct GNUNET_FSUI_Context *ctx;
+
+static void *
+eventCallback (void *cls, const GNUNET_FSUI_Event *event)
+{
+  static char unused;
+
+  switch (event->type)
+  {
+  case GNUNET_FSUI_search_resumed:
+  case GNUNET_FSUI_download_resumed:
+  case GNUNET_FSUI_upload_resumed:
+  case GNUNET_FSUI_unindex_resumed:
+    return &unused;
+
+  case GNUNET_FSUI_search_result:
+#if DEBUG_VERBOSE
+    printf ("Received search result\n");
+#endif
+    search_uri = GNUNET_ECRS_uri_duplicate (event->data.SearchResult.fi.uri);
+    search_meta = GNUNET_meta_data_duplicate (event->data.SearchResult.fi.meta);
+    break;
+
+  case GNUNET_FSUI_upload_completed:
+#if DEBUG_VERBOSE
+    printf ("Upload complete.\n");
+#endif
+    break;
+
+  case GNUNET_FSUI_download_completed:
+#if DEBUG_VERBOSE
+    printf ("Download complete.\n");
+#endif
+    break;
+
+  case GNUNET_FSUI_unindex_completed:
+#if DEBUG_VERBOSE
+    printf ("Unindex complete.\n");
+#endif
+    break;
+
+  default:
+    break;
+  }
+  lastEvent = event->type;
+  return NULL;
+}
+
+
+#define START_DAEMON 1
+
+int
+main (int argc, char *argv[])
+{
+#if START_DAEMON
+  struct GNUNET_OS_Process *daemon;
+#endif
+  int ok;
+  struct GNUNET_ECRS_URI *uri;
+  char *filename = NULL;
+
+  char *keywords[] = {
+    "fsui_foo",
+    "fsui_bar",
+  };
+  char keyword[40];
+  char *fn;
+  int prog;
+  struct GNUNET_MetaData *meta;
+  struct GNUNET_ECRS_URI *kuri;
+  struct GNUNET_GC_Configuration *cfg;
+  struct GNUNET_FSUI_UploadList *upload = NULL;
+  struct GNUNET_FSUI_SearchList *search = NULL;
+  struct GNUNET_FSUI_UnindexList *unindex = NULL;
+  struct GNUNET_FSUI_DownloadList *download = NULL;
+
+  cfg = GNUNET_GC_create ();
+  if (-1 == GNUNET_GC_parse_configuration (cfg, "check.conf"))
+  {
+    GNUNET_GC_free (cfg);
+    return -1;
+  }
+#if START_DAEMON
+  daemon = GNUNET_daemon_start (NULL, cfg, "peer.conf", GNUNET_NO);
+  GNUNET_GE_ASSERT (NULL, daemon != NULL);
+  CHECK (GNUNET_OK ==
+         GNUNET_wait_for_daemon_running (NULL, cfg, 60 * GNUNET_CRON_SECONDS));
+#endif
+  GNUNET_thread_sleep (5 * GNUNET_CRON_SECONDS);         /* give apps time to start */
+  ok = GNUNET_YES;
+
+  /* ACTUAL TEST CODE */
+  ctx = GNUNET_FSUI_start (NULL, cfg, "basic_fsui_test", 32,     /* thread pool size */
+                           GNUNET_NO,   /* no resume */
+                           &eventCallback, NULL);
+  CHECK (ctx != NULL);
+  filename = makeName (42);
+  GNUNET_disk_file_write (NULL, filename, "foo bar test!",
+                          strlen ("foo bar test!"), "600");
+  meta = GNUNET_meta_data_create ();
+  kuri =
+    GNUNET_ECRS_keyword_command_line_to_uri (NULL, 2,
+                                             (const char **) keywords);
+  /* upload */
+  upload = GNUNET_FSUI_upload_start (ctx, filename,
+                                     (GNUNET_FSUI_DirectoryScanCallback)
+                                     & GNUNET_disk_directory_scan, NULL, 0,                                                     /* anonymity */
+                                     0, /* priority */
+                                     GNUNET_YES, GNUNET_NO, GNUNET_NO,
+                                     GNUNET_get_time () + 5 * GNUNET_CRON_HOURS,
+                                     meta, kuri, kuri);
+  CHECK (upload != NULL);
+  GNUNET_ECRS_uri_destroy (kuri);
+  GNUNET_meta_data_destroy (meta);
+  prog = 0;
+  while (lastEvent != GNUNET_FSUI_upload_completed)
+  {
+    prog++;
+    CHECK (prog < 10000) GNUNET_thread_sleep (50 * GNUNET_CRON_MILLISECONDS);
+    if (GNUNET_shutdown_test () == GNUNET_YES)
+      break;
+  }
+
+  /* search */
+  GNUNET_snprintf (keyword, 40, "+%s +%s", keywords[0], keywords[1]);
+  uri = GNUNET_ECRS_keyword_string_to_uri (NULL, keyword);
+  search = GNUNET_FSUI_search_start (ctx, 0, uri);
+  GNUNET_ECRS_uri_destroy (uri);
+  CHECK (search != NULL);
+  prog = 0;
+  while (lastEvent != GNUNET_FSUI_search_result)
+  {
+    prog++;
+    CHECK (prog < 10000);
+    GNUNET_thread_sleep (50 * GNUNET_CRON_MILLISECONDS);
+    if (GNUNET_shutdown_test () == GNUNET_YES)
+      break;
+  }
+  GNUNET_FSUI_search_abort (search);
+  GNUNET_FSUI_search_stop (search);
+
+  /* download */
+  fn = makeName (43);
+  download =
+    GNUNET_FSUI_download_start (ctx, 0, GNUNET_NO, search_uri, search_meta,
+                                fn, NULL, NULL);
+  GNUNET_free (fn);
+  prog = 0;
+  while (lastEvent != GNUNET_FSUI_download_completed)
+  {
+    prog++;
+    CHECK (prog < 10000);
+    GNUNET_thread_sleep (50 * GNUNET_CRON_MILLISECONDS);
+    if (GNUNET_shutdown_test () == GNUNET_YES)
+      break;
+  }
+  GNUNET_FSUI_download_stop (download);
+  download = NULL;
+  GNUNET_ECRS_uri_destroy (search_uri);
+  GNUNET_meta_data_destroy (search_meta);
+  /* unindex */
+  unindex = GNUNET_FSUI_unindex_start (ctx, filename);
+  prog = 0;
+  while (lastEvent != GNUNET_FSUI_unindex_completed)
+  {
+    prog++;
+    CHECK (prog < 10000);
+    GNUNET_thread_sleep (50 * GNUNET_CRON_MILLISECONDS);
+    if (GNUNET_shutdown_test () == GNUNET_YES)
+      break;
+  }
+  if (lastEvent != GNUNET_FSUI_unindex_completed)
+    GNUNET_FSUI_unindex_abort (unindex);
+  GNUNET_FSUI_unindex_stop (unindex);
+
+
+  /* END OF TEST CODE */
+FAILURE:
+  if (ctx != NULL)
+    GNUNET_FSUI_stop (ctx);
+  if (filename != NULL)
+  {
+    unlink (filename);
+    GNUNET_free (filename);
+  }
+  if (download != NULL)
+  {
+    GNUNET_FSUI_download_abort (download);
+    GNUNET_FSUI_download_stop (download);
+  }
+  filename = makeName (43);
+  /* TODO: verify file 'filename(42)' == file 'filename(43)' */
+  unlink (filename);
+  GNUNET_free (filename);
+
+#if START_DAEMON
+  GNUNET_GE_ASSERT (NULL, GNUNET_OK == GNUNET_daemon_stop (NULL, daemon));
+  GNUNET_OS_process_destroy (daemon);
+#endif
+  GNUNET_GC_free (cfg);
+
+  return (ok == GNUNET_YES) ? 0 : 1;
+}
+
+
+/* end of test_fs.c */
diff --git a/src/gns/.gitignore b/src/gns/.gitignore
new file mode 100644
index 0000000000000000000000000000000000000000..3bbb2eb3db6f6f40278a098078e8e08c6be88420
--- /dev/null
+++ b/src/gns/.gitignore
@@ -0,0 +1,12 @@
+gnunet-service-gns
+gnunet-bcd
+gnunet-dns2gns
+gnunet-gns
+gnunet-gns-proxy
+gnunet-gns-benchmark
+test_gns_proxy
+local.crt
+local.der
+local.key
+server.csr
+gnunet-gns-proxy-setup-ca
diff --git a/src/gns/gns_api.c b/src/gns/gns_api.c
index 0d99d822e8c4a1d6c04e1fec9c9ba67766caae0d..bf95bf340caf730222fa35888733394ad315e57c 100644
--- a/src/gns/gns_api.c
+++ b/src/gns/gns_api.c
@@ -427,4 +427,5 @@ GNUNET_GNS_lookup (struct GNUNET_GNS_Handle *handle,
                                     proc_cls);
 }
 
+
 /* end of gns_api.c */
diff --git a/src/gns/gnunet-dns2gns.c b/src/gns/gnunet-dns2gns.c
index 74309f55467aa5dbebbc22920a47362bef0f4144..0a9b7c8612449666caa660e03e3916567523cac1 100644
--- a/src/gns/gnunet-dns2gns.c
+++ b/src/gns/gnunet-dns2gns.c
@@ -190,6 +190,7 @@ do_shutdown (void *cls)
   }
 }
 
+
 /**
  * Shuffle answers
  * Fisher-Yates (aka Knuth) Shuffle
@@ -216,6 +217,7 @@ shuffle_answers (struct Request *request)
   }
 }
 
+
 /**
  * Send the response for the given request and clean up.
  *
diff --git a/src/gns/gnunet-gns-import.c b/src/gns/gnunet-gns-import.c
new file mode 100644
index 0000000000000000000000000000000000000000..78db28cabff0172dbcd2810a56682af22b5ca689
--- /dev/null
+++ b/src/gns/gnunet-gns-import.c
@@ -0,0 +1,494 @@
+/*
+     This file is part of GNUnet.
+     Copyright (C) 2012-2013 GNUnet e.V.
+
+     GNUnet is free software: you can redistribute it and/or modify it
+     under the terms of the GNU Affero General Public License as published
+     by the Free Software Foundation, either version 3 of the License,
+     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
+     Affero General Public License for more details.
+
+     You should have received a copy of the GNU Affero General Public License
+     along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+     SPDX-License-Identifier: AGPL3.0-or-later
+ */
+/**
+ * @file gnunet-gns.c
+ * @brief binary version of gnunet-gns-import.sh
+ *        (for OSes that have no POSIX shell).
+ * @author LRN
+ */
+#include "platform.h"
+#include <gnunet_util_lib.h>
+#include <gnunet_gnsrecord_lib.h>
+#include <gnunet_identity_service.h>
+#include <gnunet_namestore_service.h>
+
+/**
+ * Configuration we are using.
+ */
+static const struct GNUNET_CONFIGURATION_Handle *cfg;
+
+/**
+ * Handle to IDENTITY service.
+ */
+static struct GNUNET_IDENTITY_Handle *sh;
+
+/**
+ * Zone iterator for master zone
+ */
+struct GNUNET_NAMESTORE_ZoneIterator *list_it;
+
+/**
+ * Handle to the namestore.
+ */
+static struct GNUNET_NAMESTORE_Handle *ns;
+
+/**
+ * String version of PKEY for master-zone.
+ */
+static char *master_zone_pkey;
+
+/**
+ * Binary version of PKEY for master-zone.
+ */
+static struct GNUNET_CRYPTO_EcdsaPrivateKey master_pk;
+
+/**
+ * String version of PKEY for private-zone.
+ */
+static char *private_zone_pkey;
+
+/**
+ * String version of PKEY for pin-zone.
+ */
+static char *pin_zone_pkey =
+  "72QC35CO20UJN1E91KPJFNT9TG4CLKAPB4VK9S3Q758S9MLBRKOG";
+
+/**
+ * Set to GNUNET_YES if private record was found;
+ */
+static int found_private_rec = GNUNET_NO;
+
+/**
+ * Set to GNUNET_YES if pin record was found;
+ */
+static int found_pin_rec = GNUNET_NO;
+
+/**
+ * Exit code.
+ */
+static int ret;
+
+
+static int
+run_process_and_wait (enum GNUNET_OS_InheritStdioFlags std_inheritance,
+                      struct GNUNET_DISK_PipeHandle *pipe_stdin,
+                      struct GNUNET_DISK_PipeHandle *pipe_stdout,
+                      enum GNUNET_OS_ProcessStatusType *st,
+                      unsigned long *code,
+                      const char *filename, ...)
+{
+  static struct GNUNET_OS_Process *p;
+  int arglen;
+  char *arg;
+  char *args;
+  char *argp;
+  va_list ap, apc1, apc2;
+
+  va_start (ap, filename);
+  va_copy (apc1, ap);
+  va_copy (apc2, ap);
+  arglen = 0;
+  while (NULL != (arg = va_arg (apc1, char *)))
+    arglen += strlen (arg) + 1;
+  va_end (apc1);
+  args = argp = GNUNET_malloc (arglen);
+  while (NULL != (arg = va_arg (apc2, char *)))
+  {
+    strcpy (argp, arg);
+    argp += strlen (arg);
+    *argp = ' ';
+    argp += 1;
+  }
+  va_end (apc2);
+  if (arglen > 0)
+    argp[-1] = '\0';
+  p = GNUNET_OS_start_process_va (std_inheritance,
+                                  pipe_stdin,
+                                  pipe_stdout,
+                                  NULL,
+                                  filename, ap);
+  va_end (ap);
+  if (NULL == p)
+  {
+    ret = 3;
+    fprintf (stderr, "Failed to run `%s'\n", args);
+    GNUNET_free (args);
+    return 1;
+  }
+
+  if (GNUNET_OK != GNUNET_OS_process_wait (p))
+  {
+    ret = 4;
+    fprintf (stderr, "Failed to wait for `%s'\n", args);
+    GNUNET_free (args);
+    return 1;
+  }
+
+  switch (GNUNET_OS_process_status (p, st, code))
+  {
+  case GNUNET_OK:
+    break;
+
+  case GNUNET_NO:
+    ret = 5;
+    fprintf (stderr, "`%s' is still running\n", args);
+    GNUNET_free (args);
+    return 1;
+
+  default:
+  case GNUNET_SYSERR:
+    ret = 6;
+    fprintf (stderr, "Failed to check the status of `%s'\n", args);
+    GNUNET_free (args);
+    return 1;
+  }
+  return 0;
+}
+
+
+static void
+check_pkey (unsigned int rd_len, const struct GNUNET_GNSRECORD_Data *rd,
+            char *pk, int *found_rec)
+{
+  int i;
+
+  for (i = 0; i < rd_len; i++)
+  {
+    char *s;
+    if ((GNUNET_GNSRECORD_TYPE_PKEY != rd[i].record_type) ||
+        (rd[i].data_size != sizeof(struct GNUNET_CRYPTO_EcdsaPublicKey)) )
+      continue;
+    s = GNUNET_GNSRECORD_value_to_string (rd[i].record_type,
+                                          rd[i].data,
+                                          rd[i].data_size);
+    if (NULL == s)
+      continue;
+    if (0 == strcmp (s, pk))
+      *found_rec = GNUNET_YES;
+    GNUNET_free (s);
+  }
+}
+
+
+/**
+ * Process a record that was stored in the namestore.
+ *
+ * @param cls closure
+ * @param zone_key private key of the zone
+ * @param rname name that is being mapped (at most 255 characters long)
+ * @param rd_len number of entries in @a rd array
+ * @param rd array of records with data to store
+ */
+static void
+zone_iterator (void *cls,
+               const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone_key,
+               const char *rname, unsigned int rd_len,
+               const struct GNUNET_GNSRECORD_Data *rd)
+{
+  if (NULL != rname)
+  {
+    if (0 == strcmp (rname, "private"))
+      check_pkey (rd_len, rd, private_zone_pkey, &found_private_rec);
+    else if (0 == strcmp (rname, "pin"))
+      check_pkey (rd_len, rd, pin_zone_pkey, &found_pin_rec);
+  }
+  GNUNET_NAMESTORE_zone_iterator_next (list_it);
+}
+
+
+static void
+zone_iteration_error (void *cls)
+{
+  enum GNUNET_OS_ProcessStatusType st;
+  unsigned long code;
+
+  if (! found_private_rec)
+  {
+    if (0 != run_process_and_wait (GNUNET_OS_INHERIT_STD_OUT_AND_ERR,
+                                   NULL, NULL, &st, &code,
+                                   "gnunet-namestore",
+                                   "gnunet-namestore", "-z", "master-zone",
+                                   "-a", "-e", "never", "-n", "private", "-p",
+                                   "-t", "PKEY", "-V",
+                                   private_zone_pkey, NULL))
+    {
+      ret = 8;
+      return;
+    }
+  }
+  if (! found_pin_rec)
+  {
+    if (0 != run_process_and_wait (GNUNET_OS_INHERIT_STD_OUT_AND_ERR,
+                                   NULL, NULL, &st, &code,
+                                   "gnunet-namestore",
+                                   "gnunet-namestore", "-z", "master-zone",
+                                   "-a", "-e", "never", "-n", "pin", "-p", "-t",
+                                   "PKEY", "-V", pin_zone_pkey,
+                                   NULL))
+    {
+      ret = 10;
+      return;
+    }
+  }
+  list_it = NULL;
+  GNUNET_SCHEDULER_shutdown ();
+}
+
+
+static void
+zone_iteration_finished (void *cls)
+{
+}
+
+
+/**
+ * Get master-zone and private-zone keys.
+ *
+ * This function is initially called for all egos and then again
+ * whenever a ego's identifier changes or if it is deleted.  At the
+ * end of the initial pass over all egos, the function is once called
+ * with 'NULL' for 'ego'. That does NOT mean that the callback won't
+ * be invoked in the future or that there was an error.
+ *
+ * When used with 'GNUNET_IDENTITY_create' or 'GNUNET_IDENTITY_get',
+ * this function is only called ONCE, and 'NULL' being passed in
+ * 'ego' does indicate an error (i.e. name is taken or no default
+ * value is known).  If 'ego' is non-NULL and if '*ctx'
+ * is set in those callbacks, the value WILL be passed to a subsequent
+ * call to the identity callback of 'GNUNET_IDENTITY_connect' (if
+ * that one was not NULL).
+ *
+ * When an identity is renamed, this function is called with the
+ * (known) ego but the NEW identifier.
+ *
+ * When an identity is deleted, this function is called with the
+ * (known) ego and "NULL" for the 'identifier'.  In this case,
+ * the 'ego' is henceforth invalid (and the 'ctx' should also be
+ * cleaned up).
+ *
+ * @param cls closure
+ * @param ego ego handle
+ * @param ctx context for application to store data for this ego
+ *                 (during the lifetime of this process, initially NULL)
+ * @param identifier identifier assigned by the user for this ego,
+ *                   NULL if the user just deleted the ego and it
+ *                   must thus no longer be used
+ */
+static void
+get_ego (void *cls,
+         struct GNUNET_IDENTITY_Ego *ego,
+         void **ctx,
+         const char *identifier)
+{
+  static struct GNUNET_CRYPTO_EcdsaPublicKey pk;
+
+  if (NULL == ego)
+  {
+    if ((NULL == master_zone_pkey) ||
+        (NULL == private_zone_pkey) )
+    {
+      ret = 11;
+      GNUNET_SCHEDULER_shutdown ();
+      return;
+    }
+    list_it = GNUNET_NAMESTORE_zone_iteration_start (ns,
+                                                     &master_pk,
+                                                     &zone_iteration_error,
+                                                     NULL, &zone_iterator, NULL,
+                                                     &zone_iteration_finished,
+                                                     NULL);
+    if (NULL == list_it)
+    {
+      ret = 12;
+      GNUNET_SCHEDULER_shutdown ();
+    }
+    return;
+  }
+  GNUNET_IDENTITY_ego_get_public_key (ego, &pk);
+  if (NULL != identifier)
+  {
+    if ((NULL == master_zone_pkey) && (0 == strcmp ("master-zone",
+                                                    identifier)) )
+    {
+      master_zone_pkey = GNUNET_CRYPTO_ecdsa_public_key_to_string (&pk);
+      master_pk = *GNUNET_IDENTITY_ego_get_private_key (ego);
+    }
+    else if ((NULL == private_zone_pkey) && (0 == strcmp ("private-zone",
+                                                          identifier)) )
+      private_zone_pkey = GNUNET_CRYPTO_ecdsa_public_key_to_string (&pk);
+  }
+}
+
+
+/**
+ * Task run on shutdown.
+ *
+ * @param cls NULL
+ */
+static void
+shutdown_task (void *cls)
+{
+  GNUNET_free (master_zone_pkey);
+  master_zone_pkey = NULL;
+  GNUNET_free (private_zone_pkey);
+  private_zone_pkey = NULL;
+  if (NULL != list_it)
+  {
+    GNUNET_NAMESTORE_zone_iteration_stop (list_it);
+    list_it = NULL;
+  }
+  if (NULL != ns)
+  {
+    GNUNET_NAMESTORE_disconnect (ns);
+    ns = NULL;
+  }
+  if (NULL != sh)
+  {
+    GNUNET_IDENTITY_disconnect (sh);
+    sh = NULL;
+  }
+}
+
+
+/**
+ * Main function that will be run.
+ *
+ * @param cls closure
+ * @param args remaining command-line arguments
+ * @param cfgfile name of the configuration file used (for saving, can be NULL!)
+ * @param c configuration
+ */
+static void
+run (void *cls, char *const *args, const char *cfgfile,
+     const struct GNUNET_CONFIGURATION_Handle *c)
+{
+  enum GNUNET_OS_ProcessStatusType st;
+  unsigned long code;
+
+  cfg = c;
+
+  if (0 != run_process_and_wait (GNUNET_OS_INHERIT_STD_NONE,
+                                 NULL, NULL, &st, &code,
+                                 "gnunet-arm",
+                                 "gnunet-arm", "-I", NULL))
+  {
+    if (7 == ret)
+      fprintf (stderr,
+               "GNUnet is not running, please start GNUnet before running import\n");
+    return;
+  }
+
+  if (0 != run_process_and_wait (GNUNET_OS_INHERIT_STD_OUT_AND_ERR,
+                                 NULL, NULL, &st, &code,
+                                 "gnunet-identity",
+                                 "gnunet-identity", "-C", "master-zone", NULL))
+    return;
+
+  if (0 != run_process_and_wait (GNUNET_OS_INHERIT_STD_OUT_AND_ERR,
+                                 NULL, NULL, &st, &code,
+                                 "gnunet-identity",
+                                 "gnunet-identity", "-C", "private-zone", NULL))
+    return;
+
+  if (0 != run_process_and_wait (GNUNET_OS_INHERIT_STD_OUT_AND_ERR,
+                                 NULL, NULL, &st, &code,
+                                 "gnunet-identity",
+                                 "gnunet-identity", "-C", "sks-zone", NULL))
+    return;
+
+  if (0 != run_process_and_wait (GNUNET_OS_INHERIT_STD_OUT_AND_ERR,
+                                 NULL, NULL, &st, &code,
+                                 "gnunet-identity",
+                                 "gnunet-identity", "-e", "master-zone", "-s",
+                                 "gns-master", NULL))
+    return;
+
+  if (0 != run_process_and_wait (GNUNET_OS_INHERIT_STD_OUT_AND_ERR,
+                                 NULL, NULL, &st, &code,
+                                 "gnunet-identity",
+                                 "gnunet-identity", "-e", "master-zone", "-s",
+                                 "namestore", NULL))
+    return;
+
+  if (0 != run_process_and_wait (GNUNET_OS_INHERIT_STD_OUT_AND_ERR,
+                                 NULL, NULL, &st, &code,
+                                 "gnunet-identity",
+                                 "gnunet-identity", "-e", "master-zone", "-s",
+                                 "gns-proxy", NULL))
+    return;
+
+  if (0 != run_process_and_wait (GNUNET_OS_INHERIT_STD_OUT_AND_ERR,
+                                 NULL, NULL, &st, &code,
+                                 "gnunet-identity",
+                                 "gnunet-identity", "-e", "master-zone", "-s",
+                                 "gns-intercept", NULL))
+    return;
+
+  if (0 != run_process_and_wait (GNUNET_OS_INHERIT_STD_OUT_AND_ERR,
+                                 NULL, NULL, &st, &code,
+                                 "gnunet-identity",
+                                 "gnunet-identity", "-e", "private-zone", "-s",
+                                 "gns-private", NULL))
+    return;
+
+  if (0 != run_process_and_wait (GNUNET_OS_INHERIT_STD_OUT_AND_ERR,
+                                 NULL, NULL, &st, &code,
+                                 "gnunet-identity",
+                                 "gnunet-identity", "-e", "sks-zone", "-s",
+                                 "fs-sks", NULL))
+    return;
+
+  ns = GNUNET_NAMESTORE_connect (cfg);
+  sh = GNUNET_IDENTITY_connect (cfg, &get_ego, NULL);
+  GNUNET_SCHEDULER_add_shutdown (&shutdown_task, NULL);
+}
+
+
+/**
+ * The main function for gnunet-gns.
+ *
+ * @param argc number of arguments from the command line
+ * @param argv command line arguments
+ * @return 0 ok, 1 on error
+ */
+int
+main (int argc, char *const *argv)
+{
+  static const struct GNUNET_GETOPT_CommandLineOption options[] = {
+    GNUNET_GETOPT_OPTION_END
+  };
+  int r;
+
+  if (GNUNET_OK != GNUNET_STRINGS_get_utf8_args (argc, argv, &argc, &argv))
+    return 2;
+
+  GNUNET_log_setup ("gnunet-gns-import", "WARNING", NULL);
+  ret = 0;
+  r = GNUNET_PROGRAM_run (argc, argv, "gnunet-gns-import",
+                          _ (
+                            "This program will import some GNS authorities into your GNS namestore."),
+                          options,
+                          &run, NULL);
+  GNUNET_free_nz ((void *) argv);
+  return GNUNET_OK == r ? ret : 1;
+}
+
+
+/* end of gnunet-gns-import.c */
diff --git a/src/gns/gnunet_w32nsp_lib.h b/src/gns/gnunet_w32nsp_lib.h
new file mode 100644
index 0000000000000000000000000000000000000000..9d19ff2aabe3fc82cdfd220fbd66e7b92798e796
--- /dev/null
+++ b/src/gns/gnunet_w32nsp_lib.h
@@ -0,0 +1,10 @@
+#if ! defined(GNUNET_W32NSP_LIB_H)
+#define GNUNET_W32NSP_LIB_H
+
+#include <basetyps.h>
+
+/* E0D24085-622C-4A93-9A0018-034469DE28DA */
+DEFINE_GUID (GNUNET_NAMESPACE_PROVIDER_DNS, 0xE0D24085L, 0x622C, 0x4A93, 0x9A,
+             0x18, 0x03, 0x44, 0x69, 0xDE, 0x28, 0xDA);
+
+#endif /* GNUNET_W32NSP_LIB_H */
diff --git a/src/gns/nss/nss_gns.c b/src/gns/nss/nss_gns.c
index 36799ba3acde4c7f99ed0951c198ebbbeb96495a..77b4340ee18f3e9ebe2d5ed29623a9df97fd7292 100644
--- a/src/gns/nss/nss_gns.c
+++ b/src/gns/nss/nss_gns.c
@@ -38,7 +38,7 @@
 /** macro to align idx to 32bit boundary */
 #define ALIGN(idx) do { \
     if (idx % sizeof(void*)) \
-      idx += (sizeof(void*) - idx % sizeof(void*)); /* Align on 32 bit boundary */ \
+    idx += (sizeof(void*) - idx % sizeof(void*));   /* Align on 32 bit boundary */ \
 } while (0)
 
 
diff --git a/src/gns/nss/nss_gns_query.c b/src/gns/nss/nss_gns_query.c
index 11e46ad7fdc0940c1639cc7fd424f1916dc90af9..96e8e10da8accf226a625a42c25d1804d5c49b13 100644
--- a/src/gns/nss/nss_gns_query.c
+++ b/src/gns/nss/nss_gns_query.c
@@ -150,7 +150,7 @@ query_gns:
     if (1 == retry)
       return -2; /* no go -> service unavailable */
     retry = 1;
-    system("gnunet-arm -s");
+    system ("gnunet-arm -s");
     goto query_gns; /* Try again */
   }
   if (3 == WEXITSTATUS (ret))
diff --git a/src/gns/plugin_rest_gns.c b/src/gns/plugin_rest_gns.c
index 37313c529588b9d92992dec3fe1d3db5a5760d71..6ec921f704d3161db3a5a98297efbdca8f1a3080 100644
--- a/src/gns/plugin_rest_gns.c
+++ b/src/gns/plugin_rest_gns.c
@@ -62,6 +62,11 @@ const struct GNUNET_CONFIGURATION_Handle *cfg;
  */
 static char *allow_methods;
 
+/**
+ * Connection to GNS
+ */
+static struct GNUNET_GNS_Handle *gns;
+
 /**
  * @brief struct returned by the initialization function of the plugin
  */
@@ -76,9 +81,14 @@ struct Plugin
 struct RequestHandle
 {
   /**
-   * Connection to GNS
+   * DLL
    */
-  struct GNUNET_GNS_Handle *gns;
+  struct RequestHandle *next;
+
+  /**
+   * DLL
+   */
+  struct RequestHandle *prev;
 
   /**
    * Active GNS lookup
@@ -136,6 +146,15 @@ struct RequestHandle
   int response_code;
 };
 
+/**
+ * DLL
+ */
+static struct RequestHandle *requests_head;
+
+/**
+ * DLL
+ */
+static struct RequestHandle *requests_tail;
 
 /**
  * Cleanup lookup handle
@@ -153,12 +172,6 @@ cleanup_handle (void *cls)
     GNUNET_GNS_lookup_with_tld_cancel (handle->gns_lookup);
     handle->gns_lookup = NULL;
   }
-  if (NULL != handle->gns)
-  {
-    GNUNET_GNS_disconnect (handle->gns);
-    handle->gns = NULL;
-  }
-
   if (NULL != handle->timeout_task)
   {
     GNUNET_SCHEDULER_cancel (handle->timeout_task);
@@ -171,6 +184,9 @@ cleanup_handle (void *cls)
   if (NULL != handle->emsg)
     GNUNET_free (handle->emsg);
 
+  GNUNET_CONTAINER_DLL_remove (requests_head,
+                               requests_tail,
+                               handle);
   GNUNET_free (handle);
 }
 
@@ -204,7 +220,7 @@ do_error (void *cls)
   handle->proc (handle->proc_cls, resp, handle->response_code);
   json_decref (json_error);
   GNUNET_free (response);
-  GNUNET_SCHEDULER_add_now (&cleanup_handle, handle);
+  cleanup_handle(handle);
 }
 
 
@@ -318,7 +334,7 @@ get_gns_cont (struct GNUNET_REST_RequestHandle *con_handle,
     handle->record_type = GNUNET_GNSRECORD_TYPE_ANY;
   }
 
-  handle->gns_lookup = GNUNET_GNS_lookup_with_tld (handle->gns,
+  handle->gns_lookup = GNUNET_GNS_lookup_with_tld (gns,
                                                    handle->name,
                                                    handle->record_type,
                                                    GNUNET_GNS_LO_DEFAULT,
@@ -351,29 +367,6 @@ options_cont (struct GNUNET_REST_RequestHandle *con_handle,
 }
 
 
-/**
- * Handle rest request
- *
- * @param handle the request handle
- */
-static void
-init_cont (struct RequestHandle *handle)
-{
-  struct GNUNET_REST_RequestHandlerError err;
-  static const struct GNUNET_REST_RequestHandler handlers[] =
-  { { MHD_HTTP_METHOD_GET, GNUNET_REST_API_NS_GNS, &get_gns_cont },
-    { MHD_HTTP_METHOD_OPTIONS, GNUNET_REST_API_NS_GNS, &options_cont },
-    GNUNET_REST_HANDLER_END };
-
-  if (GNUNET_NO ==
-      GNUNET_REST_handle_request (handle->rest_handle, handlers, &err, handle))
-  {
-    handle->response_code = err.error_code;
-    GNUNET_SCHEDULER_add_now (&do_error, handle);
-  }
-}
-
-
 /**
  * Function processing the REST call
  *
@@ -385,12 +378,17 @@ init_cont (struct RequestHandle *handle)
  * @param proc_cls closure for callback function
  * @return GNUNET_OK if request accepted
  */
-static void
+static enum GNUNET_GenericReturnValue
 rest_process_request (struct GNUNET_REST_RequestHandle *rest_handle,
                       GNUNET_REST_ResultProcessor proc,
                       void *proc_cls)
 {
   struct RequestHandle *handle = GNUNET_new (struct RequestHandle);
+  struct GNUNET_REST_RequestHandlerError err;
+  static const struct GNUNET_REST_RequestHandler handlers[] =
+  { { MHD_HTTP_METHOD_GET, GNUNET_REST_API_NS_GNS, &get_gns_cont },
+    { MHD_HTTP_METHOD_OPTIONS, GNUNET_REST_API_NS_GNS, &options_cont },
+    GNUNET_REST_HANDLER_END };
 
   handle->response_code = 0;
   handle->timeout =
@@ -398,18 +396,23 @@ rest_process_request (struct GNUNET_REST_RequestHandle *rest_handle,
   handle->proc_cls = proc_cls;
   handle->proc = proc;
   handle->rest_handle = rest_handle;
-
   handle->url = GNUNET_strdup (rest_handle->url);
+  handle->timeout_task =
+    GNUNET_SCHEDULER_add_delayed (handle->timeout, &do_timeout, handle);
+  GNUNET_CONTAINER_DLL_insert (requests_head,
+                               requests_tail,
+                               handle);
   if (handle->url[strlen (handle->url) - 1] == '/')
     handle->url[strlen (handle->url) - 1] = '\0';
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Connecting...\n");
-  handle->gns = GNUNET_GNS_connect (cfg);
-  init_cont (handle);
+  if (GNUNET_NO ==
+      GNUNET_REST_handle_request (handle->rest_handle, handlers, &err, handle))
+  {
+    cleanup_handle (handle);
+    return GNUNET_NO;
+  }
 
-  handle->timeout_task =
-    GNUNET_SCHEDULER_add_delayed (handle->timeout, &do_timeout, handle);
 
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Connected\n");
+  return GNUNET_YES;
 }
 
 
@@ -426,8 +429,6 @@ libgnunet_plugin_rest_gns_init (void *cls)
   struct GNUNET_REST_Plugin *api;
 
   cfg = cls;
-  if (NULL != plugin.cfg)
-    return NULL; /* can only initialize once! */
   memset (&plugin, 0, sizeof(struct Plugin));
   plugin.cfg = cfg;
   api = GNUNET_new (struct GNUNET_REST_Plugin);
@@ -441,6 +442,7 @@ libgnunet_plugin_rest_gns_init (void *cls)
                    MHD_HTTP_METHOD_PUT,
                    MHD_HTTP_METHOD_DELETE,
                    MHD_HTTP_METHOD_OPTIONS);
+  gns = GNUNET_GNS_connect (cfg);
 
   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, _ ("Gns REST API initialized\n"));
   return api;
@@ -457,7 +459,16 @@ void *
 libgnunet_plugin_rest_gns_done (void *cls)
 {
   struct GNUNET_REST_Plugin *api = cls;
-  struct Plugin *plugin = api->cls;
+  struct RequestHandle *request;
+  struct Plugin *plugin;
+
+  while (NULL != (request = requests_head))
+    do_error (request);
+
+  if (NULL != gns)
+    GNUNET_GNS_disconnect (gns);
+
+  plugin = api->cls;
 
   plugin->cfg = NULL;
 
diff --git a/src/gns/test_dns2gns.conf b/src/gns/test_dns2gns.conf
new file mode 100644
index 0000000000000000000000000000000000000000..3b034f8d51b2547fa9004d8378965e32ae0372c0
--- /dev/null
+++ b/src/gns/test_dns2gns.conf
@@ -0,0 +1,68 @@
+@INLINE@ test_gns_defaults.conf
+
+[namecache]
+DISABLE = YES
+
+[PATHS]
+GNUNET_TEST_HOME = $GNUNET_TMP/test-gnunet-gns-peer-1/
+
+[dht]
+START_ON_DEMAND = YES
+IMMEDIATE_START = YES
+
+[gns]
+# PREFIX = valgrind --leak-check=full --track-origins=yes
+START_ON_DEMAND = YES
+AUTO_IMPORT_PKEY = YES
+MAX_PARALLEL_BACKGROUND_QUERIES = 10
+DEFAULT_LOOKUP_TIMEOUT = 15 s
+RECORD_PUT_INTERVAL = 1 h
+ZONE_PUBLISH_TIME_WINDOW = 1 h
+DNS_ROOT=PD67SGHF3E0447TU9HADIVU9OM7V4QHTOG0EBU69TFRI2LG63DR0
+
+[namestore]
+IMMEDIATE_START = YES
+#PREFIX = valgrind --leak-check=full --track-origins=yes --log-file=/tmp/ns_log
+
+[revocation]
+WORKBITS = 1
+
+[dhtcache]
+QUOTA = 1 MB
+DATABASE = heap
+
+[topology]
+TARGET-CONNECTION-COUNT = 16
+AUTOCONNECT = YES
+FRIENDS-ONLY = NO
+MINIMUM-FRIENDS = 0
+
+[ats]
+WAN_QUOTA_IN = 1 GB
+WAN_QUOTA_OUT = 1 GB
+
+[transport]
+plugins = tcp
+NEIGHBOUR_LIMIT = 50
+PORT = 2091
+
+[transport-tcp]
+TIMEOUT = 300 s
+
+[nat]
+DISABLEV6 = YES
+BINDTO = 127.0.0.1
+ENABLE_UPNP = NO
+BEHIND_NAT = NO
+ALLOW_NAT = NO
+INTERNAL_ADDRESS = 127.0.0.1
+EXTERNAL_ADDRESS = 127.0.0.1
+
+[dns2gns]
+BINARY = gnunet-dns2gns
+START_ON_DEMAND = YES
+IMMEDIATE_START = YES
+RUN_PER_USER = YES
+BIND_TO = 127.0.0.1
+BIND_TO6 = ::1
+OPTIONS = -d 1.1.1.1 -p 12000
diff --git a/src/gns/test_dns2gns.sh b/src/gns/test_dns2gns.sh
new file mode 100755
index 0000000000000000000000000000000000000000..295bcc7665dcf3577edb0fcd1cac3905d4eded9d
--- /dev/null
+++ b/src/gns/test_dns2gns.sh
@@ -0,0 +1,50 @@
+#!/bin/bash
+# This file is in the public domain.
+trap "gnunet-arm -e -c test_dns2gns.conf" INT
+which timeout > /dev/null 2>&1 && DO_TIMEOUT="timeout 30"
+
+LOCATION=$(which gnunet-config)
+if [ -z $LOCATION ]
+then
+  LOCATION="gnunet-config"
+fi
+$LOCATION --version 1> /dev/null
+if test $? != 0
+then
+	echo "GNUnet command line tools cannot be found, check environmental variables PATH and GNUNET_PREFIX"
+	exit 77
+fi
+
+rm -rf `gnunet-config -c test_dns2gns.conf -f -s paths -o GNUNET_TEST_HOME`
+MY_EGO="localego"
+TEST_IP="127.0.0.1"
+TEST_IPV6="dead::beef"
+LABEL="fnord"
+TEST_DOMAIN="gnunet.org"
+
+gnunet-arm -s -c test_dns2gns.conf
+PKEY=`gnunet-identity -V -C $MY_EGO -c test_dns2gns.conf`
+gnunet-namestore -p -z $MY_EGO -a -n $LABEL -t A -V $TEST_IP -e 3600s -c test_dns2gns.conf
+gnunet-namestore -p -z $MY_EGO -a -n $LABEL -t AAAA -V $TEST_IPV6 -e 3600s -c test_dns2gns.conf
+
+# FIXME resolution works but always returns all available records
+# also, the records seem to be returned twice if using GNS
+
+if nslookup -port=12000 $LABEL.$PKEY localhost && nslookup -port=12000 $LABEL.$MY_EGO localhost; then
+  echo "PASS: GNS records can be resolved using dns2gns bridge"
+else
+  echo "FAIL: GNS records can't be resolved using dns2gns bridge"
+  rm -rf `gnunet-config -c test_dns2gns.conf -f -s paths -o GNUNET_TEST_HOME`
+  exit 1
+fi
+
+if nslookup -port=12000 gnunet.org localhost; then
+  echo "PASS: DNS records can be resolved using dns2gns bridge"
+else
+  echo "FAIL: DNS records can't be resolved using dns2gns bridge"
+  rm -rf `gnunet-config -c test_dns2gns.conf -f -s paths -o GNUNET_TEST_HOME`
+  exit 1
+fi
+gnunet-arm -e -c test_dns2gns.conf
+
+rm -rf `gnunet-config -c test_dns2gns.conf -f -s paths -o GNUNET_TEST_HOME`
diff --git a/src/gns/test_gns_lookup_peer1.conf b/src/gns/test_gns_lookup_peer1.conf
new file mode 100644
index 0000000000000000000000000000000000000000..1cf0ba62867896016e74c7317fe0b9baf9cb674f
--- /dev/null
+++ b/src/gns/test_gns_lookup_peer1.conf
@@ -0,0 +1,75 @@
+@INLINE@ test_gns_defaults.conf
+
+[namecache]
+DISABLE = YES
+
+[PATHS]
+GNUNET_TEST_HOME = $GNUNET_TMP/test-gnunet-gns-peer-1/
+GNUNET_RUNTIME_DIR = $GNUNET_TMP/test-gnunet-gns-peer-1-system-runtime/
+GNUNET_USER_RUNTIME_DIR = $GNUNET_TMP/test-gnunet-gns-peer-1-user-runtime/
+
+[dht]
+START_ON_DEMAND = YES
+IMMEDIATE_START = YES
+
+[gns]
+# PREFIX = valgrind --leak-check=full --track-origins=yes
+START_ON_DEMAND = YES
+AUTO_IMPORT_PKEY = YES
+MAX_PARALLEL_BACKGROUND_QUERIES = 10
+DEFAULT_LOOKUP_TIMEOUT = 15 s
+RECORD_PUT_INTERVAL = 1 h
+ZONE_PUBLISH_TIME_WINDOW = 1 h
+DNS_ROOT=PD67SGHF3E0447TU9HADIVU9OM7V4QHTOG0EBU69TFRI2LG63DR0
+
+[namestore]
+IMMEDIATE_START = YES
+#PREFIX = valgrind --leak-check=full --track-origins=yes --log-file=/tmp/ns_log
+
+[revocation]
+WORKBITS = 1
+
+[dhtcache]
+QUOTA = 1 MB
+DATABASE = heap
+
+[topology]
+TARGET-CONNECTION-COUNT = 16
+AUTOCONNECT = YES
+FRIENDS-ONLY = NO
+MINIMUM-FRIENDS = 0
+
+[ats]
+WAN_QUOTA_IN = 1 GB
+WAN_QUOTA_OUT = 1 GB
+
+[transport]
+plugins = unix
+NEIGHBOUR_LIMIT = 50
+PORT = 2091
+
+[transport-unix]
+UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-transport-plugin-unix1.sock
+
+[hostlist]
+SERVERS = http://localhost:9999/
+OPTIONS = -b
+IMMEDIATE_START = YES
+
+[nat]
+DISABLEV6 = YES
+BINDTO = 127.0.0.1
+ENABLE_UPNP = NO
+BEHIND_NAT = NO
+ALLOW_NAT = NO
+INTERNAL_ADDRESS = 127.0.0.1
+EXTERNAL_ADDRESS = 127.0.0.1
+
+[dns2gns]
+BINARY = gnunet-dns2gns
+START_ON_DEMAND = YES
+IMMEDIATE_START = YES
+RUN_PER_USER = YES
+BIND_TO = 127.0.0.1
+BIND_TO6 = ::1
+OPTIONS = -d 1.1.1.1 -p 12000
diff --git a/src/gns/test_gns_lookup_peer2.conf b/src/gns/test_gns_lookup_peer2.conf
new file mode 100644
index 0000000000000000000000000000000000000000..2e861ff0a2a4aa8e5bbcfebbe6f60348ac0198a6
--- /dev/null
+++ b/src/gns/test_gns_lookup_peer2.conf
@@ -0,0 +1,72 @@
+@INLINE@ test_gns_defaults.conf
+
+[namecache]
+DISABLE = YES
+
+[PATHS]
+GNUNET_TEST_HOME = $GNUNET_TMP/test-gnunet-gns-peer-2/
+GNUNET_RUNTIME_DIR = $GNUNET_TMP/test-gnunet-gns-peer-2-runtime/
+GNUNET_USER_RUNTIME_DIR = $GNUNET_TMP/test-gnunet-gns-peer-2-user-runtime/
+
+[dht]
+START_ON_DEMAND = YES
+IMMEDIATE_START = YES
+
+[identity]
+START_ON_DEMAND = YES
+IMMEDIATE_START = YES
+
+[gns]
+# PREFIX = valgrind --leak-check=full --track-origins=yes
+IMMEDIATE_START = YES
+START_ON_DEMAND = YES
+AUTO_IMPORT_PKEY = YES
+MAX_PARALLEL_BACKGROUND_QUERIES = 10
+DEFAULT_LOOKUP_TIMEOUT = 15 s
+RECORD_PUT_INTERVAL = 1 h
+ZONE_PUBLISH_TIME_WINDOW = 1 h
+DNS_ROOT=PD67SGHF3E0447TU9HADIVU9OM7V4QHTOG0EBU69TFRI2LG63DR0
+
+[namestore]
+IMMEDIATE_START = YES
+#PREFIX = valgrind --leak-check=full --track-origins=yes --log-file=/tmp/ns_log
+
+[revocation]
+WORKBITS = 1
+
+[dhtcache]
+QUOTA = 1 MB
+DATABASE = heap
+
+[topology]
+TARGET-CONNECTION-COUNT = 16
+AUTOCONNECT = YES
+FRIENDS-ONLY = NO
+MINIMUM-FRIENDS = 0
+
+[hostlist]
+SERVERS =
+HTTPPORT = 9999
+OPTIONS = -p
+IMMEDIATE_START = YES
+
+
+[ats]
+WAN_QUOTA_IN = 1 GB
+WAN_QUOTA_OUT = 1 GB
+
+[transport]
+plugins = unix
+NEIGHBOUR_LIMIT = 50
+
+[transport-unix]
+UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-transport-plugin-unix2.sock
+
+[nat]
+DISABLEV6 = YES
+BINDTO = 127.0.0.1
+ENABLE_UPNP = NO
+BEHIND_NAT = NO
+ALLOW_NAT = NO
+INTERNAL_ADDRESS = 127.0.0.1
+EXTERNAL_ADDRESS = 127.0.0.1
diff --git a/src/gns/test_gns_multiple_record_lookup.sh b/src/gns/test_gns_multiple_record_lookup.sh
new file mode 100755
index 0000000000000000000000000000000000000000..2d00945d661e4e87adb5fa182fd7b0c66d124446
--- /dev/null
+++ b/src/gns/test_gns_multiple_record_lookup.sh
@@ -0,0 +1,94 @@
+#!/bin/bash
+# This file is in the public domain.
+trap "gnunet-arm -e -c test_gns_lookup_peer1.conf" INT
+trap "gnunet-arm -e -c test_gns_lookup_peer2.conf" INT
+which timeout > /dev/null 2>&1 && DO_TIMEOUT="timeout 5"
+
+unset XDG_DATA_HOME
+unset XDG_CONFIG_HOME
+unset XDG_CACHE_HOME
+
+LOCATION=$(which gnunet-config)
+if [ -z $LOCATION ]
+then
+  LOCATION="gnunet-config"
+fi
+$LOCATION --version 1> /dev/null
+if test $? != 0
+then
+	echo "GNUnet command line tools cannot be found, check environmental variables PATH and GNUNET_PREFIX"
+	exit 77
+fi
+
+rm -rf `gnunet-config -c test_gns_lookup_peer1.conf -f -s paths -o GNUNET_TEST_HOME`
+rm -rf `gnunet-config -c test_gns_lookup_peer2.conf -f -s paths -o GNUNET_TEST_HOME`
+MY_EGO="localego"
+OTHER_EGO="remoteego"
+
+TEST_IP="127.0.0.1"
+TEST_IPV6="dead::beef"
+LABEL="fnord"
+
+gnunet-arm -s -c test_gns_lookup_peer2.conf
+PKEY=`$DO_TIMEOUT gnunet-identity -V -C $OTHER_EGO -c test_gns_lookup_peer2.conf`
+
+# Note: if zonemaster is kept running, it MAY publish the "A" record in the
+# DHT immediately and then _LATER_ also the "AAAA" record. But as then there
+# will be TWO valid blocks in the DHT (one with only A and one with A and
+# AAAA), the subsequent GET for both may fail and only return the result with
+# just the "A" record).
+# If we _waited_ until the original block with just "A" expired, everything
+# would be fine, but we don't want to do that for the test, so we
+# simply pause publishing to the DHT until all records are defined.
+# In the future, it would be good to have an enhanced gnunet-namestore command
+# that would read a series of changes to be made to a record set from
+# stdin and do them _all_ *atomically*. Then we would not need to do this.
+
+gnunet-arm -c test_gns_lookup_peer2.conf -k zonemaster
+gnunet-arm -c test_gns_lookup_peer2.conf -k zonemaster-monitor
+
+gnunet-namestore -p -z $OTHER_EGO -a -n $LABEL -t A -V $TEST_IP -e 3600s -c test_gns_lookup_peer2.conf
+gnunet-namestore -p -z $OTHER_EGO -a -n $LABEL -t AAAA -V $TEST_IPV6 -e 3600s -c test_gns_lookup_peer2.conf
+gnunet-namestore -D -z $OTHER_EGO -n $LABEL
+
+gnunet-arm -c test_gns_lookup_peer2.conf -i zonemaster
+gnunet-arm -c test_gns_lookup_peer2.conf -i zonemaster-monitor
+
+
+gnunet-arm -s -c test_gns_lookup_peer1.conf
+
+
+RESP=`$DO_TIMEOUT gnunet-gns --raw -u $LABEL.$PKEY -t ANY -c test_gns_lookup_peer1.conf`
+RESP1=`$DO_TIMEOUT gnunet-gns --raw -u $LABEL.$PKEY -t A -c test_gns_lookup_peer1.conf`
+RESP2=`$DO_TIMEOUT gnunet-gns --raw -u $LABEL.$PKEY -t AAAA -c test_gns_lookup_peer1.conf`
+
+
+gnunet-arm -e -c test_gns_lookup_peer1.conf
+gnunet-arm -e -c test_gns_lookup_peer2.conf
+
+rm -rf `gnunet-config -c test_gns_lookup_peer1.conf -f -s paths -o GNUNET_TEST_HOME`
+rm -rf `gnunet-config -c test_gns_lookup_peer2.conf -f -s paths -o GNUNET_TEST_HOME`
+
+RESPONSES=($(echo $RESP | tr "\n" " " ))
+
+if [ "$RESP1" == "$TEST_IP" ]
+then
+  echo "PASS: A record resolution from DHT via separate peer"
+else
+  echo "FAIL: A record resolution from DHT via separate peer, got $RESP1, expected $TEST_IP"
+  exit 1
+fi
+if [ "$RESP2" == "$TEST_IPV6" ]
+then
+  echo "PASS: AAAA record resolution from DHT via separate peer"
+else
+  echo "FAIL: AAAA record resolution from DHT via separate peer, got $RESP2, expected $TEST_IPV6"
+  exit 1
+fi
+if [[ "${RESPONSES[0]} ${RESPONSES[1]}" == "$TEST_IPV6 $TEST_IP" ]] || [[ "${RESPONSES[0]} ${RESPONSES[1]}" == "$TEST_IP $TEST_IPV6" ]]
+then
+  echo "PASS: ANY record resolution from DHT via separate peer"
+else
+  echo "FAIL: ANY record resolution from DHT via separate peer, got $RESP, expected $TEST_IPV6 $TEST_IP or $TEST_IP $TEST_IPV6"
+  exit 1
+fi
diff --git a/src/gns/test_gns_proxy.c b/src/gns/test_gns_proxy.c
index 13764d520f129d90c748a5ad1fba18eadf75a641..579de774fae959aac7af13735b884521cc6ec76b 100644
--- a/src/gns/test_gns_proxy.c
+++ b/src/gns/test_gns_proxy.c
@@ -189,7 +189,7 @@ copy_buffer (void *ptr, size_t size, size_t nmemb, void *ctx)
 }
 
 
-static int
+static enum MHD_Result
 mhd_ahc (void *cls,
          struct MHD_Connection *connection,
          const char *url,
@@ -528,8 +528,6 @@ run (void *cls,
 int
 main (int argc, char *const *argv)
 {
-  char *tmp_argv;
-
   struct GNUNET_GETOPT_CommandLineOption options[] = {
     GNUNET_GETOPT_option_uint16 ('p',
                                  "port",
@@ -559,7 +557,7 @@ main (int argc, char *const *argv)
   }
   if (GNUNET_OK !=
       GNUNET_STRINGS_get_utf8_args (argc, argv,
-                                    &argc, &tmp_argv))
+                                    &argc, &argv))
     return 2;
   GNUNET_log_setup ("gnunet-gns-proxy-test",
                     "WARNING",
@@ -570,7 +568,7 @@ main (int argc, char *const *argv)
                                        options,
                                        &run, NULL))
     return 1;
-  GNUNET_free (tmp_argv);
+  GNUNET_free_nz ((void*) argv);
   return global_ret;
 }
 
diff --git a/src/gns/test_gns_quickupdate.sh b/src/gns/test_gns_quickupdate.sh
new file mode 100755
index 0000000000000000000000000000000000000000..eac69103da4fc3d685878b622ba47f550e119ad6
--- /dev/null
+++ b/src/gns/test_gns_quickupdate.sh
@@ -0,0 +1,65 @@
+#!/bin/sh
+# This file is in the public domain.
+trap "gnunet-arm -e -c test_gns_lookup.conf" INT
+
+LOCATION=$(which gnunet-config)
+if [ -z $LOCATION ]
+then
+  LOCATION="gnunet-config"
+fi
+$LOCATION --version 1> /dev/null
+if test $? != 0
+then
+	echo "GNUnet command line tools cannot be found, check environmental variables PATH and GNUNET_PREFIX"
+	exit 77
+fi
+
+MY_EGO="myego"
+OTHER_EGO="delegatedego"
+
+
+rm -rf `gnunet-config -c test_gns_lookup.conf -f -s paths -o GNUNET_TEST_HOME`
+which timeout > /dev/null 2>&1 && DO_TIMEOUT="timeout 5"
+TEST_IP="127.0.0.1"
+gnunet-arm -s -c test_gns_lookup.conf
+gnunet-identity -C $MY_EGO -c test_gns_lookup.conf
+gnunet-identity -C $OTHER_EGO -c test_gns_lookup.conf
+DELEGATED_PKEY=$(gnunet-identity -d -c test_gns_lookup.conf | grep $OTHER_EGO | awk '{print $3}')
+gnunet-arm -i gns -c test_gns_lookup.conf
+gnunet-namestore -p -z $MY_EGO -a -n b -t PKEY -V $DELEGATED_PKEY -e never -c test_gns_lookup.conf
+# Give GNS/namestore time to fully start and finish initial iteration
+sleep 2
+# Performing namestore update
+gnunet-namestore -p -z $OTHER_EGO -a -n www -t A -V $TEST_IP -e never -c test_gns_lookup.conf
+# Give GNS chance to observe store event via monitor
+sleep 1
+gnunet-namestore -z $OTHER_EGO -d -n www -t A -V $TEST_IP  -e never -c test_gns_lookup.conf
+# give GNS chance to process monitor event
+sleep 1
+# stop everything and restart to check that DHT PUT did happen
+gnunet-arm -k gns -c test_gns_lookup.conf
+gnunet-arm -k namestore -c test_gns_lookup.conf
+gnunet-arm -k namecache -c test_gns_lookup.conf
+gnunet-arm -k zonemaster -c test_gns_lookup.conf
+# Purge nameacache, as we might otherwise fetch from there
+# FIXME: testcase started failing after the line below was fixed by adding '-f',
+# might have never worked (!)
+rm -r `gnunet-config -f -c test_gns_lookup.conf -s namecache-sqlite -o FILENAME`
+gnunet-arm -i namestore -c test_gns_lookup.conf
+gnunet-arm -i namecache -c test_gns_lookup.conf
+gnunet-arm -i zonemaster -c test_gns_lookup.conf
+gnunet-arm -i gns -c test_gns_lookup.conf
+RES_IP=`$DO_TIMEOUT gnunet-gns --raw -u www.b.$MY_EGO -t A -c test_gns_lookup.conf`
+gnunet-namestore -z $MY_EGO -d -n b -t PKEY -V $DELEGATED_PKEY  -e never -c test_gns_lookup.conf
+gnunet-identity -D $MY_EGO -c test_gns_lookup.conf
+gnunet-identity -D $OTHER_EGO -c test_gns_lookup.conf
+gnunet-arm -e -c test_gns_lookup.conf
+rm -rf `gnunet-config -c test_gns_lookup.conf -f -s paths -o GNUNET_TEST_HOME`
+
+if [ "$RES_IP" = "$TEST_IP" ]
+then
+  exit 0
+else
+  echo "Failed to properly resolve IP, expected $TEST_IP, got $RES_IP."
+  exit 1
+fi
diff --git a/src/gns/w32resolver.h b/src/gns/w32resolver.h
new file mode 100644
index 0000000000000000000000000000000000000000..c404e37d35de0cf9e4582aa8b8837b4d5f3e190a
--- /dev/null
+++ b/src/gns/w32resolver.h
@@ -0,0 +1,71 @@
+/*
+     This file is part of GNUnet.
+     Copyright (C) 2009, 2012 GNUnet e.V.
+
+     GNUnet is free software: you can redistribute it and/or modify it
+     under the terms of the GNU Affero General Public License as published
+     by the Free Software Foundation, either version 3 of the License,
+     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
+     Affero General Public License for more details.
+
+     You should have received a copy of the GNU Affero General Public License
+     along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+     SPDX-License-Identifier: AGPL3.0-or-later
+ */
+
+/**
+ * @author Christian Grothoff
+ * @file gns/w32resolver.h
+ */
+#ifndef W32RESOLVER_H
+#define W32RESOLVER_H
+
+#include "platform.h"
+#include "gnunet_crypto_lib.h"
+#include "gnunet_common.h"
+
+/**
+ * Request DNS resolution.
+ */
+#define GNUNET_MESSAGE_TYPE_W32RESOLVER_REQUEST 4
+
+/**
+ * Response to a DNS resolution request.
+ */
+#define GNUNET_MESSAGE_TYPE_W32RESOLVER_RESPONSE 5
+
+GNUNET_NETWORK_STRUCT_BEGIN
+
+/**
+ * Request for the resolver.  Followed by the 0-terminated hostname.
+ *
+ * The response will be one or more messages of type
+ * W32RESOLVER_RESPONSE, each with the message header immediately
+ * followed by the requested data (struct in[6]_addr).
+ * The last W32RESOLVER_RESPONSE will just be a header without any data
+ * (used to indicate the end of the list).
+ */
+struct GNUNET_W32RESOLVER_GetMessage
+{
+  /**
+   * Type:  GNUNET_MESSAGE_TYPE_W32RESOLVER_REQUEST
+   */
+  struct GNUNET_MessageHeader header;
+
+  uint32_t af GNUNET_PACKED;
+
+  uint32_t sc_data1 GNUNET_PACKED;
+  uint16_t sc_data2 GNUNET_PACKED;
+  uint16_t sc_data3 GNUNET_PACKED;
+  uint8_t sc_data4[8];
+  /* followed by 0-terminated string for A/AAAA lookup */
+};
+
+GNUNET_NETWORK_STRUCT_END
+
+#endif
diff --git a/src/gns/zonefiles/188JSUMKEF25GVU8TTV0PBNNN8JVCPUEDFV1UHJJU884JD25V0T0.zkey b/src/gns/zonefiles/188JSUMKEF25GVU8TTV0PBNNN8JVCPUEDFV1UHJJU884JD25V0T0.zkey
new file mode 100644
index 0000000000000000000000000000000000000000..895946037042c12e9a0db16cb57bb1c5e5e8ef30
Binary files /dev/null and b/src/gns/zonefiles/188JSUMKEF25GVU8TTV0PBNNN8JVCPUEDFV1UHJJU884JD25V0T0.zkey differ
diff --git a/src/gnsrecord/.gitignore b/src/gnsrecord/.gitignore
new file mode 100644
index 0000000000000000000000000000000000000000..dca3bd309b8db2c9424a91a1ab60b07973041961
--- /dev/null
+++ b/src/gnsrecord/.gitignore
@@ -0,0 +1,6 @@
+test_gnsrecord_block_expiration
+test_gnsrecord_crypto
+test_gnsrecord_serialization
+zonefiles
+perf_gnsrecord_crypto
+gnunet-gnsrecord-tvg
diff --git a/src/gnsrecord/gnsrecord.c b/src/gnsrecord/gnsrecord.c
index c6ebd7c2947a04a26b707e83c46796591f5a5dbc..8d5a6d95b9af5a9b765b75c4decf983e5d34a1ee 100644
--- a/src/gnsrecord/gnsrecord.c
+++ b/src/gnsrecord/gnsrecord.c
@@ -102,8 +102,15 @@ init ()
   if (1 == once)
     return;
   once = 1;
+  const struct GNUNET_OS_ProjectData *pd = GNUNET_OS_project_data_get ();
+  const struct GNUNET_OS_ProjectData *dpd = GNUNET_OS_project_data_default ();
+
+  if (pd != dpd)
+    GNUNET_OS_init (dpd);
   GNUNET_PLUGIN_load_all ("libgnunet_plugin_gnsrecord_", NULL,
                           &add_plugin, NULL);
+  if (pd != dpd)
+    GNUNET_OS_init (pd);
 }
 
 
@@ -114,6 +121,11 @@ void __attribute__ ((destructor))
 GNSRECORD_fini ()
 {
   struct Plugin *plugin;
+  const struct GNUNET_OS_ProjectData *pd = GNUNET_OS_project_data_get ();
+  const struct GNUNET_OS_ProjectData *dpd = GNUNET_OS_project_data_default ();
+
+  if (pd != dpd)
+    GNUNET_OS_init (dpd);
 
   for (unsigned int i = 0; i < num_plugins; i++)
   {
@@ -125,6 +137,10 @@ GNSRECORD_fini ()
     GNUNET_free (plugin);
   }
   GNUNET_free (gns_plugins);
+
+  if (pd != dpd)
+    GNUNET_OS_init (pd);
+
   gns_plugins = NULL;
   once = 0;
   num_plugins = 0;
diff --git a/src/hello/.gitignore b/src/hello/.gitignore
new file mode 100644
index 0000000000000000000000000000000000000000..bb49ceb204fd315a614c497474d1e86bf995ec8e
--- /dev/null
+++ b/src/hello/.gitignore
@@ -0,0 +1,3 @@
+gnunet-hello
+test_friend_hello
+test_hello
diff --git a/src/hostlist/.gitignore b/src/hostlist/.gitignore
new file mode 100644
index 0000000000000000000000000000000000000000..b16e3444aa1a320e23b8d3e5aca97ecdc2c732b8
--- /dev/null
+++ b/src/hostlist/.gitignore
@@ -0,0 +1,4 @@
+gnunet-daemon-hostlist
+test_gnunet_daemon_hostlist
+test_gnunet_daemon_hostlist_learning
+test_gnunet_daemon_hostlist_reconnect
diff --git a/src/hostlist/gnunet-daemon-hostlist_client.c b/src/hostlist/gnunet-daemon-hostlist_client.c
index 5dc2e7f2adca893b0f8e86cf273e33caa8d89908..b377f204169f26eb973dcf7bee614a6301489992 100644
--- a/src/hostlist/gnunet-daemon-hostlist_client.c
+++ b/src/hostlist/gnunet-daemon-hostlist_client.c
@@ -540,12 +540,12 @@ download_get_url ()
   {                                                 \
     ret = curl_easy_setopt (c, a, b);               \
     if (CURLE_OK != ret)                            \
-      GNUNET_log (GNUNET_ERROR_TYPE_WARNING,        \
-                  _ ("%s failed at %s:%d: `%s'\n"), \
-                  "curl_easy_setopt",               \
-                  __FILE__,                         \
-                  __LINE__,                         \
-                  curl_easy_strerror (ret));        \
+    GNUNET_log (GNUNET_ERROR_TYPE_WARNING,        \
+                _ ("%s failed at %s:%d: `%s'\n"), \
+                "curl_easy_setopt",               \
+                __FILE__,                         \
+                __LINE__,                         \
+                curl_easy_strerror (ret));        \
   } while (0)
 
 
@@ -1418,11 +1418,12 @@ load_hostlist_file ()
 
   counter = 0;
   struct GNUNET_BIO_ReadSpec rs[] = {
-    GNUNET_BIO_read_spec_int32 ("times used", (int32_t *)&times_used),
+    GNUNET_BIO_read_spec_int32 ("times used", (int32_t *) &times_used),
     GNUNET_BIO_read_spec_int64 ("quality", (int64_t *) &quality),
     GNUNET_BIO_read_spec_int64 ("last used", (int64_t *) &last_used),
     GNUNET_BIO_read_spec_int64 ("created", (int64_t *) &created),
-    GNUNET_BIO_read_spec_int32 ("hellos returned", (int32_t *) &hellos_returned),
+    GNUNET_BIO_read_spec_int32 ("hellos returned",
+                                (int32_t *) &hellos_returned),
     GNUNET_BIO_read_spec_end (),
   };
   while ((GNUNET_OK == GNUNET_BIO_read_string (rh, "url", &uri, MAX_URL_LEN)) &&
@@ -1527,7 +1528,8 @@ save_hostlist_file (int shutdown)
     {
       struct GNUNET_BIO_WriteSpec ws[] = {
         GNUNET_BIO_write_spec_string ("hostlist uri", pos->hostlist_uri),
-        GNUNET_BIO_write_spec_int32 ("times used", (int32_t *) &pos->times_used),
+        GNUNET_BIO_write_spec_int32 ("times used",
+                                     (int32_t *) &pos->times_used),
         GNUNET_BIO_write_spec_int64 ("quality", (int64_t *) &pos->quality),
         GNUNET_BIO_write_spec_int64 (
           "last usage",
diff --git a/src/hostlist/hostlists_learn_peer2.file b/src/hostlist/hostlists_learn_peer2.file
new file mode 100644
index 0000000000000000000000000000000000000000..19d031c3e4b40c47fb3b5f36660d0475765518ab
Binary files /dev/null and b/src/hostlist/hostlists_learn_peer2.file differ
diff --git a/src/hostlist/test_gnunet_daemon_hostlist.c b/src/hostlist/test_gnunet_daemon_hostlist.c
index d10924eac5d87d3f9d95898d67ac997af2773883..063db2f993a99fddf59a46329ce244ba85fe9eaa 100644
--- a/src/hostlist/test_gnunet_daemon_hostlist.c
+++ b/src/hostlist/test_gnunet_daemon_hostlist.c
@@ -136,8 +136,8 @@ setup_peer (struct PeerContext *p, const char *cfgname)
 
   binary = GNUNET_OS_get_libexec_binary_path ("gnunet-service-arm");
   p->cfg = GNUNET_CONFIGURATION_create ();
-  p->arm_proc = GNUNET_OS_start_process (GNUNET_YES,
-                                         GNUNET_OS_INHERIT_STD_OUT_AND_ERR,
+  p->arm_proc = GNUNET_OS_start_process (GNUNET_OS_INHERIT_STD_OUT_AND_ERR
+                                         | GNUNET_OS_USE_PIPE_CONTROL,
                                          NULL,
                                          NULL,
                                          NULL,
diff --git a/src/hostlist/test_gnunet_daemon_hostlist_learning.c b/src/hostlist/test_gnunet_daemon_hostlist_learning.c
index a50e7acc2194cc01c50bee49155b05220c69d4eb..a0656f770ba2f221203c95c7e3c57bee0d783c71 100644
--- a/src/hostlist/test_gnunet_daemon_hostlist_learning.c
+++ b/src/hostlist/test_gnunet_daemon_hostlist_learning.c
@@ -412,7 +412,8 @@ setup_learn_peer (struct PeerContext *p,
   binary = GNUNET_OS_get_libexec_binary_path ("gnunet-service-arm");
   p->cfg = GNUNET_CONFIGURATION_create ();
   p->arm_proc =
-    GNUNET_OS_start_process (GNUNET_YES, GNUNET_OS_INHERIT_STD_OUT_AND_ERR,
+    GNUNET_OS_start_process (GNUNET_OS_INHERIT_STD_OUT_AND_ERR
+                             | GNUNET_OS_USE_PIPE_CONTROL,
                              NULL, NULL, NULL,
                              binary,
                              "gnunet-service-arm",
@@ -459,8 +460,8 @@ setup_adv_peer (struct PeerContext *p,
   binary = GNUNET_OS_get_libexec_binary_path ("gnunet-service-arm");
   p->cfg = GNUNET_CONFIGURATION_create ();
   p->arm_proc =
-    GNUNET_OS_start_process (GNUNET_YES,
-                             GNUNET_OS_INHERIT_STD_OUT_AND_ERR,
+    GNUNET_OS_start_process (GNUNET_OS_INHERIT_STD_OUT_AND_ERR
+                             | GNUNET_OS_USE_PIPE_CONTROL,
                              NULL, NULL, NULL,
                              binary,
                              "gnunet-service-arm",
diff --git a/src/hostlist/test_gnunet_daemon_hostlist_reconnect.c b/src/hostlist/test_gnunet_daemon_hostlist_reconnect.c
index 657b85fd8ccd092c4e9b774a1dbf2a8492cf7ab5..321f96f3d44703eb23405f933c546294ca395156 100644
--- a/src/hostlist/test_gnunet_daemon_hostlist_reconnect.c
+++ b/src/hostlist/test_gnunet_daemon_hostlist_reconnect.c
@@ -105,8 +105,8 @@ setup_peer (struct PeerContext *p, const char *cfgname)
 
   binary = GNUNET_OS_get_libexec_binary_path ("gnunet-service-arm");
   p->cfg = GNUNET_CONFIGURATION_create ();
-  p->arm_proc = GNUNET_OS_start_process (GNUNET_YES,
-                                         GNUNET_OS_INHERIT_STD_OUT_AND_ERR,
+  p->arm_proc = GNUNET_OS_start_process (GNUNET_OS_INHERIT_STD_OUT_AND_ERR
+                                         | GNUNET_OS_USE_PIPE_CONTROL,
                                          NULL,
                                          NULL,
                                          NULL,
diff --git a/src/identity/.gitignore b/src/identity/.gitignore
new file mode 100644
index 0000000000000000000000000000000000000000..634a0bdd6a361704f2494ad3e2eb126b265e9383
--- /dev/null
+++ b/src/identity/.gitignore
@@ -0,0 +1,4 @@
+gnunet-service-identity
+gnunet-identity
+test_identity
+test_identity_defaults
diff --git a/src/identity/gnunet-identity.c b/src/identity/gnunet-identity.c
index cf44afd1fdbcca2f06cef17003fd66a5a4747f5f..d0f5546f3796062334ea9004e53c4ee65ae37a5c 100644
--- a/src/identity/gnunet-identity.c
+++ b/src/identity/gnunet-identity.c
@@ -406,7 +406,8 @@ run (void *cls,
       GNUNET_STRINGS_string_to_data (privkey_ego,
                                      strlen (privkey_ego),
                                      &pk,
-                                     sizeof(struct GNUNET_CRYPTO_EcdsaPrivateKey));
+                                     sizeof(struct
+                                            GNUNET_CRYPTO_EcdsaPrivateKey));
       create_op =
         GNUNET_IDENTITY_create (sh,
                                 create_ego,
@@ -452,7 +453,8 @@ main (int argc, char *const *argv)
     GNUNET_GETOPT_option_string ('P',
                                  "privkey",
                                  "PRIVATE_KEY",
-                                 gettext_noop ("set the private key for the identity to PRIVATE_KEY (use together with -C)"),
+                                 gettext_noop (
+                                   "set the private key for the identity to PRIVATE_KEY (use together with -C)"),
                                  &privkey_ego),
     GNUNET_GETOPT_option_flag ('d',
                                "display",
diff --git a/src/identity/identity_api.c b/src/identity/identity_api.c
index 5d17ac5d5216991ed8384cf57c056645aee7f04d..f7aca1655290052b23ec5621d8975e2c8d008d34 100644
--- a/src/identity/identity_api.c
+++ b/src/identity/identity_api.c
@@ -150,9 +150,9 @@ struct GNUNET_IDENTITY_Handle
 /**
  * Obtain the ego representing 'anonymous' users.
  *
- * @return handle for the anonymous user, must not be freed
+ * @return handle for the anonymous user, MUST NOT be freed
  */
-const struct GNUNET_IDENTITY_Ego *
+struct GNUNET_IDENTITY_Ego *
 GNUNET_IDENTITY_ego_get_anonymous ()
 {
   static struct GNUNET_IDENTITY_Ego anon;
diff --git a/src/identity/plugin_rest_identity.c b/src/identity/plugin_rest_identity.c
index 5aca07ddfb09d505911532d4038661ebae8485c3..d86d29e36c4383dd1fa32138fe3932d702e109be 100644
--- a/src/identity/plugin_rest_identity.c
+++ b/src/identity/plugin_rest_identity.c
@@ -126,6 +126,26 @@ const struct GNUNET_CONFIGURATION_Handle *cfg;
  */
 static char *allow_methods;
 
+/**
+ * Ego list
+ */
+static struct EgoEntry *ego_head;
+
+/**
+ * Ego list
+ */
+static struct EgoEntry *ego_tail;
+
+/**
+ * The processing state
+ */
+static int state;
+
+/**
+ * Handle to Identity service.
+ */
+static struct GNUNET_IDENTITY_Handle *identity_handle;
+
 /**
  * @brief struct returned by the initialization function of the plugin
  */
@@ -171,40 +191,29 @@ struct EgoEntry
 struct RequestHandle
 {
   /**
-   * The data from the REST request
-   */
-  const char *data;
-
-  /**
-   * The name to look up
-   */
-  char *name;
-
-  /**
-   * the length of the REST data
+   * DLL
    */
-  size_t data_size;
-
+  struct RequestHandle *next;
 
   /**
-   * Ego list
+   * DLL
    */
-  struct EgoEntry *ego_head;
+  struct RequestHandle *prev;
 
   /**
-   * Ego list
+   * The data from the REST request
    */
-  struct EgoEntry *ego_tail;
+  const char *data;
 
   /**
-   * The processing state
+   * The name to look up
    */
-  int state;
+  char *name;
 
   /**
-   * Handle to Identity service.
+   * the length of the REST data
    */
-  struct GNUNET_IDENTITY_Handle *identity_handle;
+  size_t data_size;
 
   /**
    * IDENTITY Operation
@@ -252,6 +261,16 @@ struct RequestHandle
   int response_code;
 };
 
+/**
+ * DLL
+ */
+static struct RequestHandle *requests_head;
+
+/**
+ * DLL
+ */
+static struct RequestHandle *requests_tail;
+
 /**
  * Cleanup lookup handle
  * @param handle Handle to clean up
@@ -260,8 +279,6 @@ static void
 cleanup_handle (void *cls)
 {
   struct RequestHandle *handle = cls;
-  struct EgoEntry *ego_entry;
-  struct EgoEntry *ego_tmp;
 
   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Cleaning up\n");
   if (NULL != handle->timeout_task)
@@ -276,18 +293,9 @@ cleanup_handle (void *cls)
     GNUNET_free (handle->emsg);
   if (NULL != handle->name)
     GNUNET_free (handle->name);
-  if (NULL != handle->identity_handle)
-    GNUNET_IDENTITY_disconnect (handle->identity_handle);
-
-  for (ego_entry = handle->ego_head; NULL != ego_entry;)
-  {
-    ego_tmp = ego_entry;
-    ego_entry = ego_entry->next;
-    GNUNET_free (ego_tmp->identifier);
-    GNUNET_free (ego_tmp->keystring);
-    GNUNET_free (ego_tmp);
-  }
-
+  GNUNET_CONTAINER_DLL_remove (requests_head,
+                               requests_tail,
+                               handle);
   GNUNET_free (handle);
 }
 
@@ -338,7 +346,7 @@ get_egoentry (struct RequestHandle *handle, char *pubkey, char *name)
 
   if (NULL != pubkey)
   {
-    for (ego_entry = handle->ego_head; NULL != ego_entry;
+    for (ego_entry = ego_head; NULL != ego_entry;
          ego_entry = ego_entry->next)
     {
       if (0 != strcasecmp (pubkey, ego_entry->keystring))
@@ -348,7 +356,7 @@ get_egoentry (struct RequestHandle *handle, char *pubkey, char *name)
   }
   if (NULL != name)
   {
-    for (ego_entry = handle->ego_head; NULL != ego_entry;
+    for (ego_entry = ego_head; NULL != ego_entry;
          ego_entry = ego_entry->next)
     {
       if (0 != strcasecmp (name, ego_entry->identifier))
@@ -438,7 +446,7 @@ ego_get_subsystem (struct GNUNET_REST_RequestHandle *con_handle,
   // requested default identity of subsystem
   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Looking for %s's ego\n", subsystem);
 
-  handle->op = GNUNET_IDENTITY_get (handle->identity_handle,
+  handle->op = GNUNET_IDENTITY_get (identity_handle,
                                     subsystem,
                                     &ego_get_for_subsystem,
                                     handle);
@@ -476,7 +484,7 @@ ego_get_all (struct GNUNET_REST_RequestHandle *con_handle,
 
   json_root = json_array ();
   // Return ego/egos
-  for (ego_entry = handle->ego_head; NULL != ego_entry;
+  for (ego_entry = ego_head; NULL != ego_entry;
        ego_entry = ego_entry->next)
   {
     json_ego = json_object ();
@@ -766,7 +774,7 @@ ego_edit (struct RequestHandle *handle, struct EgoEntry *ego_entry)
     json_decref (data_js);
     return;
   }
-  handle->op = GNUNET_IDENTITY_rename (handle->identity_handle,
+  handle->op = GNUNET_IDENTITY_rename (identity_handle,
                                        ego_entry->identifier,
                                        newname,
                                        &do_finished,
@@ -956,7 +964,7 @@ ego_edit_subsystem (struct GNUNET_REST_RequestHandle *con_handle,
   }
 
   handle->response_code = MHD_HTTP_NO_CONTENT;
-  handle->op = GNUNET_IDENTITY_set (handle->identity_handle,
+  handle->op = GNUNET_IDENTITY_set (identity_handle,
                                     newsubsys,
                                     ego_entry->ego,
                                     &do_finished,
@@ -1047,7 +1055,7 @@ ego_create (struct GNUNET_REST_RequestHandle *con_handle,
     return;
   }
   GNUNET_STRINGS_utf8_tolower (egoname, egoname);
-  for (ego_entry = handle->ego_head; NULL != ego_entry;
+  for (ego_entry = ego_head; NULL != ego_entry;
        ego_entry = ego_entry->next)
   {
     if (0 == strcasecmp (egoname, ego_entry->identifier))
@@ -1065,14 +1073,15 @@ ego_create (struct GNUNET_REST_RequestHandle *con_handle,
     GNUNET_STRINGS_string_to_data (privkey,
                                    strlen (privkey),
                                    &pk,
-                                   sizeof(struct GNUNET_CRYPTO_EcdsaPrivateKey));
+                                   sizeof(struct
+                                          GNUNET_CRYPTO_EcdsaPrivateKey));
     pk_ptr = &pk;
   }
   else
     pk_ptr = NULL;
   json_decref (data_js);
   handle->response_code = MHD_HTTP_CREATED;
-  handle->op = GNUNET_IDENTITY_create (handle->identity_handle,
+  handle->op = GNUNET_IDENTITY_create (identity_handle,
                                        handle->name,
                                        pk_ptr,
                                        &do_finished_create,
@@ -1117,7 +1126,7 @@ ego_delete_pubkey (struct GNUNET_REST_RequestHandle *con_handle,
   }
 
   handle->response_code = MHD_HTTP_NO_CONTENT;
-  handle->op = GNUNET_IDENTITY_delete (handle->identity_handle,
+  handle->op = GNUNET_IDENTITY_delete (identity_handle,
                                        ego_entry->identifier,
                                        &do_finished,
                                        handle);
@@ -1161,7 +1170,7 @@ ego_delete_name (struct GNUNET_REST_RequestHandle *con_handle,
   }
 
   handle->response_code = MHD_HTTP_NO_CONTENT;
-  handle->op = GNUNET_IDENTITY_delete (handle->identity_handle,
+  handle->op = GNUNET_IDENTITY_delete (identity_handle,
                                        ego_entry->identifier,
                                        &do_finished,
                                        handle);
@@ -1192,144 +1201,78 @@ options_cont (struct GNUNET_REST_RequestHandle *con_handle,
 }
 
 
-/**
- * Handle rest request
- *
- * @param handle the request handle
- */
 static void
-init_cont (struct RequestHandle *handle)
+list_ego (void *cls,
+          struct GNUNET_IDENTITY_Ego *ego,
+          void **ctx,
+          const char *identifier)
 {
-  struct GNUNET_REST_RequestHandlerError err;
-  static const struct GNUNET_REST_RequestHandler handlers[] =
-  { { MHD_HTTP_METHOD_GET, GNUNET_REST_API_NS_IDENTITY, &ego_get_all },
-    { MHD_HTTP_METHOD_GET, GNUNET_REST_API_NS_IDENTITY_PUBKEY,
-      &ego_get_pubkey },
-    { MHD_HTTP_METHOD_GET, GNUNET_REST_API_NS_IDENTITY_NAME, &ego_get_name },
-    { MHD_HTTP_METHOD_GET,
-      GNUNET_REST_API_NS_IDENTITY_SUBSYSTEM,
-      &ego_get_subsystem },
-    { MHD_HTTP_METHOD_PUT,
-      GNUNET_REST_API_NS_IDENTITY_PUBKEY,
-      &ego_edit_pubkey },
-    { MHD_HTTP_METHOD_PUT, GNUNET_REST_API_NS_IDENTITY_NAME, &ego_edit_name },
-    { MHD_HTTP_METHOD_PUT,
-      GNUNET_REST_API_NS_IDENTITY_SUBSYSTEM,
-      &ego_edit_subsystem },
-    { MHD_HTTP_METHOD_POST, GNUNET_REST_API_NS_IDENTITY, &ego_create },
-    { MHD_HTTP_METHOD_DELETE,
-      GNUNET_REST_API_NS_IDENTITY_PUBKEY,
-      &ego_delete_pubkey },
-    { MHD_HTTP_METHOD_DELETE,
-      GNUNET_REST_API_NS_IDENTITY_NAME,
-      &ego_delete_name },
-    { MHD_HTTP_METHOD_OPTIONS, GNUNET_REST_API_NS_IDENTITY, &options_cont },
-    GNUNET_REST_HANDLER_END };
-
-  if (GNUNET_NO ==
-      GNUNET_REST_handle_request (handle->rest_handle, handlers, &err, handle))
-  {
-    handle->response_code = err.error_code;
-    GNUNET_SCHEDULER_add_now (&do_error, handle);
-  }
-}
-
-
-/**
- * If listing is enabled, prints information about the egos.
- *
- * This function is initially called for all egos and then again
- * whenever a ego's identifier changes or if it is deleted.  At the
- * end of the initial pass over all egos, the function is once called
- * with 'NULL' for 'ego'. That does NOT mean that the callback won't
- * be invoked in the future or that there was an error.
- *
- * When used with 'GNUNET_IDENTITY_create' or 'GNUNET_IDENTITY_get',
- * this function is only called ONCE, and 'NULL' being passed in
- * 'ego' does indicate an error (i.e. name is taken or no default
- * value is known).  If 'ego' is non-NULL and if '*ctx'
- * is set in those callbacks, the value WILL be passed to a subsequent
- * call to the identity callback of 'GNUNET_IDENTITY_connect' (if
- * that one was not NULL).
- *
- * When an identity is renamed, this function is called with the
- * (known) ego but the NEW identifier.
- *
- * When an identity is deleted, this function is called with the
- * (known) ego and "NULL" for the 'identifier'.  In this case,
- * the 'ego' is henceforth invalid (and the 'ctx' should also be
- * cleaned up).
- *
- * @param cls closure
- * @param ego ego handle
- * @param ctx context for application to store data for this ego
- *                 (during the lifetime of this process, initially NULL)
- * @param identifier identifier assigned by the user for this ego,
- *                   NULL if the user just deleted the ego and it
- *                   must thus no longer be used
- */
-static void
-init_egos (void *cls,
-           struct GNUNET_IDENTITY_Ego *ego,
-           void **ctx,
-           const char *identifier)
-{
-  struct RequestHandle *handle = cls;
   struct EgoEntry *ego_entry;
   struct GNUNET_CRYPTO_EcdsaPublicKey pk;
 
-  if ((NULL == ego) && (ID_REST_STATE_INIT == handle->state))
+  if ((NULL == ego) && (ID_REST_STATE_INIT == state))
   {
-    handle->state = ID_REST_STATE_POST_INIT;
-    init_cont (handle);
+    state = ID_REST_STATE_POST_INIT;
     return;
   }
-  if (ID_REST_STATE_INIT == handle->state)
+  if (ID_REST_STATE_INIT == state)
   {
     ego_entry = GNUNET_new (struct EgoEntry);
     GNUNET_IDENTITY_ego_get_public_key (ego, &pk);
     ego_entry->keystring = GNUNET_CRYPTO_ecdsa_public_key_to_string (&pk);
     ego_entry->ego = ego;
     ego_entry->identifier = GNUNET_strdup (identifier);
-    GNUNET_CONTAINER_DLL_insert_tail (handle->ego_head,
-                                      handle->ego_tail,
+    GNUNET_CONTAINER_DLL_insert_tail (ego_head,
+                                      ego_tail,
                                       ego_entry);
-    return;
   }
-  // Check if ego exists
-  for (ego_entry = handle->ego_head; NULL != ego_entry;)
+  /* Ego renamed or added */
+  if (identifier != NULL)
   {
-    struct EgoEntry *tmp = ego_entry;
-    ego_entry = ego_entry->next;
-    if (ego != tmp->ego)
-      continue;
-    // Deleted
-    if (NULL == identifier)
+    for (ego_entry = ego_head; NULL != ego_entry;
+         ego_entry = ego_entry->next)
     {
-      GNUNET_CONTAINER_DLL_remove (handle->ego_head,
-                                   handle->ego_tail,
-                                   tmp);
-      GNUNET_free (tmp->keystring);
-      GNUNET_free (tmp->identifier);
-      GNUNET_free (tmp);
+      if (ego_entry->ego == ego)
+      {
+        /* Rename */
+        GNUNET_free (ego_entry->identifier);
+        ego_entry->identifier = GNUNET_strdup (identifier);
+        break;
+      }
     }
-    else
+    if (NULL == ego_entry)
+    {
+      /* Add */
+      ego_entry = GNUNET_new (struct EgoEntry);
+      GNUNET_IDENTITY_ego_get_public_key (ego, &pk);
+      ego_entry->keystring = GNUNET_CRYPTO_ecdsa_public_key_to_string (&pk);
+      ego_entry->ego = ego;
+      ego_entry->identifier = GNUNET_strdup (identifier);
+      GNUNET_CONTAINER_DLL_insert_tail (ego_head,
+                                        ego_tail,
+                                        ego_entry);
+    }
+  }
+  else
+  {
+    /* Delete */
+    for (ego_entry = ego_head; NULL != ego_entry;
+         ego_entry = ego_entry->next)
     {
-      // Renamed
-      GNUNET_free (tmp->identifier);
-      tmp->identifier = GNUNET_strdup (identifier);
+      if (ego_entry->ego == ego)
+        break;
     }
+    if (NULL == ego_entry)
+      return; /* Not found */
+
+    GNUNET_CONTAINER_DLL_remove (ego_head,
+                                 ego_tail,
+                                 ego_entry);
+    GNUNET_free (ego_entry->identifier);
+    GNUNET_free (ego_entry->keystring);
+    GNUNET_free (ego_entry);
     return;
   }
-  // New ego
-  ego_entry = GNUNET_new (struct EgoEntry);
-  GNUNET_IDENTITY_ego_get_public_key (ego, &pk);
-  ego_entry->keystring = GNUNET_CRYPTO_ecdsa_public_key_to_string (&pk);
-  ego_entry->ego = ego;
-  GNUNET_asprintf (&ego_entry->identifier, "%s", identifier);
-  GNUNET_CONTAINER_DLL_insert_tail (handle->ego_head,
-                                    handle->ego_tail,
-                                    ego_entry);
 
 }
 
@@ -1345,12 +1288,38 @@ init_egos (void *cls,
  * @param proc_cls closure for callback function
  * @return GNUNET_OK if request accepted
  */
-static void
+static enum GNUNET_GenericReturnValue
 rest_process_request (struct GNUNET_REST_RequestHandle *rest_handle,
                       GNUNET_REST_ResultProcessor proc,
                       void *proc_cls)
 {
   struct RequestHandle *handle = GNUNET_new (struct RequestHandle);
+  struct GNUNET_REST_RequestHandlerError err;
+  static const struct GNUNET_REST_RequestHandler handlers[] =
+  { { MHD_HTTP_METHOD_GET, GNUNET_REST_API_NS_IDENTITY_PUBKEY,
+      &ego_get_pubkey },
+    { MHD_HTTP_METHOD_GET, GNUNET_REST_API_NS_IDENTITY_NAME, &ego_get_name },
+    { MHD_HTTP_METHOD_GET,
+      GNUNET_REST_API_NS_IDENTITY_SUBSYSTEM,
+      &ego_get_subsystem },
+    { MHD_HTTP_METHOD_GET, GNUNET_REST_API_NS_IDENTITY, &ego_get_all },
+    { MHD_HTTP_METHOD_PUT,
+      GNUNET_REST_API_NS_IDENTITY_PUBKEY,
+      &ego_edit_pubkey },
+    { MHD_HTTP_METHOD_PUT, GNUNET_REST_API_NS_IDENTITY_NAME, &ego_edit_name },
+    { MHD_HTTP_METHOD_PUT,
+      GNUNET_REST_API_NS_IDENTITY_SUBSYSTEM,
+      &ego_edit_subsystem },
+    { MHD_HTTP_METHOD_POST, GNUNET_REST_API_NS_IDENTITY, &ego_create },
+    { MHD_HTTP_METHOD_DELETE,
+      GNUNET_REST_API_NS_IDENTITY_PUBKEY,
+      &ego_delete_pubkey },
+    { MHD_HTTP_METHOD_DELETE,
+      GNUNET_REST_API_NS_IDENTITY_NAME,
+      &ego_delete_name },
+    { MHD_HTTP_METHOD_OPTIONS, GNUNET_REST_API_NS_IDENTITY, &options_cont },
+    GNUNET_REST_HANDLER_END };
+
 
   handle->response_code = 0;
   handle->timeout = GNUNET_TIME_UNIT_FOREVER_REL;
@@ -1363,14 +1332,21 @@ rest_process_request (struct GNUNET_REST_RequestHandle *rest_handle,
   handle->url = GNUNET_strdup (rest_handle->url);
   if (handle->url[strlen (handle->url) - 1] == '/')
     handle->url[strlen (handle->url) - 1] = '\0';
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Connecting...\n");
-
-  handle->identity_handle = GNUNET_IDENTITY_connect (cfg, &init_egos, handle);
-
   handle->timeout_task =
     GNUNET_SCHEDULER_add_delayed (handle->timeout, &do_error, handle);
+  GNUNET_CONTAINER_DLL_insert (requests_head,
+                               requests_tail,
+                               handle);
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Connecting...\n");
+  if (GNUNET_NO ==
+      GNUNET_REST_handle_request (handle->rest_handle, handlers, &err, handle))
+  {
+    cleanup_handle (handle);
+    return GNUNET_NO;
+  }
 
   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Connected\n");
+  return GNUNET_YES;
 }
 
 
@@ -1402,6 +1378,8 @@ libgnunet_plugin_rest_identity_init (void *cls)
                    MHD_HTTP_METHOD_PUT,
                    MHD_HTTP_METHOD_DELETE,
                    MHD_HTTP_METHOD_OPTIONS);
+  state = ID_REST_STATE_INIT;
+  identity_handle = GNUNET_IDENTITY_connect (cfg, &list_ego, NULL);
 
   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, _ ("Identity REST API initialized\n"));
   return api;
@@ -1419,8 +1397,23 @@ libgnunet_plugin_rest_identity_done (void *cls)
 {
   struct GNUNET_REST_Plugin *api = cls;
   struct Plugin *plugin = api->cls;
+  struct EgoEntry *ego_entry;
+  struct EgoEntry *ego_tmp;
 
   plugin->cfg = NULL;
+  while (NULL != requests_head)
+    cleanup_handle (requests_head);
+  if (NULL != identity_handle)
+    GNUNET_IDENTITY_disconnect (identity_handle);
+
+  for (ego_entry = ego_head; NULL != ego_entry;)
+  {
+    ego_tmp = ego_entry;
+    ego_entry = ego_entry->next;
+    GNUNET_free (ego_tmp->identifier);
+    GNUNET_free (ego_tmp->keystring);
+    GNUNET_free (ego_tmp);
+  }
 
   GNUNET_free (allow_methods);
   GNUNET_free (api);
diff --git a/src/identity/test_plugin_rest_identity.sh b/src/identity/test_plugin_rest_identity.sh
new file mode 100755
index 0000000000000000000000000000000000000000..a5879dd7ec474d3535c64dcb89fe97ba07028ea2
--- /dev/null
+++ b/src/identity/test_plugin_rest_identity.sh
@@ -0,0 +1,157 @@
+#!/usr/bin/bash
+
+#First, start gnunet-arm and the rest-service.
+#Exit 0 means success, exit 1 means failed test
+
+identity_link="http://localhost:7776/identity"
+wrong_link="http://localhost:7776/identityandmore"
+
+
+curl_get () {
+    #$1 is link
+    #$2 is grep
+    cache="$(curl -v "$1" 2>&1 | grep "$2")"
+    #echo $cache
+    if [ "" == "$cache" ]
+    then
+        exit 1
+    fi
+}
+
+curl_post () {
+    #$1 is link
+    #$2 is data
+    #$3 is grep
+    cache="$(curl -v -X "POST" "$1" --data "$2" 2>&1 | grep "$3")"
+    #echo $cache
+    if [ "" == "$cache" ]
+    then
+        exit 1
+    fi
+}
+
+curl_delete () {
+    #$1 is link
+    #$2 is grep
+    cache="$(curl -v -X "DELETE" "$1" 2>&1 | grep "$2")"
+    #echo $cache
+    if [ "" == "$cache" ]
+    then
+        exit 1
+    fi
+}
+
+curl_put () {
+    #$1 is link
+    #$2 is data
+    #$3 is grep
+    cache="$(curl -v -X "PUT" "$1" --data "$2" 2>&1 | grep "$3")"
+    #echo $cache
+    if [ "" == "$cache" ]
+    then
+        exit 1
+    fi
+}
+
+#Test GET
+test="$(gnunet-identity -d)"
+#if no identity exists
+if [ "" == "$test" ]
+then
+    curl_get "$identity_link/all" "error"
+    gnunet-identity -C "test_plugin_rest_identity"
+    name="$(gnunet-identity -d | awk 'NR==1{print $1}')"
+    public="$(gnunet-identity -d | awk 'NR==1{print $3}')"
+    
+    curl_get "${identity_link}/name/$name" "$public"
+    curl_get "${identity_link}/name/$public" "error"
+    curl_get "${identity_link}/name/" "error"
+    
+    curl_get "${identity_link}/pubkey/$public" "$name"
+    curl_get "${identity_link}/pubkey/$name" "error"
+    curl_get "${identity_link}/pubkey/" "error"
+    
+    gnunet-identity -D "test_plugin_rest_identity"
+else
+    name="$(gnunet-identity -d | awk 'NR==1{print $1}')"
+    public="$(gnunet-identity -d | awk 'NR==1{print $3}')"
+    
+    curl_get "${identity_link}/name/$name" "$public"
+    curl_get "${identity_link}/name/$public" "error"
+    curl_get "${identity_link}/name/" "error"
+    
+    curl_get "${identity_link}/pubkey/$public" "$name"
+    curl_get "${identity_link}/pubkey/$name" "error"
+    curl_get "${identity_link}/pubkey/" "error"
+fi
+
+#Test POST
+gnunet-identity -D "test_plugin_rest_identity" > /dev/null 2>&1
+gnunet-identity -D "test_plugin_rest_identity1" > /dev/null 2>&1
+
+curl_post "${identity_link}" '{"name":"test_plugin_rest_identity"}' "HTTP/1.1 201 Created"
+curl_post "${identity_link}" '{"name":"test_plugin_rest_identity"}' "HTTP/1.1 409"
+curl_post "${identity_link}" '{"name":"Test_plugin_rest_identity"}' "HTTP/1.1 409"
+curl_post "${identity_link}" '{}' "error"
+curl_post "${identity_link}" '' "error"
+curl_post "${identity_link}" '{"name":""}' "error"
+curl_post "${identity_link}" '{"name":123}' "error"
+curl_post "${identity_link}" '{"name":[]}' "error"
+curl_post "${identity_link}" '{"name1":"test_plugin_rest_identity"}' "error"
+curl_post "${identity_link}" '{"other":""}' "error"
+curl_post "${identity_link}" '{"name":"test_plugin_rest_identity1", "other":"test_plugin_rest_identity2"}' "error"
+
+#Test PUT
+name="$(gnunet-identity -d | grep "test_plugin_rest_identity" | awk 'NR==1{print $1}')"
+public="$(gnunet-identity -d | grep "test_plugin_rest_identity" | awk 'NR==1{print $3}')"
+
+curl_put "${identity_link}/pubkey/$public" '{"newname":"test_plugin_rest_identity1"}' "HTTP/1.1 204"
+curl_put "${identity_link}/pubkey/$public" '{"newname":"test_plugin_rest_identity1"}' "HTTP/1.1 409"
+curl_put "${identity_link}/pubkey/${public}xx" '{"newname":"test_plugin_rest_identity1"}' "HTTP/1.1 404"
+curl_put "${identity_link}/pubkey/" '{"newname":"test_plugin_rest_identity1"}' "HTTP/1.1 404"
+curl_put "${identity_link}/pubke" '{"newname":"test_plugin_rest_identity1"}' "error"
+curl_put "${identity_link}" '{"newname":"test_plugin_rest_identity1","other":"sdfdsf"}' "error"
+curl_put "${identity_link}/pubkey/$name" '{"newname":"test_plugin_rest_identity1"}' "HTTP/1.1 404"
+curl_put "${identity_link}/name/test_plugin_rest_identity1" '{"newname":"test_plugin_rest_identity"}' "HTTP/1.1 204"
+curl_put "${identity_link}/pubkey/$public" '{"newnam":"test_plugin_rest_identity"}' "error"
+curl_put "${identity_link}/name/test_plugin_rest_identity" '{"newname":"test_plugin_rest_identity1"}' "HTTP/1.1 204"
+curl_put "${identity_link}/name/test_plugin_rest_identity1" '{"newname":"TEST_plugin_rest_identity1"}' "HTTP/1.1 409"
+curl_put "${identity_link}/name/test_plugin_rest_identity1" '{"newname":"test_plugin_rest_identity1"}' "HTTP/1.1 409"
+curl_put "${identity_link}/name/test_plugin_rest_identityxxx" '{"newname":"test_plugin_rest_identity"}' "HTTP/1.1 404"
+curl_put "${identity_link}/name/test_plugin_rest_identity1" '{"newname":"test_plugin_rest_identity"}' "HTTP/1.1 204"
+curl_put "${identity_link}/name/test_plugin_rest_identity" '{"newnam":"test_plugin_rest_identityfail"}' "error"
+
+#Test subsystem
+curl_put "${identity_link}/subsystem/test_plugin_rest_identity" '{"subsystem":"namestore"}' "HTTP/1.1 204"
+curl_put "${identity_link}/subsystem/test_plugin_rest_identity" '{"subsystem":"namestore"}' "HTTP/1.1 204"
+curl_get "${identity_link}/subsystem/namestore" "test_plugin_rest_identity"
+public="$(gnunet-identity -d | grep "test_plugin_rest_identity" | awk 'NR==1{print $3}')"
+curl_put "${identity_link}/subsystem/$public" '{"subsystem":"namestore"}' "HTTP/1.1 404"
+curl_post "${identity_link}" '{"name":"test_plugin_rest_identity1"}' "HTTP/1.1 201 Created"
+curl_get "${identity_link}/subsystem/test_plugin_rest_identity_no_subsystem" "error"
+curl_put "${identity_link}/subsystem/test_plugin_rest_identity1" '{"subsystem":"test_plugin_rest_identity_no_subsystem"}' "HTTP/1.1 204"
+curl_get "${identity_link}/subsystem/test_plugin_rest_identity_no_subsystem" "test_plugin_rest_identity1"
+
+curl_put "${identity_link}/subsystem/test_plugin_rest_identity1" '{"subsyste":"test_plugin_rest_identity_no_subsystem"}' "error"
+curl_put "${identity_link}/subsystem/test_plugin_rest_identity1" '{"subsystem":"test_plugin_rest_identity_no_subsystem"}' "HTTP/1.1 204"
+
+#Test DELETE
+curl_delete "${identity_link}/name/test_plugin_rest_identity" "HTTP/1.1 204"
+curl_get "${identity_link}/name/test_plugin_rest_identity" "error"
+curl_delete "${identity_link}/name/TEST_plugin_rest_identity1" "HTTP/1.1 204"
+curl_delete "${identity_link}/name/test_plugin_rest_identity1" "HTTP/1.1 404"
+curl_get "${identity_link}/name/test_plugin_rest_identity1" "error"
+curl_delete "${identity_link}/name/test_plugin_rest_identity_not_found" "HTTP/1.1 404"
+curl_post "${identity_link}" '{"name":"test_plugin_rest_identity1"}' "HTTP/1.1 201 Created"
+public="$(gnunet-identity -d | grep "test_plugin_rest_identity1" | awk 'NR==1{print $3}')"
+curl_delete "${identity_link}/pubkey/$public" "HTTP/1.1 204"
+curl_delete "${identity_link}/pubke/$public" "error"
+curl_delete "${identity_link}/pubkey/${public}other=232" "HTTP/1.1 404"
+
+#Test wrong_link
+curl_get "$wrong_link" "HTTP/1.1 404"
+curl_post "$wrong_link" '{"name":"test_plugin_rest_identity"}' "HTTP/1.1 404"
+curl_put "$wrong_link/name/test_plugin_rest_identity" '{"newname":"test_plugin_rest_identity1"}' "HTTP/1.1 404"
+curl_delete "$wrong_link/name/test_plugin_rest_identity1" "HTTP/1.1 404"
+
+exit 0;
diff --git a/src/include/Makefile.am b/src/include/Makefile.am
index d2c254ae6fc689688d045991ac889ce6b3298fd6..202abb7accbdc8a46ff2b23271faf167544e616f 100644
--- a/src/include/Makefile.am
+++ b/src/include/Makefile.am
@@ -99,6 +99,8 @@ gnunetinclude_HEADERS = \
   gnunet_secretsharing_service.h \
   gnunet_service_lib.h \
   gnunet_set_service.h \
+  gnunet_seti_service.h \
+  gnunet_setu_service.h \
   gnunet_signal_lib.h \
   gnunet_signatures.h \
   gnunet_socks.h \
@@ -119,5 +121,6 @@ gnunetinclude_HEADERS = \
   gnunet_transport_monitor_service.h \
   gnunet_transport_plugin.h \
   gnunet_tun_lib.h \
+  gnunet_uri_lib.h \
   gnunet_util_lib.h \
   gnunet_vpn_service.h
diff --git a/src/include/gnunet_bio_lib.h b/src/include/gnunet_bio_lib.h
index 687334c1c4a2f9e8ea834115627d74652b84ff15..e49ce1354668499665fc43d7cb194c3495076888 100644
--- a/src/include/gnunet_bio_lib.h
+++ b/src/include/gnunet_bio_lib.h
@@ -138,9 +138,9 @@ GNUNET_BIO_read_meta_data (struct GNUNET_BIO_ReadHandle *h,
  * @param f address of float to read
  */
 int
-GNUNET_BIO_read_float(struct GNUNET_BIO_ReadHandle *h,
-                      const char *what,
-                      float *f);
+GNUNET_BIO_read_float (struct GNUNET_BIO_ReadHandle *h,
+                       const char *what,
+                       float *f);
 
 
 /**
@@ -151,10 +151,9 @@ GNUNET_BIO_read_float(struct GNUNET_BIO_ReadHandle *h,
  * @param f address of double to read
  */
 int
-GNUNET_BIO_read_double(struct GNUNET_BIO_ReadHandle *h,
-                       const char *what,
-                       double *f);
-
+GNUNET_BIO_read_double (struct GNUNET_BIO_ReadHandle *h,
+                        const char *what,
+                        double *f);
 
 
 /**
@@ -171,7 +170,6 @@ GNUNET_BIO_read_int32 (struct GNUNET_BIO_ReadHandle *h,
                        int32_t *i);
 
 
-
 /**
  * Read an (u)int64_t.
  *
@@ -186,7 +184,6 @@ GNUNET_BIO_read_int64 (struct GNUNET_BIO_ReadHandle *h,
                        int64_t *i);
 
 
-
 /****************************** WRITING API *******************************/
 
 /**
@@ -310,9 +307,9 @@ GNUNET_BIO_write_meta_data (struct GNUNET_BIO_WriteHandle *h,
  * @param f float to write (must be a variable)
  */
 int
-GNUNET_BIO_write_float(struct GNUNET_BIO_WriteHandle *h,
-                       const char *what,
-                       float f);
+GNUNET_BIO_write_float (struct GNUNET_BIO_WriteHandle *h,
+                        const char *what,
+                        float f);
 
 /**
  * Write a double.
@@ -322,9 +319,9 @@ GNUNET_BIO_write_float(struct GNUNET_BIO_WriteHandle *h,
  * @param f double to write (must be a variable)
  */
 int
-GNUNET_BIO_write_double(struct GNUNET_BIO_WriteHandle *h,
-                        const char *what,
-                        double f);
+GNUNET_BIO_write_double (struct GNUNET_BIO_WriteHandle *h,
+                         const char *what,
+                         double f);
 
 
 /**
@@ -490,7 +487,7 @@ GNUNET_BIO_read_spec_int64 (const char *what,
  * @param f address of float to read
  */
 struct GNUNET_BIO_ReadSpec
-GNUNET_BIO_read_spec_float(const char *what, float *f);
+GNUNET_BIO_read_spec_float (const char *what, float *f);
 
 
 /**
@@ -500,7 +497,7 @@ GNUNET_BIO_read_spec_float(const char *what, float *f);
  * @param f address of double to read
  */
 struct GNUNET_BIO_ReadSpec
-GNUNET_BIO_read_spec_double(const char *what, double *f);
+GNUNET_BIO_read_spec_double (const char *what, double *f);
 
 
 /**
@@ -647,7 +644,7 @@ GNUNET_BIO_write_spec_int64 (const char *what,
  * @return the write spec
  */
 struct GNUNET_BIO_WriteSpec
-GNUNET_BIO_write_spec_float(const char *what, float *f);
+GNUNET_BIO_write_spec_float (const char *what, float *f);
 
 
 /**
@@ -658,7 +655,7 @@ GNUNET_BIO_write_spec_float(const char *what, float *f);
  * @return the write spec
  */
 struct GNUNET_BIO_WriteSpec
-GNUNET_BIO_write_spec_double(const char *what, double *f);
+GNUNET_BIO_write_spec_double (const char *what, double *f);
 
 
 /**
diff --git a/src/include/gnunet_block_lib.h b/src/include/gnunet_block_lib.h
index 18ca6f63fd8a1fd4edebb0d7daf323426e0229a8..73b51252ea069f0672356f70356b359b701c64e1 100644
--- a/src/include/gnunet_block_lib.h
+++ b/src/include/gnunet_block_lib.h
@@ -137,6 +137,19 @@ enum GNUNET_BLOCK_Type
    * Contains either special marker elements or a nested block.
    */
   GNUNET_BLOCK_TYPE_CONSENSUS_ELEMENT = 25,
+
+  /**
+   * Block for testing set intersection.  If first byte of the block
+   * is non-zero, the block is considered invalid.
+   */
+  GNUNET_BLOCK_TYPE_SETI_TEST = 24,
+
+  /**
+   * Block for testing set union.  If first byte of the block
+   * is non-zero, the block is considered invalid.
+   */
+  GNUNET_BLOCK_TYPE_SETU_TEST = 24,
+
 };
 
 
diff --git a/src/include/gnunet_buffer_lib.h b/src/include/gnunet_buffer_lib.h
index e23536ab2ca9e6b3327090b1ac0e3dd109fd97a7..0c566df752de3329bee4f6433c067cbcd86361cd 100644
--- a/src/include/gnunet_buffer_lib.h
+++ b/src/include/gnunet_buffer_lib.h
@@ -109,6 +109,21 @@ void
 GNUNET_buffer_write_str (struct GNUNET_Buffer *buf, const char *str);
 
 
+/**
+ * Write data encoded via #GNUNET_STRINGS_data_to_string to the buffer.
+ *
+ * Grows the buffer if necessary.
+ *
+ * @param buf buffer to write to
+ * @param data data to read from
+ * @param data_len number of bytes to copy from @a data to @a buf
+ */
+void
+GNUNET_buffer_write_data_encoded (struct GNUNET_Buffer *buf,
+                                  const void *data,
+                                  size_t data_len);
+
+
 /**
  * Write a path component to a buffer, ensuring that
  * there is exactly one slash between the previous contents
@@ -147,7 +162,7 @@ GNUNET_buffer_write_fstr (struct GNUNET_Buffer *buf, const char *fmt, ...);
  */
 void
 GNUNET_buffer_write_vfstr (struct GNUNET_Buffer *buf, const char *fmt, va_list
-                          args);
+                           args);
 
 
 /**
diff --git a/src/include/gnunet_common.h b/src/include/gnunet_common.h
index b2f99cd55329abaf6f131843255f2d4bd6ff29a9..fcaae1026fe35738767dba344dec59dd810cdd19 100644
--- a/src/include/gnunet_common.h
+++ b/src/include/gnunet_common.h
@@ -1173,9 +1173,9 @@ GNUNET_memcmp_ct_ (const void *b1,
  * @param a pointer to @a n bytes which should be tested for the
  *          entire memory being zero'ed out.
  * @param n number of bytes in @a to be tested
- * @return 0 if a is zero, non-zero otherwise
+ * @return GNUNET_YES if a is zero, GNUNET_NO otherwise
  */
-int
+enum GNUNET_GenericReturnValue
 GNUNET_is_zero_ (const void *a,
                  size_t n);
 
@@ -1185,7 +1185,7 @@ GNUNET_is_zero_ (const void *a,
  *
  * @param a pointer to a struct which should be tested for the
  *          entire memory being zero'ed out.
- * @return 0 if a is zero, non-zero otherwise
+ * @return GNUNET_YES if a is zero, GNUNET_NO otherwise
  */
 #define GNUNET_is_zero(a)           \
   GNUNET_is_zero_ (a, sizeof (*a))
diff --git a/src/include/gnunet_configuration_lib.h b/src/include/gnunet_configuration_lib.h
index 302429430c38ec037518c9d43b312d656127fcf5..f782509eb5e33bce6df0b5037fc5f41934bdd6a0 100644
--- a/src/include/gnunet_configuration_lib.h
+++ b/src/include/gnunet_configuration_lib.h
@@ -100,6 +100,18 @@ GNUNET_CONFIGURATION_load_from (struct GNUNET_CONFIGURATION_Handle *cfg,
                                 const char *defaults_d);
 
 
+/**
+ * Return GNUnet's default configuration.  A new configuration is allocated
+ * each time and it's up to the caller to destroy it when done.  This function
+ * returns GNUnet's configuration even when #GNUNET_OS_init has been called
+ * with a value different from #GNUNET_OS_project_data_default.
+ *
+ * @return a freshly allocated configuration
+ */
+struct GNUNET_CONFIGURATION_Handle *
+GNUNET_CONFIGURATION_default (void);
+
+
 /**
  * Parse a configuration file, add all of the options in the
  * file to the configuration environment.
diff --git a/src/include/gnunet_constants.h b/src/include/gnunet_constants.h
index c83bec683b737a22080cde6035a3ca50ddb18ddb..8b3cbc7e60862afd093928af690e3849cd2d62d2 100644
--- a/src/include/gnunet_constants.h
+++ b/src/include/gnunet_constants.h
@@ -47,7 +47,8 @@ extern "C"
  * so that at least one maximum-size message can be send roughly once
  * per minute.
  */
-#define GNUNET_CONSTANTS_DEFAULT_BW_IN_OUT GNUNET_BANDWIDTH_value_init (1024*1024)
+#define GNUNET_CONSTANTS_DEFAULT_BW_IN_OUT GNUNET_BANDWIDTH_value_init (1024 \
+                                                                        * 1024)
 
 /**
  * After how long do we consider a connection to a peer dead
diff --git a/src/include/gnunet_container_lib.h b/src/include/gnunet_container_lib.h
index f3325a06450681d82dae5350b44450020dcf63f7..8d8cbf4c194c9952bfa97d183c256261773edd89 100644
--- a/src/include/gnunet_container_lib.h
+++ b/src/include/gnunet_container_lib.h
@@ -2158,9 +2158,9 @@ GNUNET_CONTAINER_multihashmap32_iterator_destroy (
     (element)->next = (head);                                           \
     (element)->prev = NULL;                                             \
     if ((tail) == NULL)                                                 \
-      (tail) = element;                                                 \
+    (tail) = element;                                                 \
     else                                                                \
-      (head)->prev = element;                                           \
+    (head)->prev = element;                                           \
     (head) = (element);                                                 \
   } while (0)
 
@@ -2182,9 +2182,9 @@ GNUNET_CONTAINER_multihashmap32_iterator_destroy (
     (element)->prev = (tail);                                           \
     (element)->next = NULL;                                             \
     if ((head) == NULL)                                                 \
-      (head) = element;                                                 \
+    (head) = element;                                                 \
     else                                                                \
-      (tail)->next = element;                                           \
+    (tail)->next = element;                                           \
     (tail) = (element);                                                 \
   } while (0)
 
@@ -2216,9 +2216,9 @@ GNUNET_CONTAINER_multihashmap32_iterator_destroy (
       (other)->next = (element);                                        \
     }                                                                   \
     if (NULL == (element)->next)                                        \
-      (tail) = (element);                                               \
+    (tail) = (element);                                               \
     else                                                                \
-      (element)->next->prev = (element);                                \
+    (element)->next->prev = (element);                                \
   } while (0)
 
 
@@ -2249,9 +2249,9 @@ GNUNET_CONTAINER_multihashmap32_iterator_destroy (
       (other)->prev = (element);                                        \
     }                                                                   \
     if (NULL == (element)->prev)                                        \
-      (head) = (element);                                               \
+    (head) = (element);                                               \
     else                                                                \
-      (element)->prev->next = (element);                                \
+    (element)->prev->next = (element);                                \
   } while (0)
 
 
@@ -2275,13 +2275,13 @@ GNUNET_CONTAINER_multihashmap32_iterator_destroy (
     GNUNET_assert (((element)->prev != NULL) || ((head) == (element))); \
     GNUNET_assert (((element)->next != NULL) || ((tail) == (element))); \
     if ((element)->prev == NULL)                                        \
-      (head) = (element)->next;                                         \
+    (head) = (element)->next;                                         \
     else                                                                \
-      (element)->prev->next = (element)->next;                          \
+    (element)->prev->next = (element)->next;                          \
     if ((element)->next == NULL)                                        \
-      (tail) = (element)->prev;                                         \
+    (tail) = (element)->prev;                                         \
     else                                                                \
-      (element)->next->prev = (element)->prev;                          \
+    (element)->next->prev = (element)->prev;                          \
     (element)->next = NULL;                                             \
     (element)->prev = NULL;                                             \
   } while (0)
@@ -2308,9 +2308,9 @@ GNUNET_CONTAINER_multihashmap32_iterator_destroy (
     (element)->next_ ## mdll = (head);                                           \
     (element)->prev_ ## mdll = NULL;                                             \
     if ((tail) == NULL)                                                        \
-      (tail) = element;                                                        \
+    (tail) = element;                                                        \
     else                                                                       \
-      (head)->prev_ ## mdll = element;                                           \
+    (head)->prev_ ## mdll = element;                                           \
     (head) = (element);                                                        \
   } while (0)
 
@@ -2333,9 +2333,9 @@ GNUNET_CONTAINER_multihashmap32_iterator_destroy (
     (element)->prev_ ## mdll = (tail);                                           \
     (element)->next_ ## mdll = NULL;                                             \
     if ((head) == NULL)                                                        \
-      (head) = element;                                                        \
+    (head) = element;                                                        \
     else                                                                       \
-      (tail)->next_ ## mdll = element;                                           \
+    (tail)->next_ ## mdll = element;                                           \
     (tail) = (element);                                                        \
   } while (0)
 
@@ -2368,9 +2368,9 @@ GNUNET_CONTAINER_multihashmap32_iterator_destroy (
       (other)->next_ ## mdll = (element);                                        \
     }                                                                          \
     if (NULL == (element)->next_ ## mdll)                                        \
-      (tail) = (element);                                                      \
+    (tail) = (element);                                                      \
     else                                                                       \
-      (element)->next_ ## mdll->prev_ ## mdll = (element);                         \
+    (element)->next_ ## mdll->prev_ ## mdll = (element);                         \
   } while (0)
 
 
@@ -2402,9 +2402,9 @@ GNUNET_CONTAINER_multihashmap32_iterator_destroy (
       (other)->prev_ ## mdll = (element);                                        \
     }                                                                          \
     if (NULL == (element)->prev_ ## mdll)                                        \
-      (head) = (element);                                                      \
+    (head) = (element);                                                      \
     else                                                                       \
-      (element)->prev_ ## mdll->next_ ## mdll = (element);                         \
+    (element)->prev_ ## mdll->next_ ## mdll = (element);                         \
   } while (0)
 
 
@@ -2425,13 +2425,13 @@ GNUNET_CONTAINER_multihashmap32_iterator_destroy (
     GNUNET_assert (((element)->prev_ ## mdll != NULL) || ((head) == (element))); \
     GNUNET_assert (((element)->next_ ## mdll != NULL) || ((tail) == (element))); \
     if ((element)->prev_ ## mdll == NULL)                                        \
-      (head) = (element)->next_ ## mdll;                                         \
+    (head) = (element)->next_ ## mdll;                                         \
     else                                                                       \
-      (element)->prev_ ## mdll->next_ ## mdll = (element)->next_ ## mdll;            \
+    (element)->prev_ ## mdll->next_ ## mdll = (element)->next_ ## mdll;            \
     if ((element)->next_ ## mdll == NULL)                                        \
-      (tail) = (element)->prev_ ## mdll;                                         \
+    (tail) = (element)->prev_ ## mdll;                                         \
     else                                                                       \
-      (element)->next_ ## mdll->prev_ ## mdll = (element)->prev_ ## mdll;            \
+    (element)->next_ ## mdll->prev_ ## mdll = (element)->prev_ ## mdll;            \
     (element)->next_ ## mdll = NULL;                                             \
     (element)->prev_ ## mdll = NULL;                                             \
   } while (0)
@@ -2468,8 +2468,8 @@ GNUNET_CONTAINER_multihashmap32_iterator_destroy (
       TYPE *pos;                                                            \
                                                                             \
       for (pos = head; NULL != pos; pos = pos->next)                        \
-        if (0 < comparator (comparator_cls, element, pos))                  \
-          break; /* element < pos */                                        \
+      if (0 < comparator (comparator_cls, element, pos))                  \
+      break;     /* element < pos */                                        \
       if (NULL == pos)     /* => element > tail */                              \
       {                                                                     \
         GNUNET_CONTAINER_DLL_insert_tail (head, tail, element);             \
diff --git a/src/include/gnunet_core_service.h b/src/include/gnunet_core_service.h
index 66b292c3cbc0fe3794194380abff85f37d6dd390..60bc3c2a6257d606f07c888f5fceda01c4977040 100644
--- a/src/include/gnunet_core_service.h
+++ b/src/include/gnunet_core_service.h
@@ -48,6 +48,122 @@ extern "C" {
  */
 #define GNUNET_CORE_VERSION 0x00000001
 
+GNUNET_NETWORK_STRUCT_BEGIN
+
+/**
+ * Message transmitted with the signed ephemeral key of a peer.  The
+ * session key is then derived from the two ephemeral keys (ECDHE).
+ */
+struct EphemeralKeyMessage
+{
+  /**
+   * Message type is #GNUNET_MESSAGE_TYPE_CORE_EPHEMERAL_KEY.
+   */
+  struct GNUNET_MessageHeader header;
+
+  /**
+   * Status of the sender (should be in `enum PeerStateMachine`), nbo.
+   */
+  int32_t sender_status GNUNET_PACKED;
+
+  /**
+   * An ECC signature of the @e origin_identity asserting the validity
+   * of the given ephemeral key.
+   */
+  struct GNUNET_CRYPTO_EddsaSignature signature;
+
+  /**
+   * Information about what is being signed.
+   */
+  struct GNUNET_CRYPTO_EccSignaturePurpose purpose;
+
+  /**
+   * At what time was this key created (beginning of validity).
+   */
+  struct GNUNET_TIME_AbsoluteNBO creation_time;
+
+  /**
+   * When does the given ephemeral key expire (end of validity).
+   */
+  struct GNUNET_TIME_AbsoluteNBO expiration_time;
+
+  /**
+   * Ephemeral public ECC key.
+   */
+  struct GNUNET_CRYPTO_EcdhePublicKey ephemeral_key;
+
+  /**
+   * Public key of the signing peer (persistent version, not the
+   * ephemeral public key).
+   */
+  struct GNUNET_PeerIdentity origin_identity;
+};
+
+
+/**
+ * We're sending an (encrypted) PING to the other peer to check if it
+ * can decrypt.  The other peer should respond with a PONG with the
+ * same content, except this time encrypted with the receiver's key.
+ */
+struct PingMessage
+{
+  /**
+   * Message type is #GNUNET_MESSAGE_TYPE_CORE_PING.
+   */
+  struct GNUNET_MessageHeader header;
+
+  /**
+   * Seed for the IV
+   */
+  uint32_t iv_seed GNUNET_PACKED;
+
+  /**
+   * Intended target of the PING, used primarily to check
+   * that decryption actually worked.
+   */
+  struct GNUNET_PeerIdentity target;
+
+  /**
+   * Random number chosen to make replay harder.
+   */
+  uint32_t challenge GNUNET_PACKED;
+};
+
+
+/**
+ * Response to a PING.  Includes data from the original PING.
+ */
+struct PongMessage
+{
+  /**
+   * Message type is #GNUNET_MESSAGE_TYPE_CORE_PONG.
+   */
+  struct GNUNET_MessageHeader header;
+
+  /**
+   * Seed for the IV
+   */
+  uint32_t iv_seed GNUNET_PACKED;
+
+  /**
+   * Random number to make replay attacks harder.
+   */
+  uint32_t challenge GNUNET_PACKED;
+
+  /**
+   * Reserved, always zero.
+   */
+  uint32_t reserved;
+
+  /**
+   * Intended target of the PING, used primarily to check
+   * that decryption actually worked.
+   */
+  struct GNUNET_PeerIdentity target;
+};
+
+
+GNUNET_NETWORK_STRUCT_END
 
 /**
  * Opaque handle to the service.
diff --git a/src/include/gnunet_crypto_lib.h b/src/include/gnunet_crypto_lib.h
index 3207016430ee734a64adb8888023be6ed68db01c..03fb16a43a881025a8004fe3b80790f71887b1e2 100644
--- a/src/include/gnunet_crypto_lib.h
+++ b/src/include/gnunet_crypto_lib.h
@@ -50,6 +50,7 @@ extern "C" {
 #endif
 #endif
 
+#include <sodium.h>
 
 /**
  * The identity of the host (wraps the signing key of the peer).
@@ -289,6 +290,17 @@ struct GNUNET_CRYPTO_SymmetricSessionKey
   unsigned char twofish_key[GNUNET_CRYPTO_AES_KEY_LENGTH];
 };
 
+/**
+ * Type of a nonce used for challenges.
+ */
+struct ChallengeNonceP
+{
+  /**
+   * The value of the nonce.  Note that this is NOT a hash.
+   */
+  struct GNUNET_ShortHashCode value;
+};
+
 GNUNET_NETWORK_STRUCT_END
 
 /**
@@ -607,7 +619,7 @@ GNUNET_CRYPTO_hash_to_enc (const struct GNUNET_HashCode *block,
  * @param result where to store the hash code
  * @return #GNUNET_OK on success, #GNUNET_SYSERR if result has the wrong encoding
  */
-int
+enum GNUNET_GenericReturnValue
 GNUNET_CRYPTO_hash_from_string2 (const char *enc,
                                  size_t enclen,
                                  struct GNUNET_HashCode *result);
@@ -656,6 +668,15 @@ GNUNET_CRYPTO_hash (const void *block,
                     struct GNUNET_HashCode *ret);
 
 
+/**
+ * Value for a salt for #GNUNET_CRYPTO_pow_hash().
+ */
+struct GNUNET_CRYPTO_PowSalt
+{
+  char salt[crypto_pwhash_argon2id_SALTBYTES];
+};
+
+
 /**
  * Calculate the 'proof-of-work' hash (an expensive hash).
  *
@@ -665,7 +686,7 @@ GNUNET_CRYPTO_hash (const void *block,
  * @param result where to write the resulting hash
  */
 void
-GNUNET_CRYPTO_pow_hash (const char *salt,
+GNUNET_CRYPTO_pow_hash (const struct GNUNET_CRYPTO_PowSalt *salt,
                         const void *buf,
                         size_t buf_len,
                         struct GNUNET_HashCode *result);
@@ -1779,7 +1800,7 @@ GNUNET_CRYPTO_eddsa_verify_ (
  */
 #define GNUNET_CRYPTO_eddsa_verify(purp,ps,sig,pub) ({             \
     /* check size is set correctly */                              \
-    GNUNET_assert (htonl ((ps)->purpose.size) == sizeof (*(ps))); \
+    GNUNET_assert (ntohl ((ps)->purpose.size) == sizeof (*(ps))); \
     /* check 'ps' begins with the purpose */                       \
     GNUNET_static_assert (((void*) (ps)) ==                        \
                           ((void*) &(ps)->purpose));               \
diff --git a/src/include/gnunet_curl_lib.h b/src/include/gnunet_curl_lib.h
index 875cfa3bd2952cefd7aced0d4ecd57c8b6989c14..f291d6b14e99e7d91d09d1251764e7f7be17b108 100644
--- a/src/include/gnunet_curl_lib.h
+++ b/src/include/gnunet_curl_lib.h
@@ -225,13 +225,9 @@ typedef void
  * upon its completion. Note that the context will make use of the
  * CURLOPT_PRIVATE facility of the CURL @a eh.
  *
- * This function modifies the CURL handle to add the
- * "Content-Type: application/json" header if @a add_json is set.
- *
  * @param ctx context to execute the job in
  * @param eh curl easy handle for the request, will
  *           be executed AND cleaned up
- * @param add_json add "application/json" content type header
  * @param jcc callback to invoke upon completion
  * @param jcc_cls closure for @a jcc
  * @return NULL on error (in this case, @eh is still released!)
@@ -239,17 +235,73 @@ typedef void
 struct GNUNET_CURL_Job *
 GNUNET_CURL_job_add (struct GNUNET_CURL_Context *ctx,
                      CURL *eh,
-                     int add_json,
                      GNUNET_CURL_JobCompletionCallback jcc,
                      void *jcc_cls);
 
 
 /**
  * Schedule a CURL request to be executed and call the given @a jcc
- * upon its completion.  Note that the context will make use of the
+ * upon its completion. Note that the context will make use of the
  * CURLOPT_PRIVATE facility of the CURL @a eh.
  *
  * This function modifies the CURL handle to add the
+ * "Content-Type: application/json" header.
+ *
+ * @param ctx context to execute the job in
+ * @param eh curl easy handle for the request, will
+ *           be executed AND cleaned up
+ * @param jcc callback to invoke upon completion
+ * @param jcc_cls closure for @a jcc
+ * @return NULL on error (in this case, @eh is still released!)
+ */
+struct GNUNET_CURL_Job *
+GNUNET_CURL_job_add_with_ct_json (struct GNUNET_CURL_Context *ctx,
+                                  CURL *eh,
+                                  GNUNET_CURL_JobCompletionCallback jcc,
+                                  void *jcc_cls);
+
+
+/**
+ * Force use of the provided username and password
+ * for client authentication for all operations performed
+ * with @a ctx.
+ *
+ * @param ctx context to set authentication data for
+ * @param userpass string with "$USERNAME:$PASSWORD"
+ */
+void
+GNUNET_CURL_set_userpass (struct GNUNET_CURL_Context *ctx,
+                          const char *userpass);
+
+
+/**
+ * Force use of the provided TLS client certificate for client authentication
+ * for all operations performed with @a ctx.
+ *
+ * Note that if the provided information is incorrect,
+ * the earliest operation that could fail is
+ * #GNUNET_CURL_job_add() or #GNUNET_CURL_job_add2()!
+ *
+ * @param ctx context to set authentication data for
+ * @param certtype type of the certificate
+ * @param certfile file with the certificate
+ * @param keyfile file with the private key
+ * @param keypass passphrase to decrypt @a keyfile (or NULL)
+ */
+void
+GNUNET_CURL_set_tlscert (struct GNUNET_CURL_Context *ctx,
+                         const char *certtype,
+                         const char *certfile,
+                         const char *keyfile,
+                         const char *keypass);
+
+
+/**
+ * Schedule a CURL request to be executed and call the given @a jcc upon its
+ * completion.  Note that the context will make use of the CURLOPT_PRIVATE
+ * facility of the CURL @a eh.
+ *
+ * This function modifies the CURL handle to add the
  * "Content-Type: application/json" header if @a add_json is set.
  *
  * @param ctx context to execute the job in
@@ -291,6 +343,17 @@ GNUNET_CURL_job_add_raw (struct GNUNET_CURL_Context *ctx,
                          void *jcc_cls);
 
 
+/**
+ * Add @a extra_headers to the HTTP headers for @a job.
+ *
+ * @param[in,out] job the job to modify
+ * @param extra_headers headers to append
+ */
+void
+GNUNET_CURL_extend_headers (struct GNUNET_CURL_Job *job,
+                            const struct curl_slist *extra_headers);
+
+
 /**
  * Cancel a job.  Must only be called before the job completion
  * callback is called for the respective job.
diff --git a/src/include/gnunet_disk_lib.h b/src/include/gnunet_disk_lib.h
index f43cf8943508e9014bde68ba646aa2b7353bb03c..51ae7d8d5f6a571f882f0709226561d3165893f6 100644
--- a/src/include/gnunet_disk_lib.h
+++ b/src/include/gnunet_disk_lib.h
@@ -390,34 +390,55 @@ GNUNET_DISK_file_handle_size (struct GNUNET_DISK_FileHandle *fh,
                               off_t *size);
 
 
+/**
+ * Flags for #GNUNET_DISK_pipe().
+ */
+enum GNUNET_DISK_PipeFlags
+{
+
+  /**
+   * No special options, use non-blocking read/write operations.
+   */
+  GNUNET_DISK_PF_NONE,
+
+  /**
+   * Configure read end to block when reading if set.
+   */
+  GNUNET_DISK_PF_BLOCKING_READ = 1,
+  /**
+   * Configure write end to block when writing if set.
+   */
+  GNUNET_DISK_PF_BLOCKING_WRITE = 2,
+
+  /**
+   * Configure both pipe ends for blocking operations if set.
+   */
+  GNUNET_DISK_PF_BLOCKING_RW = GNUNET_DISK_PF_BLOCKING_READ
+                               | GNUNET_DISK_PF_BLOCKING_WRITE
+
+};
+
+
 /**
  * Creates an interprocess channel
  *
- * @param blocking_read creates an asynchronous pipe for reading if set to #GNUNET_NO
- * @param blocking_write creates an asynchronous pipe for writing if set to #GNUNET_NO
- * @param inherit_read 1 to make read handle inheritable, 0 otherwise (NT only)
- * @param inherit_write 1 to make write handle inheritable, 0 otherwise (NT only)
+ * @param pf how to configure the pipe
  * @return handle to the new pipe, NULL on error
  */
 struct GNUNET_DISK_PipeHandle *
-GNUNET_DISK_pipe (int blocking_read,
-                  int blocking_write,
-                  int inherit_read,
-                  int inherit_write);
+GNUNET_DISK_pipe (enum GNUNET_DISK_PipeFlags pf);
 
 
 /**
  * Creates a pipe object from a couple of file descriptors.
  * Useful for wrapping existing pipe FDs.
  *
- * @param blocking_read creates an asynchronous pipe for reading if set to #GNUNET_NO
- * @param blocking_write creates an asynchronous pipe for writing if set to #GNUNET_NO
+ * @param pf how to configure the pipe
  * @param fd an array of two fd values. One of them may be -1 for read-only or write-only pipes
  * @return handle to the new pipe, NULL on error
  */
 struct GNUNET_DISK_PipeHandle *
-GNUNET_DISK_pipe_from_fd (int blocking_read,
-                          int blocking_write,
+GNUNET_DISK_pipe_from_fd (enum GNUNET_DISK_PipeFlags pf,
                           int fd[2]);
 
 
@@ -479,6 +500,7 @@ const struct GNUNET_DISK_FileHandle *
 GNUNET_DISK_pipe_handle (const struct GNUNET_DISK_PipeHandle *p,
                          enum GNUNET_DISK_PipeEnd n);
 
+
 /**
  * Update POSIX permissions mask of a file on disk.  If both argumets
  * are #GNUNET_NO, the file is made world-read-write-executable (777).
diff --git a/src/include/gnunet_gnsrecord_lib.h b/src/include/gnunet_gnsrecord_lib.h
index c976c89c51b63c7920e25eccb0a4f42576557d8e..960203fb155435474a4bb2ba1e0335739b650c38 100644
--- a/src/include/gnunet_gnsrecord_lib.h
+++ b/src/include/gnunet_gnsrecord_lib.h
@@ -143,12 +143,13 @@ extern "C" {
 /**
  * Record type for an attribute attestation
  */
-#define GNUNET_GNSRECORD_TYPE_RECLAIM_ATTESTATION 65554
+#define GNUNET_GNSRECORD_TYPE_RECLAIM_CREDENTIAL 65554
 
 /**
- * Record type for an attestation reference in a ticket
+ * Record type for a presentation of a credential (used
+ * in a ticket record set)
  */
-#define GNUNET_GNSRECORD_TYPE_RECLAIM_ATTESTATION_REF 65555
+#define GNUNET_GNSRECORD_TYPE_RECLAIM_PRESENTATION 65555
 
 
 /**
diff --git a/src/include/gnunet_identity_service.h b/src/include/gnunet_identity_service.h
index f4e6535982e5e6638955c7be00156346ffa28fac..94127248e5dd76e84b4406e15d50a4d8fa34611a 100644
--- a/src/include/gnunet_identity_service.h
+++ b/src/include/gnunet_identity_service.h
@@ -86,9 +86,9 @@ GNUNET_IDENTITY_ego_get_private_key (const struct GNUNET_IDENTITY_Ego *ego);
 /**
  * Obtain the ego representing 'anonymous' users.
  *
- * @return handle for the anonymous user, must not be freed
+ * @return handle for the anonymous user, MUST NOT be freed
  */
-const struct GNUNET_IDENTITY_Ego *
+struct GNUNET_IDENTITY_Ego *
 GNUNET_IDENTITY_ego_get_anonymous (void);
 
 
diff --git a/src/include/gnunet_json_lib.h b/src/include/gnunet_json_lib.h
index 95d136239a3a32f5238bf9401728d2e46153242a..07a14d32916b09ad27f5224d648cae00731ba327 100644
--- a/src/include/gnunet_json_lib.h
+++ b/src/include/gnunet_json_lib.h
@@ -127,7 +127,7 @@ struct GNUNET_JSON_Specification
  * @param[out] which index into @a spec did we encounter an error
  * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
  */
-int
+enum GNUNET_GenericReturnValue
 GNUNET_JSON_parse (const json_t *root,
                    struct GNUNET_JSON_Specification *spec,
                    const char **error_json_name,
diff --git a/src/include/gnunet_mq_lib.h b/src/include/gnunet_mq_lib.h
index 520027dbb9d003a5d0a78488432698b1bc8e1dad..37f21e5b1f34adfd63945e13030c10736a3c57d1 100644
--- a/src/include/gnunet_mq_lib.h
+++ b/src/include/gnunet_mq_lib.h
@@ -547,7 +547,7 @@ struct GNUNET_MQ_MessageHandler
  */
 #define GNUNET_MQ_hd_fixed_size(name, code, str, ctx)                   \
   ({                                                                    \
-    void (*_cb)(void *cls, const str * msg) = &handle_ ## name;           \
+    void (*_cb)(void *cls, const str *msg) = &handle_ ## name;           \
     ((struct GNUNET_MQ_MessageHandler){ NULL,                            \
                                         (GNUNET_MQ_MessageCallback) _cb, \
                                         (ctx),                           \
@@ -598,8 +598,8 @@ struct GNUNET_MQ_MessageHandler
  */
 #define GNUNET_MQ_hd_var_size(name, code, str, ctx)                          \
   __extension__ ({                                                            \
-    int (*_mv)(void *cls, const str * msg) = &check_ ## name;                  \
-    void (*_cb)(void *cls, const str * msg) = &handle_ ## name;                \
+    int (*_mv)(void *cls, const str *msg) = &check_ ## name;                  \
+    void (*_cb)(void *cls, const str *msg) = &handle_ ## name;                \
     ((struct GNUNET_MQ_MessageHandler){ (GNUNET_MQ_MessageValidationCallback) \
                                         _mv,                                \
                                         (GNUNET_MQ_MessageCallback) _cb,      \
diff --git a/src/include/gnunet_my_lib.h b/src/include/gnunet_my_lib.h
index 74e7bf492364a26eb7546422162da1b1ccc95004..b8513ca84d7e3b86e2d267166753efd0da1432d7 100644
--- a/src/include/gnunet_my_lib.h
+++ b/src/include/gnunet_my_lib.h
@@ -245,7 +245,7 @@ struct GNUNET_MY_ResultSpec
   /**
    * Memory for MySQL to notify us about NULL values.
    */
-  my_bool is_null;
+  MYSQL_BOOL is_null;
 };
 
 
diff --git a/src/include/gnunet_mysql_lib.h b/src/include/gnunet_mysql_lib.h
index 964483024bceefc0352b192862ba0df12a12b27d..843d3ccb378bf1ee9634481cd5d76f8e1930c5c4 100644
--- a/src/include/gnunet_mysql_lib.h
+++ b/src/include/gnunet_mysql_lib.h
@@ -41,6 +41,12 @@ extern "C"
 #endif
 #endif
 
+#ifdef HAVE_MYSQL8
+  typedef bool MYSQL_BOOL;
+#else
+  typedef my_bool MYSQL_BOOL; //MySQL < 8 wants this
+#endif
+
 
 /**
  * Mysql context.
diff --git a/src/include/gnunet_os_lib.h b/src/include/gnunet_os_lib.h
index b583cc493afdb9e2d3e995f8a3731c2442a68f93..749f766d2cd364c80b6fb61a8ef8ceecd81758df 100644
--- a/src/include/gnunet_os_lib.h
+++ b/src/include/gnunet_os_lib.h
@@ -1,6 +1,6 @@
 /*
      This file is part of GNUnet.
-     Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006, 2011 GNUnet e.V.
+     Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006, 2011, 2020 GNUnet e.V.
 
      GNUnet is free software: you can redistribute it and/or modify it
      under the terms of the GNU Affero General Public License as published
@@ -100,7 +100,12 @@ enum GNUNET_OS_InheritStdioFlags
    * Use this option to have all of the standard streams
    * (stdin, stdout and stderror) be inherited.
    */
-  GNUNET_OS_INHERIT_STD_ALL = 7
+  GNUNET_OS_INHERIT_STD_ALL = 7,
+
+  /**
+   * Should a pipe be used to send signals to the child?
+   */
+  GNUNET_OS_USE_PIPE_CONTROL = 8
 };
 
 
@@ -455,7 +460,6 @@ GNUNET_OS_process_get_pid (struct GNUNET_OS_Process *proc);
 /**
  * Start a process.
  *
- * @param pipe_control should a pipe be used to send signals to the child?
  * @param std_inheritance a set of GNUNET_OS_INHERIT_STD_* flags
  * @param pipe_stdin pipe to use to send input to child process (or NULL)
  * @param pipe_stdout pipe to use to get output from child process (or NULL)
@@ -465,8 +469,7 @@ GNUNET_OS_process_get_pid (struct GNUNET_OS_Process *proc);
  * @return pointer to process structure of the new process, NULL on error
  */
 struct GNUNET_OS_Process *
-GNUNET_OS_start_process_vap (int pipe_control,
-                             enum GNUNET_OS_InheritStdioFlags std_inheritance,
+GNUNET_OS_start_process_vap (enum GNUNET_OS_InheritStdioFlags std_inheritance,
                              struct GNUNET_DISK_PipeHandle *pipe_stdin,
                              struct GNUNET_DISK_PipeHandle *pipe_stdout,
                              struct GNUNET_DISK_PipeHandle *pipe_stderr,
@@ -477,7 +480,6 @@ GNUNET_OS_start_process_vap (int pipe_control,
 /**
  * Start a process.
  *
- * @param pipe_control should a pipe be used to send signals to the child?
  * @param std_inheritance a set of GNUNET_OS_INHERIT_STD_* flags
  * @param pipe_stdin pipe to use to send input to child process (or NULL)
  * @param pipe_stdout pipe to use to get output from child process (or NULL)
@@ -487,8 +489,7 @@ GNUNET_OS_start_process_vap (int pipe_control,
  * @return pointer to process structure of the new process, NULL on error
  */
 struct GNUNET_OS_Process *
-GNUNET_OS_start_process (int pipe_control,
-                         enum GNUNET_OS_InheritStdioFlags std_inheritance,
+GNUNET_OS_start_process (enum GNUNET_OS_InheritStdioFlags std_inheritance,
                          struct GNUNET_DISK_PipeHandle *pipe_stdin,
                          struct GNUNET_DISK_PipeHandle *pipe_stdout,
                          struct GNUNET_DISK_PipeHandle *pipe_stderr,
@@ -498,7 +499,6 @@ GNUNET_OS_start_process (int pipe_control,
 /**
  * Start a process.
  *
- * @param pipe_control should a pipe be used to send signals to the child?
  * @param std_inheritance a set of GNUNET_OS_INHERIT_STD_* flags
  * @param pipe_stdin pipe to use to send input to child process (or NULL)
  * @param pipe_stdout pipe to use to get output from child process (or NULL)
@@ -508,8 +508,7 @@ GNUNET_OS_start_process (int pipe_control,
  * @return pointer to process structure of the new process, NULL on error
  */
 struct GNUNET_OS_Process *
-GNUNET_OS_start_process_va (int pipe_control,
-                            enum GNUNET_OS_InheritStdioFlags std_inheritance,
+GNUNET_OS_start_process_va (enum GNUNET_OS_InheritStdioFlags std_inheritance,
                             struct GNUNET_DISK_PipeHandle *pipe_stdin,
                             struct GNUNET_DISK_PipeHandle *pipe_stdout,
                             struct GNUNET_DISK_PipeHandle *pipe_stderr,
@@ -518,7 +517,6 @@ GNUNET_OS_start_process_va (int pipe_control,
 /**
  * Start a process.
  *
- * @param pipe_control should a pipe be used to send signals to the child?
  * @param std_inheritance a set of GNUNET_OS_INHERIT_STD_* flags
  * @param lsocks array of listen sockets to dup systemd-style (or NULL);
  *         must be NULL on platforms where dup is not supported
@@ -528,8 +526,7 @@ GNUNET_OS_start_process_va (int pipe_control,
  * @return pointer to process structure of the new process, NULL on error
  */
 struct GNUNET_OS_Process *
-GNUNET_OS_start_process_v (int pipe_control,
-                           enum GNUNET_OS_InheritStdioFlags std_inheritance,
+GNUNET_OS_start_process_v (enum GNUNET_OS_InheritStdioFlags std_inheritance,
                            const int *lsocks,
                            const char *filename,
                            char *const argv[]);
@@ -542,7 +539,6 @@ GNUNET_OS_start_process_v (int pipe_control,
  * in the order they appear.  Arguments containing spaces can be used by
  * quoting them with @em ".
  *
- * @param pipe_control should a pipe be used to send signals to the child?
  * @param std_inheritance a set of GNUNET_OS_INHERIT_STD_* flags
  * @param lsocks array of listen sockets to dup systemd-style (or NULL);
  *         must be NULL on platforms where dup is not supported
@@ -554,8 +550,7 @@ GNUNET_OS_start_process_v (int pipe_control,
  * @return pointer to process structure of the new process, NULL on error
  */
 struct GNUNET_OS_Process *
-GNUNET_OS_start_process_s (int pipe_control,
-                           unsigned int std_inheritance,
+GNUNET_OS_start_process_s (enum GNUNET_OS_InheritStdioFlags std_inheritance,
                            const int *lsocks,
                            const char *filename, ...);
 
diff --git a/src/include/gnunet_peerstore_service.h b/src/include/gnunet_peerstore_service.h
index cd68dad665651703c0e281e7303ea653d5dab64f..91a8f2e666898be902cefdf3b2f029f84cbd4152 100644
--- a/src/include/gnunet_peerstore_service.h
+++ b/src/include/gnunet_peerstore_service.h
@@ -67,6 +67,24 @@ extern "C" {
 #define GNUNET_PEERSTORE_TRANSPORT_DVLEARN_MONOTIME \
   "transport-dv-learn-monotonic-time"
 
+/**
+ * Key used to store sender's monotonic time from handshake message.
+ */
+#define GNUNET_PEERSTORE_TRANSPORT_TCP_COMMUNICATOR_HANDSHAKE \
+  "transport-tcp-communicator-handshake"
+
+/**
+ * Key used to store sender's monotonic time from handshake ack message.
+ */
+#define GNUNET_PEERSTORE_TRANSPORT_TCP_COMMUNICATOR_HANDSHAKE_ACK \
+  "transport-tcp-communicator-handshake-ack"
+
+/**
+ * Key used to store sender's monotonic time from rekey message.
+ */
+#define GNUNET_PEERSTORE_TRANSPORT_TCP_COMMUNICATOR_REKEY \
+  "transport-tcp-communicator-rekey"
+
 
 /**
  * Options for storing values in PEERSTORE
diff --git a/src/include/gnunet_protocols.h b/src/include/gnunet_protocols.h
index 0db6150aa469362ece6f8b9b574be03e904de390..d9821ffe84787344f206fe67a5e817d200b49842 100644
--- a/src/include/gnunet_protocols.h
+++ b/src/include/gnunet_protocols.h
@@ -1658,10 +1658,213 @@ extern "C" {
 #define GNUNET_MESSAGE_TYPE_CONSENSUS_P2P_ROUND_CONTEXT 547
 
 
+/*******************************************************************************
+ * SETU message types
+ ******************************************************************************/
+
+
+/**
+ * Cancel a set operation
+ */
+#define GNUNET_MESSAGE_TYPE_SETU_CANCEL 550
+
+/**
+ * Add element to set
+ */
+#define GNUNET_MESSAGE_TYPE_SETU_ADD 551
+
+/**
+ * Create a new local set
+ */
+#define GNUNET_MESSAGE_TYPE_SETU_CREATE 552
+
+/**
+ * Handle result message from operation
+ */
+#define GNUNET_MESSAGE_TYPE_SETU_RESULT 553
+
+/**
+ * Evaluate a set operation
+ */
+#define GNUNET_MESSAGE_TYPE_SETU_EVALUATE 554
+
+/**
+ * Listen for operation requests
+ */
+#define GNUNET_MESSAGE_TYPE_SETU_LISTEN 555
+
+/**
+ * Reject a set request.
+ */
+#define GNUNET_MESSAGE_TYPE_SETU_REJECT 556
+
+/**
+ * Accept an incoming set request
+ */
+#define GNUNET_MESSAGE_TYPE_SETU_ACCEPT 557
+
+/**
+ * Notify the client of an incoming request from a remote peer
+ */
+#define GNUNET_MESSAGE_TYPE_SETU_REQUEST 558
+
+
+/**
+ * Demand the whole element from the other
+ * peer, given only the hash code.
+ */
+#define GNUNET_MESSAGE_TYPE_SETU_P2P_REQUEST_FULL 559
+
+/**
+ * Demand the whole element from the other
+ * peer, given only the hash code.
+ */
+#define GNUNET_MESSAGE_TYPE_SETU_P2P_DEMAND 560
+
+/**
+ * Tell the other peer to send us a list of
+ * hashes that match an IBF key.
+ */
+#define GNUNET_MESSAGE_TYPE_SETU_P2P_INQUIRY 561
+
+/**
+ * Tell the other peer which hashes match a
+ * given IBF key.
+ */
+#define GNUNET_MESSAGE_TYPE_SETU_P2P_OFFER 562
+
+/**
+ * Request a set union operation from a remote peer.
+ */
+#define GNUNET_MESSAGE_TYPE_SETU_P2P_OPERATION_REQUEST 563
+
+/**
+ * Strata estimator.
+ */
+#define GNUNET_MESSAGE_TYPE_SETU_P2P_SE 564
+
+/**
+ * Invertible bloom filter.
+ */
+#define GNUNET_MESSAGE_TYPE_SETU_P2P_IBF 565
+
+/**
+ * Actual set elements.
+ */
+#define GNUNET_MESSAGE_TYPE_SETU_P2P_ELEMENTS 566
+
+/**
+ * Requests for the elements with the given hashes.
+ */
+#define GNUNET_MESSAGE_TYPE_SETU_P2P_ELEMENT_REQUESTS 567
+
+/**
+ * Set operation is done.
+ */
+#define GNUNET_MESSAGE_TYPE_SETU_P2P_DONE 568
+
+/**
+ * Compressed strata estimator.
+ */
+#define GNUNET_MESSAGE_TYPE_SETU_P2P_SEC 569
+
+/**
+ * Request all missing elements from the other peer,
+ * based on their sets and the elements we previously sent
+ * with #GNUNET_MESSAGE_TYPE_SET_P2P_ELEMENTS.
+ */
+#define GNUNET_MESSAGE_TYPE_SETU_P2P_FULL_DONE 570
+
+/**
+ * Send a set element, not as response to a demand but because
+ * we're sending the full set.
+ */
+#define GNUNET_MESSAGE_TYPE_SETU_P2P_FULL_ELEMENT 571
+
+/**
+ * Request all missing elements from the other peer,
+ * based on their sets and the elements we previously sent
+ * with #GNUNET_MESSAGE_TYPE_SET_P2P_ELEMENTS.
+ */
+#define GNUNET_MESSAGE_TYPE_SETU_P2P_OVER 572
+
+
+/*******************************************************************************
+ * SETI message types
+ ******************************************************************************/
+
+
+/**
+ * Cancel a set operation
+ */
+#define GNUNET_MESSAGE_TYPE_SETI_CANCEL 580
+
+/**
+ * Add element to set.
+ */
+#define GNUNET_MESSAGE_TYPE_SETI_ADD 581
+
+/**
+ * Create a new local set
+ */
+#define GNUNET_MESSAGE_TYPE_SETI_CREATE 582
+
+/**
+ * Handle result message from operation
+ */
+#define GNUNET_MESSAGE_TYPE_SETI_RESULT 583
+
+/**
+ * Evaluate a set operation
+ */
+#define GNUNET_MESSAGE_TYPE_SETI_EVALUATE 584
+
+/**
+ * Listen for operation requests
+ */
+#define GNUNET_MESSAGE_TYPE_SETI_LISTEN 585
+
+/**
+ * Reject a set request.
+ */
+#define GNUNET_MESSAGE_TYPE_SETI_REJECT 586
+
+/**
+ * Accept an incoming set request
+ */
+#define GNUNET_MESSAGE_TYPE_SETI_ACCEPT 587
+
+/**
+ * Notify the client of an incoming request from a remote peer
+ */
+#define GNUNET_MESSAGE_TYPE_SETI_REQUEST 588
+
+/**
+ * Information about the element count for intersection
+ */
+#define GNUNET_MESSAGE_TYPE_SETI_P2P_ELEMENT_INFO 591
+
+/**
+ * Bloom filter message for intersection exchange started by Bob.
+ */
+#define GNUNET_MESSAGE_TYPE_SETI_P2P_BF 592
+
+/**
+ * Intersection operation is done.
+ */
+#define GNUNET_MESSAGE_TYPE_SETI_P2P_DONE 593
+
+/**
+ * Request to begin set intersection operation.
+ */
+#define GNUNET_MESSAGE_TYPE_SETI_P2P_OPERATION_REQUEST 594
+
+
 /*******************************************************************************
  * SET message types
  ******************************************************************************/
 
+
 /**
  * Demand the whole element from the other
  * peer, given only the hash code.
@@ -2697,17 +2900,17 @@ extern "C" {
 
 #define GNUNET_MESSAGE_TYPE_RECLAIM_ATTRIBUTE_DELETE 976
 
-#define GNUNET_MESSAGE_TYPE_RECLAIM_ATTESTATION_STORE 977
+#define GNUNET_MESSAGE_TYPE_RECLAIM_CREDENTIAL_STORE 977
 
-#define GNUNET_MESSAGE_TYPE_RECLAIM_ATTESTATION_DELETE 978
+#define GNUNET_MESSAGE_TYPE_RECLAIM_CREDENTIAL_DELETE 978
 
-#define GNUNET_MESSAGE_TYPE_RECLAIM_ATTESTATION_RESULT 979
+#define GNUNET_MESSAGE_TYPE_RECLAIM_CREDENTIAL_RESULT 979
 
-#define GNUNET_MESSAGE_TYPE_RECLAIM_ATTESTATION_ITERATION_START 980
+#define GNUNET_MESSAGE_TYPE_RECLAIM_CREDENTIAL_ITERATION_START 980
 
-#define GNUNET_MESSAGE_TYPE_RECLAIM_ATTESTATION_ITERATION_STOP 981
+#define GNUNET_MESSAGE_TYPE_RECLAIM_CREDENTIAL_ITERATION_STOP 981
 
-#define GNUNET_MESSAGE_TYPE_RECLAIM_ATTESTATION_ITERATION_NEXT 982
+#define GNUNET_MESSAGE_TYPE_RECLAIM_CREDENTIAL_ITERATION_NEXT 982
 
 
 /**************************************************
@@ -3292,6 +3495,11 @@ extern "C" {
  */
 #define GNUNET_MESSAGE_TYPE_COMMUNICATOR_TCP_FINISH 1452
 
+/**
+ * TCP communicator confirmation ack.
+ */
+#define GNUNET_MESSAGE_TYPE_COMMUNICATOR_TCP_CONFIRMATION_ACK 1453
+
 /**
  * UDP KX acknowledgement.
  */
diff --git a/src/include/gnunet_reclaim_lib.h b/src/include/gnunet_reclaim_lib.h
index 54d284f3cbe601abb31f7c0922ae412cd6927b1e..bbf1c3ad366a3a653734cb8ea14413b9898bfa15 100644
--- a/src/include/gnunet_reclaim_lib.h
+++ b/src/include/gnunet_reclaim_lib.h
@@ -39,32 +39,41 @@ extern "C" {
 
 #include "gnunet_util_lib.h"
 
+enum GNUNET_RECLAIM_AttributeType {
+  /**
+   * No value attribute.
+   */
+  GNUNET_RECLAIM_ATTRIBUTE_TYPE_NONE = 0,
 
-/**
- * No value attribute.
- */
-#define GNUNET_RECLAIM_ATTRIBUTE_TYPE_NONE 0
+  /**
+   * String attribute.
+   */
+  GNUNET_RECLAIM_ATTRIBUTE_TYPE_STRING = 1
+};
 
-/**
- * String attribute.
- */
-#define GNUNET_RECLAIM_ATTRIBUTE_TYPE_STRING 1
+enum GNUNET_RECLAIM_CredentialType {
+  /**
+   * No value credential.
+   */
+  GNUNET_RECLAIM_CREDENTIAL_TYPE_NONE = 0,
 
-/**
-* No value attestation.
-*/
-#define GNUNET_RECLAIM_ATTESTATION_TYPE_NONE 10
+  /**
+   * A JSON Web Token credential.
+   */
+  GNUNET_RECLAIM_CREDENTIAL_TYPE_JWT = 1,
 
-/**
-* A JSON Web Token attestation.
-*/
-#define GNUNET_RECLAIM_ATTESTATION_TYPE_JWT 11
+  /**
+   * libpabc credential
+   */
+  GNUNET_RECLAIM_CREDENTIAL_TYPE_PABC = 2
+};
 
 /**
  * We want an ID to be a 256-bit symmetric key
  */
 #define GNUNET_RECLAIM_ID_LENGTH (256 / 8)
 
+GNUNET_NETWORK_STRUCT_BEGIN
 /**
  * A reclaim identifier
  * FIXME maybe put this in a different namespace
@@ -74,13 +83,15 @@ struct GNUNET_RECLAIM_Identifier
   char id[GNUNET_RECLAIM_ID_LENGTH];
 };
 
+GNUNET_NETWORK_STRUCT_END
+
 static const struct GNUNET_RECLAIM_Identifier GNUNET_RECLAIM_ID_ZERO;
 
 #define GNUNET_RECLAIM_id_is_equal(a,b) ((0 == \
                                           memcmp (a, \
                                                   b, \
                                                   sizeof (GNUNET_RECLAIM_ID_ZERO))) \
-  ? \
+                                         ? \
                                          GNUNET_YES : GNUNET_NO)
 
 
@@ -104,9 +115,10 @@ struct GNUNET_RECLAIM_Attribute
   struct GNUNET_RECLAIM_Identifier id;
 
   /**
-   * Referenced ID of Attestation (may be 0 if self-attested)
+   * Referenced ID of credential
+   * (may be GNUNET_RECLAIM_ID_ZERO if self-creded)
    */
-  struct GNUNET_RECLAIM_Identifier attestation;
+  struct GNUNET_RECLAIM_Identifier credential;
 
   /**
    * Type of Claim
@@ -138,9 +150,9 @@ struct GNUNET_RECLAIM_Attribute
 };
 
 /**
- * An attestation.
+ * A credential.
  */
-struct GNUNET_RECLAIM_Attestation
+struct GNUNET_RECLAIM_Credential
 {
   /**
    * ID
@@ -158,7 +170,7 @@ struct GNUNET_RECLAIM_Attestation
   uint32_t flag;
 
   /**
-   * The name of the attribute. Note "name" must never be individually
+   * The name of the credential. Note: must never be individually
    * free'd
    */
   const char *name;
@@ -169,7 +181,36 @@ struct GNUNET_RECLAIM_Attestation
   size_t data_size;
 
   /**
-   * Binary value stored as attribute value.  Note: "data" must never
+   * Binary value stored as credential value.  Note: "data" must never
+   * be individually 'malloc'ed, but instead always points into some
+   * existing data area.
+   */
+  const void *data;
+};
+
+
+/**
+ * A credential presentation.
+ */
+struct GNUNET_RECLAIM_Presentation
+{
+  /**
+   * The credential id of which this is a presentation.
+   */
+  struct GNUNET_RECLAIM_Identifier credential_id;
+
+  /**
+   * Type/Format of Claim
+   */
+  uint32_t type;
+
+  /**
+   * Number of bytes in @e data.
+   */
+  size_t data_size;
+
+  /**
+   * Binary value stored as presentation value.  Note: "data" must never
    * be individually 'malloc'ed, but instead always points into some
    * existing data area.
    */
@@ -177,6 +218,7 @@ struct GNUNET_RECLAIM_Attestation
 };
 
 
+
 /**
  * A list of GNUNET_RECLAIM_Attribute structures.
  */
@@ -214,56 +256,94 @@ struct GNUNET_RECLAIM_AttributeListEntry
 };
 
 /**
- * A list of GNUNET_RECLAIM_Attestation structures.
+ * A list of GNUNET_RECLAIM_Credential structures.
+ */
+struct GNUNET_RECLAIM_CredentialList
+{
+  /**
+   * List head
+   */
+  struct GNUNET_RECLAIM_CredentialListEntry *list_head;
+
+  /**
+   * List tail
+   */
+  struct GNUNET_RECLAIM_CredentialListEntry *list_tail;
+};
+
+
+struct GNUNET_RECLAIM_CredentialListEntry
+{
+  /**
+   * DLL
+   */
+  struct GNUNET_RECLAIM_CredentialListEntry *prev;
+
+  /**
+   * DLL
+   */
+  struct GNUNET_RECLAIM_CredentialListEntry *next;
+
+  /**
+   * The credential
+   */
+  struct GNUNET_RECLAIM_Credential *credential;
+
+};
+
+
+/**
+ * A list of GNUNET_RECLAIM_Presentation structures.
  */
-struct GNUNET_RECLAIM_AttestationList
+struct GNUNET_RECLAIM_PresentationList
 {
   /**
    * List head
    */
-  struct GNUNET_RECLAIM_AttestationListEntry *list_head;
+  struct GNUNET_RECLAIM_PresentationListEntry *list_head;
 
   /**
    * List tail
    */
-  struct GNUNET_RECLAIM_AttestationListEntry *list_tail;
+  struct GNUNET_RECLAIM_PresentationListEntry *list_tail;
 };
 
 
-struct GNUNET_RECLAIM_AttestationListEntry
+struct GNUNET_RECLAIM_PresentationListEntry
 {
   /**
    * DLL
    */
-  struct GNUNET_RECLAIM_AttestationListEntry *prev;
+  struct GNUNET_RECLAIM_PresentationListEntry *prev;
 
   /**
    * DLL
    */
-  struct GNUNET_RECLAIM_AttestationListEntry *next;
+  struct GNUNET_RECLAIM_PresentationListEntry *next;
 
   /**
-   * The attestation
+   * The credential
    */
-  struct GNUNET_RECLAIM_Attestation *attestation;
+  struct GNUNET_RECLAIM_Presentation *presentation;
 
 };
 
 
+
 /**
  * Create a new attribute claim.
  *
  * @param attr_name the attribute name
- * @param attestation ID of the attestation (may be NULL)
+ * @param credential ID of the credential (may be NULL)
  * @param type the attribute type
- * @param data the attribute value. Must be the mapped name if attestation not NULL
+ * @param data the attribute value. Must be #attr_name if credential not NULL
  * @param data_size the attribute value size
  * @return the new attribute
  */
 struct GNUNET_RECLAIM_Attribute *
 GNUNET_RECLAIM_attribute_new (const char *attr_name,
                               const struct
-                              GNUNET_RECLAIM_Identifier *attestation,
+                              GNUNET_RECLAIM_Identifier *credential,
                               uint32_t type,
                               const void *data,
                               size_t data_size);
@@ -295,7 +375,7 @@ GNUNET_RECLAIM_attribute_list_destroy (
  *
  * @param attrs the attribute list to add to
  * @param attr_name the name of the new attribute claim
- * @param attestation attestation ID (may be NULL)
+ * @param credential credential ID (may be NULL)
  * @param type the type of the claim
  * @param data claim payload
  * @param data_size claim payload size
@@ -304,7 +384,7 @@ void
 GNUNET_RECLAIM_attribute_list_add (
   struct GNUNET_RECLAIM_AttributeList *attrs,
   const char *attr_name,
-  const struct GNUNET_RECLAIM_Identifier *attestation,
+  const struct GNUNET_RECLAIM_Identifier *credential,
   uint32_t type,
   const void *data,
   size_t data_size);
@@ -361,11 +441,13 @@ GNUNET_RECLAIM_attribute_serialize (const struct GNUNET_RECLAIM_Attribute *attr,
  *
  * @param data the serialized attribute
  * @param data_size the length of the serialized data
+ * @param attr deserialized attribute. Will be allocated. Must be free'd
  *
- * @return a GNUNET_IDENTITY_PROVIDER_Attribute, must be free'd by caller
+ * @return number of bytes read or -1 for error
  */
-struct GNUNET_RECLAIM_Attribute *
-GNUNET_RECLAIM_attribute_deserialize (const char *data, size_t data_size);
+ssize_t
+GNUNET_RECLAIM_attribute_deserialize (const char *data, size_t data_size,
+                                      struct GNUNET_RECLAIM_Attribute **attr);
 
 
 /**
@@ -434,8 +516,8 @@ GNUNET_RECLAIM_attribute_number_to_typename (uint32_t type);
  * @return the required buffer size
  */
 size_t
-GNUNET_RECLAIM_attestation_list_serialize_get_size (
-  const struct GNUNET_RECLAIM_AttestationList *attestations);
+GNUNET_RECLAIM_credential_list_serialize_get_size (
+  const struct GNUNET_RECLAIM_CredentialList *credentials);
 
 
 /**
@@ -444,8 +526,8 @@ GNUNET_RECLAIM_attestation_list_serialize_get_size (
  * @param attrs list to destroy
  */
 void
-GNUNET_RECLAIM_attestation_list_destroy (
-  struct GNUNET_RECLAIM_AttestationList *attestations);
+GNUNET_RECLAIM_credential_list_destroy (
+  struct GNUNET_RECLAIM_CredentialList *credentials);
 
 
 /**
@@ -457,8 +539,8 @@ GNUNET_RECLAIM_attestation_list_destroy (
  * @param data_size claim payload size
  */
 void
-GNUNET_RECLAIM_attestation_list_add (
-  struct GNUNET_RECLAIM_AttestationList *attrs,
+GNUNET_RECLAIM_credential_list_add (
+  struct GNUNET_RECLAIM_CredentialList *attrs,
   const char *att_name,
   uint32_t type,
   const void *data,
@@ -473,8 +555,8 @@ GNUNET_RECLAIM_attestation_list_add (
  * @return length of serialized data
  */
 size_t
-GNUNET_RECLAIM_attestation_list_serialize (
-  const struct GNUNET_RECLAIM_AttestationList *attrs,
+GNUNET_RECLAIM_credential_list_serialize (
+  const struct GNUNET_RECLAIM_CredentialList *attrs,
   char *result);
 
 
@@ -485,75 +567,75 @@ GNUNET_RECLAIM_attestation_list_serialize (
  * @param data_size the length of the serialized data
  * @return a GNUNET_IDENTITY_PROVIDER_AttributeList, must be free'd by caller
  */
-struct GNUNET_RECLAIM_AttestationList *
-GNUNET_RECLAIM_attestation_list_deserialize (const char *data,
+struct GNUNET_RECLAIM_CredentialList *
+GNUNET_RECLAIM_credential_list_deserialize (const char *data,
                                              size_t data_size);
 
 
 /**
-   * @param attestation the attestation to serialize
+   * @param credential the credential to serialize
    * @return the required buffer size
    */
 size_t
-GNUNET_RECLAIM_attestation_serialize_get_size (
-  const struct GNUNET_RECLAIM_Attestation *attestation);
+GNUNET_RECLAIM_credential_serialize_get_size (
+  const struct GNUNET_RECLAIM_Credential *credential);
 
 
 /**
- * Serialize an attestation
+ * Serialize an credential
  *
- * @param attestation the attestation to serialize
- * @param result the serialized attestation
+ * @param credential the credential to serialize
+ * @param result the serialized credential
  * @return length of serialized data
  */
 size_t
-GNUNET_RECLAIM_attestation_serialize (
-  const struct GNUNET_RECLAIM_Attestation *attestation,
+GNUNET_RECLAIM_credential_serialize (
+  const struct GNUNET_RECLAIM_Credential *credential,
   char *result);
 
 
 /**
- * Deserialize an attestation
+ * Deserialize an credential
  *
- * @param data the serialized attestation
+ * @param data the serialized credential
  * @param data_size the length of the serialized data
  *
  * @return a GNUNET_IDENTITY_PROVIDER_Attribute, must be free'd by caller
  */
-struct GNUNET_RECLAIM_Attestation *
-GNUNET_RECLAIM_attestation_deserialize (const char *data, size_t data_size);
+struct GNUNET_RECLAIM_Credential *
+GNUNET_RECLAIM_credential_deserialize (const char *data, size_t data_size);
 
 
 /**
- * Create a new attestation.
+ * Create a new credential.
  *
- * @param name the attestation name
- * @param type the attestation type
- * @param data the attestation value
- * @param data_size the attestation value size
- * @return the new attestation
- */
-struct GNUNET_RECLAIM_Attestation *
-GNUNET_RECLAIM_attestation_new (const char *name,
+ * @param name the credential name
+ * @param type the credential type
+ * @param data the credential value
+ * @param data_size the credential value size
+ * @return the new credential
+ */
+struct GNUNET_RECLAIM_Credential *
+GNUNET_RECLAIM_credential_new (const char *name,
                                 uint32_t type,
                                 const void *data,
                                 size_t data_size);
 
 /**
- * Convert the 'claim' of an attestation to a string
+ * Convert the 'claim' of an credential to a string
  *
- * @param type the type of attestation
+ * @param type the type of credential
  * @param data claim in binary encoding
  * @param data_size number of bytes in @a data
  * @return NULL on error, otherwise human-readable representation of the claim
  */
 char *
-GNUNET_RECLAIM_attestation_value_to_string (uint32_t type,
+GNUNET_RECLAIM_credential_value_to_string (uint32_t type,
                                             const void *data,
                                             size_t data_size);
 
 /**
- * Convert human-readable version of a 'claim' of an attestation to the binary
+ * Convert human-readable version of a 'claim' of an credential to the binary
  * representation
  *
  * @param type type of the claim
@@ -563,48 +645,206 @@ GNUNET_RECLAIM_attestation_value_to_string (uint32_t type,
  * @return #GNUNET_OK on success
  */
 int
-GNUNET_RECLAIM_attestation_string_to_value (uint32_t type,
+GNUNET_RECLAIM_credential_string_to_value (uint32_t type,
                                             const char *s,
                                             void **data,
                                             size_t *data_size);
 
 /**
- * Convert an attestation type number to the corresponding attestation type string
+ * Convert an credential type number to the corresponding credential type string
  *
  * @param type number of a type
  * @return corresponding typestring, NULL on error
  */
 const char *
-GNUNET_RECLAIM_attestation_number_to_typename (uint32_t type);
+GNUNET_RECLAIM_credential_number_to_typename (uint32_t type);
 
 /**
- * Convert an attestation type name to the corresponding number
+ * Convert an credential type name to the corresponding number
  *
  * @param typename name to convert
  * @return corresponding number, UINT32_MAX on error
  */
 uint32_t
-GNUNET_RECLAIM_attestation_typename_to_number (const char *typename);
+GNUNET_RECLAIM_credential_typename_to_number (const char *typename);
 
 /**
- * Convert an attestation type name to the corresponding number
+ * Convert an credential type name to the corresponding number
  *
  * @param typename name to convert
  * @return corresponding number, UINT32_MAX on error
  */
 struct GNUNET_RECLAIM_AttributeList*
-GNUNET_RECLAIM_attestation_get_attributes (const struct
-                                           GNUNET_RECLAIM_Attestation *attest);
+GNUNET_RECLAIM_credential_get_attributes (const struct
+                                           GNUNET_RECLAIM_Credential *cred);
+
+char*
+GNUNET_RECLAIM_credential_get_issuer (const struct
+                                       GNUNET_RECLAIM_Credential *cred);
+
+int
+GNUNET_RECLAIM_credential_get_expiration (const struct
+                                           GNUNET_RECLAIM_Credential *cred,
+                                           struct GNUNET_TIME_Absolute *exp);
+
+/**
+ * Get required size for serialization buffer
+ *
+ * @param presentations the presentation list to serialize
+ * @return the required buffer size
+ */
+size_t
+GNUNET_RECLAIM_presentation_list_serialize_get_size (
+  const struct GNUNET_RECLAIM_PresentationList *presentations);
+
+
+/**
+ * Destroy presentations list
+ *
+ * @param presentations list to destroy
+ */
+void
+GNUNET_RECLAIM_presentation_list_destroy (
+  struct GNUNET_RECLAIM_PresentationList *presentations);
+
+
+/**
+ * Serialize a presentation list
+ *
+ * @param presentations the attribute list to serialize
+ * @param result the serialized list
+ * @return length of serialized data
+ */
+size_t
+GNUNET_RECLAIM_presentation_list_serialize (
+  const struct GNUNET_RECLAIM_PresentationList *presentations,
+  char *result);
+
+
+/**
+ * Deserialize a presentation list
+ *
+ * @param data the serialized list
+ * @param data_size the length of the serialized data
+ * @return a GNUNET_RECLAIM_PresentationList, must be free'd by caller
+ */
+struct GNUNET_RECLAIM_PresentationList *
+GNUNET_RECLAIM_presentation_list_deserialize (const char *data,
+                                              size_t data_size);
+
+
+/**
+ * @param presentation the presentation to serialize
+ * @return the required buffer size
+ */
+size_t
+GNUNET_RECLAIM_presentation_serialize_get_size (
+  const struct GNUNET_RECLAIM_Presentation *presentation);
+
+
+/**
+ * Serialize a presentation.
+ *
+ * @param presentation the presentation to serialize
+ * @param result the serialized presentation
+ * @return length of serialized data
+ */
+size_t
+GNUNET_RECLAIM_presentation_serialize (
+  const struct GNUNET_RECLAIM_Presentation *presentation,
+  char *result);
+
+
+/**
+ * Deserialize a presentation
+ *
+ * @param data the serialized presentation
+ * @param data_size the length of the serialized data
+ *
+ * @return a GNUNET_RECLAIM_Presentation, must be free'd by caller
+ */
+struct GNUNET_RECLAIM_Presentation *
+GNUNET_RECLAIM_presentation_deserialize (const char *data, size_t data_size);
+
+
+/**
+ * Convert the 'claim' of a presentation to a string
+ *
+ * @param type the type of presentation
+ * @param data presentation in binary encoding
+ * @param data_size number of bytes in @a data
+ * @return NULL on error, otherwise human-readable representation of the claim
+ */
+char *
+GNUNET_RECLAIM_presentation_value_to_string (uint32_t type,
+                                             const void *data,
+                                             size_t data_size);
+
+struct GNUNET_RECLAIM_Presentation *
+GNUNET_RECLAIM_presentation_new (uint32_t type,
+                                 const void *data,
+                                 size_t data_size);
+
+/**
+ * Convert human-readable version of a 'claim' of a presentation to the binary
+ * representation
+ *
+ * @param type type of the presentation
+ * @param s human-readable string
+ * @param data set to value in binary encoding (will be allocated)
+ * @param data_size set to number of bytes in @a data
+ * @return #GNUNET_OK on success
+ */
+int
+GNUNET_RECLAIM_presentation_string_to_value (uint32_t type,
+                                             const char *s,
+                                             void **data,
+                                             size_t *data_size);
+
+/**
+ * Convert a presentation type number to the corresponding credential type
+ * string.
+ *
+ * @param type number of a type
+ * @return corresponding typestring, NULL on error
+ */
+const char *
+GNUNET_RECLAIM_presentation_number_to_typename (uint32_t type);
+
+struct GNUNET_RECLAIM_AttributeList*
+GNUNET_RECLAIM_presentation_get_attributes (const struct
+                                           GNUNET_RECLAIM_Presentation *cred);
 
 char*
-GNUNET_RECLAIM_attestation_get_issuer (const struct
-                                       GNUNET_RECLAIM_Attestation *attest);
+GNUNET_RECLAIM_presentation_get_issuer (const struct
+                                       GNUNET_RECLAIM_Presentation *cred);
 
 int
-GNUNET_RECLAIM_attestation_get_expiration (const struct
-                                           GNUNET_RECLAIM_Attestation *attest,
+GNUNET_RECLAIM_presentation_get_expiration (const struct
+                                           GNUNET_RECLAIM_Presentation *cred,
                                            struct GNUNET_TIME_Absolute *exp);
 
+
+
+/**
+ * Create a presentation from a credential and a lift of (selected)
+ * attributes in the credential.
+ * FIXME not yet implemented
+ *
+ * @param cred the credential to use
+ * @param attrs the attributes to present from the credential
+ * @param presentation the credential presentation presenting the attributes according
+ *         to the presentation mechanism of the credential
+ *         or NULL on error.
+ * @return GNUNET_OK on success.
+ */
+int
+GNUNET_RECLAIM_credential_get_presentation (
+                              const struct GNUNET_RECLAIM_Credential *cred,
+                              const struct GNUNET_RECLAIM_AttributeList *attrs,
+                              struct GNUNET_RECLAIM_Presentation **presentation);
+
+
 #if 0 /* keep Emacsens' auto-indent happy */
 {
 #endif
diff --git a/src/include/gnunet_reclaim_plugin.h b/src/include/gnunet_reclaim_plugin.h
index 992ad0cc3975d196208d75ea6e7380bb05893f3d..2ba8fc8a022262c3c8fc4a1866a1912219e76936 100644
--- a/src/include/gnunet_reclaim_plugin.h
+++ b/src/include/gnunet_reclaim_plugin.h
@@ -27,8 +27,8 @@
  * @defgroup reclaim-attribute-plugin  reclaim plugin API for attributes/claims
  * @{
  */
-#ifndef GNUNET_RECLAIM_AttributePLUGIN_H
-#define GNUNET_RECLAIM_AttributePLUGIN_H
+#ifndef GNUNET_RECLAIM_PLUGIN_H
+#define GNUNET_RECLAIM_PLUGIN_H
 
 #include "gnunet_util_lib.h"
 #include "gnunet_reclaim_lib.h"
@@ -113,7 +113,7 @@ typedef const char *(*GNUNET_RECLAIM_AttributeNumberToTypenameFunction) (
  * @param data_size number of bytes in @a data
  * @return NULL on error, otherwise human-readable representation of the value
  */
-typedef char *(*GNUNET_RECLAIM_AttestationValueToStringFunction) (
+typedef char *(*GNUNET_RECLAIM_CredentialValueToStringFunction) (
   void *cls,
   uint32_t type,
   const void *data,
@@ -132,7 +132,7 @@ typedef char *(*GNUNET_RECLAIM_AttestationValueToStringFunction) (
  * @param data_size set to number of bytes in @a data
  * @return #GNUNET_OK on success
  */
-typedef int (*GNUNET_RECLAIM_AttestationStringToValueFunction) (
+typedef int (*GNUNET_RECLAIM_CredentialStringToValueFunction) (
   void *cls,
   uint32_t type,
   const char *s,
@@ -148,7 +148,7 @@ typedef int (*GNUNET_RECLAIM_AttestationStringToValueFunction) (
  * @param typename name to convert
  * @return corresponding number, UINT32_MAX on error
  */
-typedef uint32_t (*GNUNET_RECLAIM_AttestationTypenameToNumberFunction) (
+typedef uint32_t (*GNUNET_RECLAIM_CredentialTypenameToNumberFunction) (
   void *cls,
   const char *typename);
 
@@ -161,46 +161,151 @@ typedef uint32_t (*GNUNET_RECLAIM_AttestationTypenameToNumberFunction) (
  * @param type number of a type to convert
  * @return corresponding typestring, NULL on error
  */
-typedef const char *(*GNUNET_RECLAIM_AttestationNumberToTypenameFunction) (
+typedef const char *(*GNUNET_RECLAIM_CredentialNumberToTypenameFunction) (
   void *cls,
   uint32_t type);
 
 /**
- * Function called to extract attributes from an attestation
+ * Function called to extract attributes from a credential
  *
  * @param cls closure
- * @param attest the attestation object
+ * @param cred the credential object
  * @return an attribute list
  */
-typedef struct GNUNET_RECLAIM_AttributeList *(*GNUNET_RECLAIM_AttestationGetAttributesFunction) (
+typedef struct
+  GNUNET_RECLAIM_AttributeList *(*
+GNUNET_RECLAIM_CredentialGetAttributesFunction) (
   void *cls,
-  const struct GNUNET_RECLAIM_Attestation *attest);
+  const struct GNUNET_RECLAIM_Credential *cred);
 
 /**
- * Function called to get the issuer of the attestation (as string)
+ * Function called to get the issuer of the credential (as string)
  *
  * @param cls closure
- * @param attest the attestation object
+ * @param cred the credential object
  * @return corresponding issuer string
  */
-typedef char *(*GNUNET_RECLAIM_AttestationGetIssuerFunction) (
+typedef char *(*GNUNET_RECLAIM_CredentialGetIssuerFunction) (
   void *cls,
-  const struct GNUNET_RECLAIM_Attestation *attest);
+  const struct GNUNET_RECLAIM_Credential *cred);
 
 /**
- * Function called to get the expiration of the attestation
+ * Function called to get the expiration of the credential
  *
  * @param cls closure
- * @param attest the attestation object
+ * @param cred the credential object
  * @param where to write the value
  * @return GNUNET_OK if successful
  */
-typedef int (*GNUNET_RECLAIM_AttestationGetExpirationFunction) (
+typedef int (*GNUNET_RECLAIM_CredentialGetExpirationFunction) (
   void *cls,
-  const struct GNUNET_RECLAIM_Attestation *attest,
+  const struct GNUNET_RECLAIM_Credential *cred,
   struct GNUNET_TIME_Absolute *expiration);
 
+/**
+ * Function called to convert the binary value @a data of an attribute of
+ * type @a type to a human-readable string.
+ *
+ * @param cls closure
+ * @param type type of the attribute
+ * @param data value in binary encoding
+ * @param data_size number of bytes in @a data
+ * @return NULL on error, otherwise human-readable representation of the value
+ */
+typedef char *(*GNUNET_RECLAIM_PresentationValueToStringFunction) (
+  void *cls,
+  uint32_t type,
+  const void *data,
+  size_t data_size);
+
+
+/**
+ * Function called to convert human-readable version of the value @a s
+ * of an attribute of type @a type to the respective binary
+ * representation.
+ *
+ * @param cls closure
+ * @param type type of the attribute
+ * @param s human-readable string
+ * @param data set to value in binary encoding (will be allocated)
+ * @param data_size set to number of bytes in @a data
+ * @return #GNUNET_OK on success
+ */
+typedef int (*GNUNET_RECLAIM_PresentationStringToValueFunction) (
+  void *cls,
+  uint32_t type,
+  const char *s,
+  void **data,
+  size_t *data_size);
+
+
+/**
+ * Function called to convert a type name to the
+ * corresponding number.
+ *
+ * @param cls closure
+ * @param typename name to convert
+ * @return corresponding number, UINT32_MAX on error
+ */
+typedef uint32_t (*GNUNET_RECLAIM_PresentationTypenameToNumberFunction) (
+  void *cls,
+  const char *typename);
+
+
+/**
+ * Function called to convert a type number (i.e. 1) to the
+ * corresponding type string
+ *
+ * @param cls closure
+ * @param type number of a type to convert
+ * @return corresponding typestring, NULL on error
+ */
+typedef const char *(*GNUNET_RECLAIM_PresentationNumberToTypenameFunction) (
+  void *cls,
+  uint32_t type);
 
+/**
+ * Function called to extract attributes from a credential
+ *
+ * @param cls closure
+ * @param cred the credential object
+ * @return an attribute list
+ */
+typedef struct
+  GNUNET_RECLAIM_AttributeList *(*
+GNUNET_RECLAIM_PresentationGetAttributesFunction) (
+  void *cls,
+  const struct GNUNET_RECLAIM_Presentation *cred);
+
+/**
+ * Function called to get the issuer of the credential (as string)
+ *
+ * @param cls closure
+ * @param cred the credential object
+ * @return corresponding issuer string
+ */
+typedef char *(*GNUNET_RECLAIM_PresentationGetIssuerFunction) (
+  void *cls,
+  const struct GNUNET_RECLAIM_Presentation *cred);
+
+/**
+ * Function called to get the expiration of the credential
+ *
+ * @param cls closure
+ * @param cred the credential object
+ * @param where to write the value
+ * @return GNUNET_OK if successful
+ */
+typedef int (*GNUNET_RECLAIM_PresentationGetExpirationFunction) (
+  void *cls,
+  const struct GNUNET_RECLAIM_Presentation *cred,
+  struct GNUNET_TIME_Absolute *expiration);
+
+typedef int (*GNUNET_RECLAIM_CredentialToPresentation) (
+  void *cls,
+  const struct GNUNET_RECLAIM_Credential *cred,
+  const struct GNUNET_RECLAIM_AttributeList *attrs,
+  struct GNUNET_RECLAIM_Presentation **presentation);
 
 /**
  * Each plugin is required to return a pointer to a struct of this
@@ -239,7 +344,7 @@ struct GNUNET_RECLAIM_AttributePluginFunctions
  * Each plugin is required to return a pointer to a struct of this
  * type as the return value from its entry point.
  */
-struct GNUNET_RECLAIM_AttestationPluginFunctions
+struct GNUNET_RECLAIM_CredentialPluginFunctions
 {
   /**
    * Closure for all of the callbacks.
@@ -249,39 +354,79 @@ struct GNUNET_RECLAIM_AttestationPluginFunctions
   /**
    * Conversion to string.
    */
-  GNUNET_RECLAIM_AttestationValueToStringFunction value_to_string;
+  GNUNET_RECLAIM_CredentialValueToStringFunction value_to_string;
 
   /**
    * Conversion to binary.
    */
-  GNUNET_RECLAIM_AttestationStringToValueFunction string_to_value;
+  GNUNET_RECLAIM_CredentialStringToValueFunction string_to_value;
 
   /**
    * Typename to number.
    */
-  GNUNET_RECLAIM_AttestationTypenameToNumberFunction typename_to_number;
+  GNUNET_RECLAIM_CredentialTypenameToNumberFunction typename_to_number;
 
   /**
    * Number to typename.
    */
-  GNUNET_RECLAIM_AttestationNumberToTypenameFunction number_to_typename;
+  GNUNET_RECLAIM_CredentialNumberToTypenameFunction number_to_typename;
 
   /**
    * Attesation attributes.
    */
-  GNUNET_RECLAIM_AttestationGetAttributesFunction get_attributes;
+  GNUNET_RECLAIM_CredentialGetAttributesFunction get_attributes;
 
   /**
    * Attesation issuer.
    */
-  GNUNET_RECLAIM_AttestationGetIssuerFunction get_issuer;
+  GNUNET_RECLAIM_CredentialGetIssuerFunction get_issuer;
 
   /**
    * Expiration.
    */
-  GNUNET_RECLAIM_AttestationGetExpirationFunction get_expiration;
-};
+  GNUNET_RECLAIM_CredentialGetExpirationFunction get_expiration;
+
+  /**
+   * Conversion to string.
+   */
+  GNUNET_RECLAIM_PresentationValueToStringFunction value_to_string_p;
 
+  /**
+   * Conversion to binary.
+   */
+  GNUNET_RECLAIM_PresentationStringToValueFunction string_to_value_p;
+
+  /**
+   * Typename to number.
+   */
+  GNUNET_RECLAIM_PresentationTypenameToNumberFunction typename_to_number_p;
+
+  /**
+   * Number to typename.
+   */
+  GNUNET_RECLAIM_PresentationNumberToTypenameFunction number_to_typename_p;
+
+  /**
+   * Attesation attributes.
+   */
+  GNUNET_RECLAIM_PresentationGetAttributesFunction get_attributes_p;
+
+  /**
+   * Attesation issuer.
+   */
+  GNUNET_RECLAIM_PresentationGetIssuerFunction get_issuer_p;
+
+  /**
+   * Expiration.
+   */
+  GNUNET_RECLAIM_PresentationGetExpirationFunction get_expiration_p;
+
+  /**
+   * Get presentation
+   */
+  GNUNET_RECLAIM_CredentialToPresentation create_presentation;
+
+};
 
 
 #if 0 /* keep Emacsens' auto-indent happy */
diff --git a/src/include/gnunet_reclaim_service.h b/src/include/gnunet_reclaim_service.h
index 813bc1a59ac0bc4e96fb22b6abd92964ddff18d4..368058f569a43fcf2cef412f24b104f39a1ddf1a 100644
--- a/src/include/gnunet_reclaim_service.h
+++ b/src/include/gnunet_reclaim_service.h
@@ -92,7 +92,21 @@ struct GNUNET_RECLAIM_Ticket
  * @param ticket the ticket
  */
 typedef void (*GNUNET_RECLAIM_TicketCallback) (
-  void *cls, const struct GNUNET_RECLAIM_Ticket *ticket);
+  void *cls,
+  const struct GNUNET_RECLAIM_Ticket *ticket);
+
+/**
+ * Method called when a token has been issued.
+ * On success returns a ticket that can be given to a relying party
+ * in order for it retrive identity attributes
+ *
+ * @param cls closure
+ * @param ticket the ticket
+ */
+typedef void (*GNUNET_RECLAIM_IssueTicketCallback) (
+  void *cls,
+  const struct GNUNET_RECLAIM_Ticket *ticket,
+  const struct GNUNET_RECLAIM_PresentationList *presentations);
 
 
 /**
@@ -113,7 +127,6 @@ typedef void (*GNUNET_RECLAIM_ContinuationWithStatus) (void *cls,
  * @param cls The callback closure
  * @param identity The identity authoritative over the attributes
  * @param attr The attribute
- * @param attestation The attestation for the attribute (may be NULL)
  */
 typedef void (*GNUNET_RECLAIM_AttributeResult) (
   void *cls, const struct GNUNET_CRYPTO_EcdsaPublicKey *identity,
@@ -125,25 +138,25 @@ typedef void (*GNUNET_RECLAIM_AttributeResult) (
  * @param cls The callback closure
  * @param identity The identity authoritative over the attributes
  * @param attr The attribute
- * @param attestation The attestation for the attribute (may be NULL)
+ * @param presentation The presentation for the credential (may be NULL)
  */
 typedef void (*GNUNET_RECLAIM_AttributeTicketResult) (
   void *cls, const struct GNUNET_CRYPTO_EcdsaPublicKey *identity,
   const struct GNUNET_RECLAIM_Attribute *attr,
-  const struct GNUNET_RECLAIM_Attestation *attestation);
+  const struct GNUNET_RECLAIM_Presentation *presentation);
 
 
 /**
- * Callback used to notify the client of attestation results.
+ * Callback used to notify the client of credential results.
  *
  * @param cls The callback closure
  * @param identity The identity authoritative over the attributes
- * @param attestation The attestation
+ * @param credential The credential
  * @param attributes the parsed attributes
  */
-typedef void (*GNUNET_RECLAIM_AttestationResult) (
+typedef void (*GNUNET_RECLAIM_CredentialResult) (
   void *cls, const struct GNUNET_CRYPTO_EcdsaPublicKey *identity,
-  const struct GNUNET_RECLAIM_Attestation *attestation);
+  const struct GNUNET_RECLAIM_Credential *credential);
 
 
 /**
@@ -178,22 +191,22 @@ GNUNET_RECLAIM_attribute_store (
 
 
 /**
-   * Store an attestation.  If the attestation is already present,
-   * it is replaced with the new attestation.
+   * Store a credential.  If the credential is already present,
+   * it is replaced with the new credential.
    *
    * @param h handle to the re:claimID service
    * @param pkey private key of the identity
-   * @param attr the attestation value
-   * @param exp_interval the relative expiration interval for the attestation
+   * @param attr the credential value
+   * @param exp_interval the relative expiration interval for the credential
    * @param cont continuation to call when done
    * @param cont_cls closure for @a cont
    * @return handle to abort the request
    */
 struct GNUNET_RECLAIM_Operation *
-GNUNET_RECLAIM_attestation_store (
+GNUNET_RECLAIM_credential_store (
   struct GNUNET_RECLAIM_Handle *h,
   const struct GNUNET_CRYPTO_EcdsaPrivateKey *pkey,
-  const struct GNUNET_RECLAIM_Attestation *attestation,
+  const struct GNUNET_RECLAIM_Credential *credential,
   const struct GNUNET_TIME_Relative *exp_interval,
   GNUNET_RECLAIM_ContinuationWithStatus cont,
   void *cont_cls);
@@ -218,21 +231,21 @@ GNUNET_RECLAIM_attribute_delete (
   GNUNET_RECLAIM_ContinuationWithStatus cont, void *cont_cls);
 
 /**
- * Delete an attestation. Tickets used to share this attestation are updated
- * accordingly.
+ * Delete a credential. Tickets used to share use a presentation of this
+ * credential are updated accordingly.
  *
  * @param h handle to the re:claimID service
  * @param pkey Private key of the identity to add an attribute to
- * @param attr The attestation
+ * @param cred The credential
  * @param cont Continuation to call when done
  * @param cont_cls Closure for @a cont
  * @return handle Used to to abort the request
  */
 struct GNUNET_RECLAIM_Operation *
-GNUNET_RECLAIM_attestation_delete (
+GNUNET_RECLAIM_credential_delete (
   struct GNUNET_RECLAIM_Handle *h,
   const struct GNUNET_CRYPTO_EcdsaPrivateKey *pkey,
-  const struct GNUNET_RECLAIM_Attestation *attr,
+  const struct GNUNET_RECLAIM_Credential *cred,
   GNUNET_RECLAIM_ContinuationWithStatus cont,
   void *cont_cls);
 
@@ -293,12 +306,12 @@ GNUNET_RECLAIM_get_attributes_stop (
 
 
 /**
- * List all attestations for a local identity.
+ * List all credentials for a local identity.
  * This MUST lock the `struct GNUNET_RECLAIM_Handle`
- * for any other calls than #GNUNET_RECLAIM_get_attestations_next() and
- * #GNUNET_RECLAIM_get_attestations_stop. @a proc will be called once
+ * for any other calls than #GNUNET_RECLAIM_get_credentials_next() and
+ * #GNUNET_RECLAIM_get_credentials_stop. @a proc will be called once
  * immediately, and then again after
- * #GNUNET_RECLAIM_get_attestations_next() is invoked.
+ * #GNUNET_RECLAIM_get_credentials_next() is invoked.
  *
  * On error (disconnect), @a error_cb will be invoked.
  * On normal completion, @a finish_cb proc will be
@@ -309,33 +322,34 @@ GNUNET_RECLAIM_get_attributes_stop (
  * @param error_cb Function to call on error (i.e. disconnect),
  *        the handle is afterwards invalid
  * @param error_cb_cls Closure for @a error_cb
- * @param proc Function to call on each attestation
+ * @param proc Function to call on each credential
  * @param proc_cls Closure for @a proc
  * @param finish_cb Function to call on completion
  *        the handle is afterwards invalid
  * @param finish_cb_cls Closure for @a finish_cb
  * @return an iterator Handle to use for iteration
  */
-struct GNUNET_RECLAIM_AttestationIterator *
-GNUNET_RECLAIM_get_attestations_start (
+struct GNUNET_RECLAIM_CredentialIterator *
+GNUNET_RECLAIM_get_credentials_start (
   struct GNUNET_RECLAIM_Handle *h,
   const struct GNUNET_CRYPTO_EcdsaPrivateKey *identity,
   GNUNET_SCHEDULER_TaskCallback error_cb,
   void *error_cb_cls,
-  GNUNET_RECLAIM_AttestationResult proc,
+  GNUNET_RECLAIM_CredentialResult proc,
   void *proc_cls,
   GNUNET_SCHEDULER_TaskCallback finish_cb,
   void *finish_cb_cls);
 
 
 /**
- * Calls the record processor specified in #GNUNET_RECLAIM_get_attestation_start
+ * Calls the record processor specified in #GNUNET_RECLAIM_get_credentials_start
  * for the next record.
  *
  * @param it the iterator
  */
 void
-GNUNET_RECLAIM_get_attestations_next (struct GNUNET_RECLAIM_AttestationIterator *ait);
+GNUNET_RECLAIM_get_credentials_next (
+                              struct GNUNET_RECLAIM_CredentialIterator *ait);
 
 
 /**
@@ -346,7 +360,8 @@ GNUNET_RECLAIM_get_attestations_next (struct GNUNET_RECLAIM_AttestationIterator
  * @param it the iterator
  */
 void
-GNUNET_RECLAIM_get_attestations_stop (struct GNUNET_RECLAIM_AttestationIterator *ait);
+GNUNET_RECLAIM_get_credentials_stop (
+                              struct GNUNET_RECLAIM_CredentialIterator *ait);
 
 
 /**
@@ -368,7 +383,7 @@ GNUNET_RECLAIM_ticket_issue (
   const struct GNUNET_CRYPTO_EcdsaPrivateKey *iss,
   const struct GNUNET_CRYPTO_EcdsaPublicKey *rp,
   const struct GNUNET_RECLAIM_AttributeList *attrs,
-  GNUNET_RECLAIM_TicketCallback cb, void *cb_cls);
+  GNUNET_RECLAIM_IssueTicketCallback cb, void *cb_cls);
 
 
 /**
diff --git a/src/include/gnunet_rest_plugin.h b/src/include/gnunet_rest_plugin.h
index 770ba66f2e58b27eea24274dff3ce36281378cef..96454f66bef03445459a87b95861cc543fe32795 100644
--- a/src/include/gnunet_rest_plugin.h
+++ b/src/include/gnunet_rest_plugin.h
@@ -69,10 +69,12 @@ struct GNUNET_REST_Plugin
    * @param data_size the length of the data
    * @param proc the callback for result
    * @param proc_cls closure for callback
+   * @return GNUNET_YES if the request was processed
    */
-  void (*process_request) (struct GNUNET_REST_RequestHandle *handle,
-                           GNUNET_REST_ResultProcessor proc,
-                           void *proc_cls);
+  enum GNUNET_GenericReturnValue (*process_request)(
+    struct GNUNET_REST_RequestHandle *handle,
+    GNUNET_REST_ResultProcessor proc,
+    void *proc_cls);
 };
 
 
diff --git a/src/include/gnunet_seti_service.h b/src/include/gnunet_seti_service.h
new file mode 100644
index 0000000000000000000000000000000000000000..c0b6f41a5f60b3b387d41c9fbc7a17fd6ddeb4fe
--- /dev/null
+++ b/src/include/gnunet_seti_service.h
@@ -0,0 +1,369 @@
+/*
+      This file is part of GNUnet
+      Copyright (C) 2013, 2014, 2020 GNUnet e.V.
+
+      GNUnet is free software: you can redistribute it and/or modify it
+      under the terms of the GNU Affero General Public License as published
+      by the Free Software Foundation, either version 3 of the License,
+      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
+      Affero General Public License for more details.
+
+      You should have received a copy of the GNU Affero General Public License
+      along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+     SPDX-License-Identifier: AGPL3.0-or-later
+ */
+/**
+ * @author Florian Dold
+ * @author Christian Grothoff
+ *
+ * @file
+ * Two-peer set intersection operations
+ *
+ * @defgroup set  Set intersection service
+ * Two-peer set operations
+ *
+ * @{
+ */
+
+#ifndef GNUNET_SETI_SERVICE_H
+#define GNUNET_SETI_SERVICE_H
+
+#ifdef __cplusplus
+extern "C"
+{
+#if 0                           /* keep Emacsens' auto-indent happy */
+}
+#endif
+#endif
+
+#include "gnunet_common.h"
+#include "gnunet_time_lib.h"
+#include "gnunet_configuration_lib.h"
+
+
+/**
+ * Maximum size of a context message for set operation requests.
+ */
+#define GNUNET_SETI_CONTEXT_MESSAGE_MAX_SIZE ((1 << 16) - 1024)
+
+/**
+ * Opaque handle to a set.
+ */
+struct GNUNET_SETI_Handle;
+
+/**
+ * Opaque handle to a set operation request from another peer.
+ */
+struct GNUNET_SETI_Request;
+
+/**
+ * Opaque handle to a listen operation.
+ */
+struct GNUNET_SETI_ListenHandle;
+
+/**
+ * Opaque handle to a set operation.
+ */
+struct GNUNET_SETI_OperationHandle;
+
+
+/**
+ * Status for the result callback
+ */
+enum GNUNET_SETI_Status
+{
+
+  /**
+   * Element should be added to the result set of the local peer, i.e. the
+   * element is in the intersection.
+   */
+  GNUNET_SETI_STATUS_ADD_LOCAL,
+
+  /**
+   * Element should be delete from the result set of the local peer, i.e. the
+   * local peer is having an element that is not in the intersection.
+   */
+  GNUNET_SETI_STATUS_DEL_LOCAL,
+
+  /**
+   * The other peer refused to do the operation with us, or something went
+   * wrong.
+   */
+  GNUNET_SETI_STATUS_FAILURE,
+
+  /**
+   * Success, all elements have been sent (and received).
+   */
+  GNUNET_SETI_STATUS_DONE
+};
+
+
+/**
+ * Element stored in a set.
+ */
+struct GNUNET_SETI_Element
+{
+  /**
+   * Number of bytes in the buffer pointed to by data.
+   */
+  uint16_t size;
+
+  /**
+   * Application-specific element type.
+   */
+  uint16_t element_type;
+
+  /**
+   * Actual data of the element
+   */
+  const void *data;
+};
+
+
+/**
+ * Possible options to pass to a set operation.
+ *
+ * Used as tag for struct #GNUNET_SETI_Option.
+ */
+enum GNUNET_SETI_OptionType
+{
+  /**
+   * List terminator.
+   */
+  GNUNET_SETI_OPTION_END = 0,
+
+  /**
+   * Return the elements remaining in the intersection
+   * (#GNUNET_SETI_STATUS_ADD_LOCAL). If not given, the default is to return a
+   * list of the elements to be removed (#GNUNET_SETI_STATUS_DEL_LOCAL).
+   */
+  GNUNET_SETI_OPTION_RETURN_INTERSECTION = 1,
+};
+
+
+/**
+ * Option for set operations.
+ */
+struct GNUNET_SETI_Option
+{
+  /**
+   * Type of the option.
+   */
+  enum GNUNET_SETI_OptionType type;
+
+  /**
+   * Value for the option, only used with some options.
+   */
+  union
+  {
+    uint64_t num;
+  } v;
+};
+
+
+/**
+ * Callback for set union operation results. Called for each element
+ * in the result set.
+ *
+ * @param cls closure
+ * @param element a result element, only valid if status is #GNUNET_SETI_STATUS_OK
+ * @param current_size current set size
+ * @param status see `enum GNUNET_SETI_Status`
+ */
+typedef void
+(*GNUNET_SETI_ResultIterator) (void *cls,
+                               const struct GNUNET_SETI_Element *element,
+                               uint64_t current_size,
+                               enum GNUNET_SETI_Status status);
+
+
+/**
+ * Called when another peer wants to do a set operation with the
+ * local peer. If a listen error occurs, the @a request is NULL.
+ *
+ * @param cls closure
+ * @param other_peer the other peer
+ * @param context_msg message with application specific information from
+ *        the other peer
+ * @param request request from the other peer (never NULL), use GNUNET_SETI_accept()
+ *        to accept it, otherwise the request will be refused
+ *        Note that we can't just return value from the listen callback,
+ *        as it is also necessary to specify the set we want to do the
+ *        operation with, whith sometimes can be derived from the context
+ *        message. It's necessary to specify the timeout.
+ */
+typedef void
+(*GNUNET_SETI_ListenCallback) (void *cls,
+                               const struct GNUNET_PeerIdentity *other_peer,
+                               const struct GNUNET_MessageHeader *context_msg,
+                               struct GNUNET_SETI_Request *request);
+
+
+/**
+ * Create an empty set, supporting the specified operation.
+ *
+ * @param cfg configuration to use for connecting to the
+ *        set service
+ * @return a handle to the set
+ */
+struct GNUNET_SETI_Handle *
+GNUNET_SETI_create (const struct GNUNET_CONFIGURATION_Handle *cfg);
+
+
+/**
+ * Add an element to the given set.
+ *
+ * @param set set to add element to
+ * @param element element to add to the set
+ * @param cb function to call when finished, can be NULL
+ * @param cb_cls closure for @a cb
+ * @return #GNUNET_OK on success, #GNUNET_SYSERR if the
+ *         set is invalid (e.g. the set service crashed)
+ */
+int
+GNUNET_SETI_add_element (struct GNUNET_SETI_Handle *set,
+                         const struct GNUNET_SETI_Element *element,
+                         GNUNET_SCHEDULER_TaskCallback cb,
+                         void *cb_cls);
+
+
+/**
+ * Destroy the set handle, and free all associated resources.  Operations may
+ * still be pending when a set is destroyed (and will be allowed to complete).
+ *
+ * @param set set to destroy
+ */
+void
+GNUNET_SETI_destroy (struct GNUNET_SETI_Handle *set);
+
+
+/**
+ * Prepare a set operation to be evaluated with another peer.  The evaluation
+ * will not start until the client provides a local set with
+ * GNUNET_SETI_commit().
+ *
+ * @param other_peer peer with the other set
+ * @param app_id hash for the application using the set
+ * @param context_msg additional information for the request
+ * @param options options to use when processing the request
+ * @param result_cb called on error or success
+ * @param result_cls closure for @a result_cb
+ * @return a handle to cancel the operation
+ */
+struct GNUNET_SETI_OperationHandle *
+GNUNET_SETI_prepare (const struct GNUNET_PeerIdentity *other_peer,
+                     const struct GNUNET_HashCode *app_id,
+                     const struct GNUNET_MessageHeader *context_msg,
+                     const struct GNUNET_SETI_Option options[],
+                     GNUNET_SETI_ResultIterator result_cb,
+                     void *result_cls);
+
+
+/**
+ * Wait for set operation requests for the given application ID.
+ * If the connection to the set service is lost, the listener is
+ * re-created transparently with exponential backoff.
+ *
+ * @param cfg configuration to use for connecting to
+ *            the set service
+ * @param app_id id of the application that handles set operation requests
+ * @param listen_cb called for each incoming request matching the operation
+ *                  and application id
+ * @param listen_cls handle for @a listen_cb
+ * @return a handle that can be used to cancel the listen operation
+ */
+struct GNUNET_SETI_ListenHandle *
+GNUNET_SETI_listen (const struct GNUNET_CONFIGURATION_Handle *cfg,
+                    const struct GNUNET_HashCode *app_id,
+                    GNUNET_SETI_ListenCallback listen_cb,
+                    void *listen_cls);
+
+
+/**
+ * Cancel the given listen operation.  After calling cancel, the
+ * listen callback for this listen handle will not be called again.
+ * Note that cancelling a listen operation will automatically reject
+ * all operations that have not yet been accepted.
+ *
+ * @param lh handle for the listen operation
+ */
+void
+GNUNET_SETI_listen_cancel (struct GNUNET_SETI_ListenHandle *lh);
+
+
+/**
+ * Accept a request we got via GNUNET_SETI_listen().  Must be called during
+ * GNUNET_SETI_listen(), as the `struct GNUNET_SETI_Request` becomes invalid
+ * afterwards.
+ * Call GNUNET_SETI_commit() to provide the local set to use for the operation,
+ * and to begin the exchange with the remote peer.
+ *
+ * @param request request to accept
+ * @param options options to use when processing the request
+ * @param result_cb callback for the results
+ * @param result_cls closure for @a result_cb
+ * @return a handle to cancel the operation
+ */
+struct GNUNET_SETI_OperationHandle *
+GNUNET_SETI_accept (struct GNUNET_SETI_Request *request,
+                    const struct GNUNET_SETI_Option options[],
+                    GNUNET_SETI_ResultIterator result_cb,
+                    void *result_cls);
+
+
+/**
+ * Commit a set to be used with a set operation.
+ * This function is called once we have fully constructed
+ * the set that we want to use for the operation.  At this
+ * time, the P2P protocol can then begin to exchange the
+ * set information and call the result callback with the
+ * result information.
+ *
+ * @param oh handle to the set operation
+ * @param set the set to use for the operation
+ * @return #GNUNET_OK on success, #GNUNET_SYSERR if the
+ *         set is invalid (e.g. the set service crashed)
+ */
+int
+GNUNET_SETI_commit (struct GNUNET_SETI_OperationHandle *oh,
+                    struct GNUNET_SETI_Handle *set);
+
+
+/**
+ * Cancel the given set operation.  May not be called after the operation's
+ * `GNUNET_SETI_ResultIterator` has been called with a status of
+ * #GNUNET_SETI_STATUS_FAILURE or #GNUNET_SETI_STATUS_DONE.
+ *
+ * @param oh set operation to cancel
+ */
+void
+GNUNET_SETI_operation_cancel (struct GNUNET_SETI_OperationHandle *oh);
+
+
+/**
+ * Hash a set element.
+ *
+ * @param element the element that should be hashed
+ * @param[out] ret_hash a pointer to where the hash of @a element
+ *        should be stored
+ */
+void
+GNUNET_SETI_element_hash (const struct GNUNET_SETI_Element *element,
+                          struct GNUNET_HashCode *ret_hash);
+
+
+#if 0                           /* keep Emacsens' auto-indent happy */
+{
+#endif
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
+/** @} */  /* end of group */
diff --git a/src/include/gnunet_setu_service.h b/src/include/gnunet_setu_service.h
new file mode 100644
index 0000000000000000000000000000000000000000..634c5c40b546e807b28e87be7e3b2474607db60e
--- /dev/null
+++ b/src/include/gnunet_setu_service.h
@@ -0,0 +1,390 @@
+/*
+      This file is part of GNUnet
+      Copyright (C) 2013, 2014, 2020 GNUnet e.V.
+
+      GNUnet is free software: you can redistribute it and/or modify it
+      under the terms of the GNU Affero General Public License as published
+      by the Free Software Foundation, either version 3 of the License,
+      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
+      Affero General Public License for more details.
+
+      You should have received a copy of the GNU Affero General Public License
+      along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+     SPDX-License-Identifier: AGPL3.0-or-later
+ */
+/**
+ * @author Florian Dold
+ * @author Christian Grothoff
+ *
+ * @file
+ * Two-peer set union operations
+ *
+ * @defgroup set  Set union service
+ * Two-peer set operations
+ *
+ * @{
+ */
+
+#ifndef GNUNET_SETU_SERVICE_H
+#define GNUNET_SETU_SERVICE_H
+
+#ifdef __cplusplus
+extern "C"
+{
+#if 0                           /* keep Emacsens' auto-indent happy */
+}
+#endif
+#endif
+
+#include "gnunet_common.h"
+#include "gnunet_time_lib.h"
+#include "gnunet_configuration_lib.h"
+
+
+/**
+ * Maximum size of a context message for set operation requests.
+ */
+#define GNUNET_SETU_CONTEXT_MESSAGE_MAX_SIZE ((1 << 16) - 1024)
+
+/**
+ * Opaque handle to a set.
+ */
+struct GNUNET_SETU_Handle;
+
+/**
+ * Opaque handle to a set operation request from another peer.
+ */
+struct GNUNET_SETU_Request;
+
+/**
+ * Opaque handle to a listen operation.
+ */
+struct GNUNET_SETU_ListenHandle;
+
+/**
+ * Opaque handle to a set operation.
+ */
+struct GNUNET_SETU_OperationHandle;
+
+
+/**
+ * Status for the result callback
+ */
+enum GNUNET_SETU_Status
+{
+
+  /**
+   * Element should be added to the result set of the local peer, i.e. the
+   * local peer is missing an element.
+   */
+  GNUNET_SETU_STATUS_ADD_LOCAL,
+
+  /**
+   * Element should be added to the result set of the remote peer, i.e. the
+   * remote peer is missing an element. Only used if
+   * #GNUNET_SETU_OPTION_SYMMETRIC is set.
+   */
+  GNUNET_SETU_STATUS_ADD_REMOTE,
+
+  /**
+   * The other peer refused to do the operation with us, or something went
+   * wrong.
+   */
+  GNUNET_SETU_STATUS_FAILURE,
+
+  /**
+   * Success, all elements have been sent (and received).
+   */
+  GNUNET_SETU_STATUS_DONE
+};
+
+
+/**
+ * Element stored in a set.
+ */
+struct GNUNET_SETU_Element
+{
+  /**
+   * Number of bytes in the buffer pointed to by data.
+   */
+  uint16_t size;
+
+  /**
+   * Application-specific element type.
+   */
+  uint16_t element_type;
+
+  /**
+   * Actual data of the element
+   */
+  const void *data;
+};
+
+
+/**
+ * Possible options to pass to a set operation.
+ *
+ * Used as tag for struct #GNUNET_SETU_Option.
+ */
+enum GNUNET_SETU_OptionType
+{
+  /**
+   * List terminator.
+   */
+  GNUNET_SETU_OPTION_END=0,
+
+  /**
+   * Fail set operations when the other peer shows weird behavior
+   * that might by a Byzantine fault.
+   *
+   * For set union, 'v.num' is a lower bound on elements that the other peer
+   * must have in common with us.
+   */
+  GNUNET_SETU_OPTION_BYZANTINE=1,
+
+  /**
+   * Do not use the optimized set operation, but send full sets.  Might
+   * trigger Byzantine fault detection.
+   */
+  GNUNET_SETU_OPTION_FORCE_FULL=2,
+
+  /**
+   * Only use optimized set operations, even though for this particular set
+   * operation they might be much slower.  Might trigger Byzantine fault
+   * detection.
+   */
+  GNUNET_SETU_OPTION_FORCE_DELTA=4,
+
+  /**
+   * Notify client also if we are sending a value to the other peer.
+   */
+  GNUNET_SETU_OPTION_SYMMETRIC = 8
+};
+
+
+/**
+ * Option for set operations.
+ */
+struct GNUNET_SETU_Option
+{
+  /**
+   * Type of the option.
+   */
+  enum GNUNET_SETU_OptionType type;
+
+  /**
+   * Value for the option, only used with some options.
+   */
+  union
+  {
+    uint64_t num;
+  } v;
+};
+
+
+/**
+ * Callback for set union operation results. Called for each element
+ * in the result set.
+ *
+ * @param cls closure
+ * @param element a result element, only valid if status is #GNUNET_SETU_STATUS_OK
+ * @param current_size current set size
+ * @param status see `enum GNUNET_SETU_Status`
+ */
+typedef void
+(*GNUNET_SETU_ResultIterator) (void *cls,
+                               const struct GNUNET_SETU_Element *element,
+                               uint64_t current_size,
+                               enum GNUNET_SETU_Status status);
+
+
+/**
+ * Called when another peer wants to do a set operation with the
+ * local peer. If a listen error occurs, the @a request is NULL.
+ *
+ * @param cls closure
+ * @param other_peer the other peer
+ * @param context_msg message with application specific information from
+ *        the other peer
+ * @param request request from the other peer (never NULL), use GNUNET_SETU_accept()
+ *        to accept it, otherwise the request will be refused
+ *        Note that we can't just return value from the listen callback,
+ *        as it is also necessary to specify the set we want to do the
+ *        operation with, whith sometimes can be derived from the context
+ *        message. It's necessary to specify the timeout.
+ */
+typedef void
+(*GNUNET_SETU_ListenCallback) (void *cls,
+                               const struct GNUNET_PeerIdentity *other_peer,
+                               const struct GNUNET_MessageHeader *context_msg,
+                               struct GNUNET_SETU_Request *request);
+
+
+/**
+ * Create an empty set, supporting the specified operation.
+ *
+ * @param cfg configuration to use for connecting to the
+ *        set service
+ * @return a handle to the set
+ */
+struct GNUNET_SETU_Handle *
+GNUNET_SETU_create (const struct GNUNET_CONFIGURATION_Handle *cfg);
+
+
+/**
+ * Add an element to the given set.
+ *
+ * @param set set to add element to
+ * @param element element to add to the set
+ * @param cb function to call when finished, can be NULL
+ * @param cb_cls closure for @a cb
+ * @return #GNUNET_OK on success, #GNUNET_SYSERR if the
+ *         set is invalid (e.g. the set service crashed)
+ */
+int
+GNUNET_SETU_add_element (struct GNUNET_SETU_Handle *set,
+                         const struct GNUNET_SETU_Element *element,
+                         GNUNET_SCHEDULER_TaskCallback cb,
+                         void *cb_cls);
+
+
+/**
+ * Destroy the set handle, and free all associated resources.  Operations may
+ * still be pending when a set is destroyed (and will be allowed to complete).
+ *
+ * @param set set to destroy
+ */
+void
+GNUNET_SETU_destroy (struct GNUNET_SETU_Handle *set);
+
+
+/**
+ * Prepare a set operation to be evaluated with another peer.  The evaluation
+ * will not start until the client provides a local set with
+ * GNUNET_SETU_commit().
+ *
+ * @param other_peer peer with the other set
+ * @param app_id hash for the application using the set
+ * @param context_msg additional information for the request
+ * @param options options to use when processing the request
+ * @param result_cb called on error or success
+ * @param result_cls closure for @a result_cb
+ * @return a handle to cancel the operation
+ */
+struct GNUNET_SETU_OperationHandle *
+GNUNET_SETU_prepare (const struct GNUNET_PeerIdentity *other_peer,
+                     const struct GNUNET_HashCode *app_id,
+                     const struct GNUNET_MessageHeader *context_msg,
+                     const struct GNUNET_SETU_Option options[],
+                     GNUNET_SETU_ResultIterator result_cb,
+                     void *result_cls);
+
+
+/**
+ * Wait for set operation requests for the given application ID.
+ * If the connection to the set service is lost, the listener is
+ * re-created transparently with exponential backoff.
+ *
+ * @param cfg configuration to use for connecting to
+ *            the set service
+ * @param app_id id of the application that handles set operation requests
+ * @param listen_cb called for each incoming request matching the operation
+ *                  and application id
+ * @param listen_cls handle for @a listen_cb
+ * @return a handle that can be used to cancel the listen operation
+ */
+struct GNUNET_SETU_ListenHandle *
+GNUNET_SETU_listen (const struct GNUNET_CONFIGURATION_Handle *cfg,
+                    const struct GNUNET_HashCode *app_id,
+                    GNUNET_SETU_ListenCallback listen_cb,
+                    void *listen_cls);
+
+
+/**
+ * Cancel the given listen operation.  After calling cancel, the
+ * listen callback for this listen handle will not be called again.
+ * Note that cancelling a listen operation will automatically reject
+ * all operations that have not yet been accepted.
+ *
+ * @param lh handle for the listen operation
+ */
+void
+GNUNET_SETU_listen_cancel (struct GNUNET_SETU_ListenHandle *lh);
+
+
+/**
+ * Accept a request we got via GNUNET_SETU_listen().  Must be called during
+ * GNUNET_SETU_listen(), as the `struct GNUNET_SETU_Request` becomes invalid
+ * afterwards.
+ * Call GNUNET_SETU_commit() to provide the local set to use for the operation,
+ * and to begin the exchange with the remote peer.
+ *
+ * @param request request to accept
+ * @param options options to use when processing the request
+ * @param result_cb callback for the results
+ * @param result_cls closure for @a result_cb
+ * @return a handle to cancel the operation
+ */
+struct GNUNET_SETU_OperationHandle *
+GNUNET_SETU_accept (struct GNUNET_SETU_Request *request,
+                    const struct GNUNET_SETU_Option options[],
+                    GNUNET_SETU_ResultIterator result_cb,
+                    void *result_cls);
+
+
+/**
+ * Commit a set to be used with a set operation.
+ * This function is called once we have fully constructed
+ * the set that we want to use for the operation.  At this
+ * time, the P2P protocol can then begin to exchange the
+ * set information and call the result callback with the
+ * result information.
+ *
+ * @param oh handle to the set operation
+ * @param set the set to use for the operation
+ * @return #GNUNET_OK on success, #GNUNET_SYSERR if the
+ *         set is invalid (e.g. the set service crashed)
+ */
+int
+GNUNET_SETU_commit (struct GNUNET_SETU_OperationHandle *oh,
+                    struct GNUNET_SETU_Handle *set);
+
+
+/**
+ * Cancel the given set operation.  May not be called after the operation's
+ * `GNUNET_SETU_ResultIterator` has been called with a status of
+ * #GNUNET_SETU_STATUS_FAILURE or #GNUNET_SETU_STATUS_DONE.
+ *
+ * @param oh set operation to cancel
+ */
+void
+GNUNET_SETU_operation_cancel (struct GNUNET_SETU_OperationHandle *oh);
+
+
+/**
+ * Hash a set element.
+ *
+ * @param element the element that should be hashed
+ * @param[out] ret_hash a pointer to where the hash of @a element
+ *        should be stored
+ */
+void
+GNUNET_SETU_element_hash (const struct GNUNET_SETU_Element *element,
+                          struct GNUNET_HashCode *ret_hash);
+
+
+#if 0                           /* keep Emacsens' auto-indent happy */
+{
+#endif
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
+/** @} */  /* end of group */
diff --git a/src/include/gnunet_signatures.h b/src/include/gnunet_signatures.h
index 5031137701498ffe405636eee9bd90703b4084c7..7c0c1d104e625a9cb9f9fd2d45076a89e5f492c0 100644
--- a/src/include/gnunet_signatures.h
+++ b/src/include/gnunet_signatures.h
@@ -246,6 +246,11 @@ extern "C"
  */
 #define GNUNET_SIGNATURE_PURPOSE_CADET_CONNECTION_INITIATOR 38
 
+/**
+ * Signature by a peer sending back the nonce received at initial handshake.
+ */
+#define GNUNET_SIGNATURE_COMMUNICATOR_TCP_HANDSHAKE_ACK 39
+
 #if 0                           /* keep Emacsens' auto-indent happy */
 {
 #endif
diff --git a/src/include/gnunet_strings_lib.h b/src/include/gnunet_strings_lib.h
index 663b44194749a70018a51575d538a18aa9832055..8d829d42e12cc74b87ebe047a44fc0df449c8644 100644
--- a/src/include/gnunet_strings_lib.h
+++ b/src/include/gnunet_strings_lib.h
@@ -349,6 +349,18 @@ GNUNET_STRINGS_base64_encode (const void *in,
                               char **output);
 
 
+/**
+ * url/percent encode (RFC3986).
+ *
+ * @param data the data to decode
+ * @param len the length of the input
+ * @param output where to write the output (*output should be NULL,
+ *   is allocated)
+ * @return the size of the output
+ */
+size_t
+GNUNET_STRINGS_urlencode (const char *data, size_t len, char **out);
+
 /**
  * Encode into Base64url. RFC7515
  *
@@ -389,6 +401,18 @@ GNUNET_STRINGS_base64_decode (const char *data,
 size_t
 GNUNET_STRINGS_base64url_decode (const char *data, size_t len, void **out);
 
+/**
+ * url/percent encode (RFC3986).
+ *
+ * @param data the data to encode
+ * @param len the length of the input
+ * @param output where to write the output (*output should be NULL,
+ *   is allocated)
+ * @return the size of the output
+ */
+size_t
+GNUNET_STRINGS_urldecode (const char *data, size_t len, char **out);
+
 
 /**
  * Convert a peer path to a human-readable string.
diff --git a/src/include/gnunet_transport_communication_service.h b/src/include/gnunet_transport_communication_service.h
index ea6b95e2ddaedf4e33b9750ddcb39f4abe74df3d..431b9a67153cbbdef406cc6ddaefa563e134399a 100644
--- a/src/include/gnunet_transport_communication_service.h
+++ b/src/include/gnunet_transport_communication_service.h
@@ -336,6 +336,14 @@ void
 GNUNET_TRANSPORT_communicator_address_remove (
   struct GNUNET_TRANSPORT_AddressIdentifier *ai);
 
+/**
+ * Notify transport service that this communicator no longer provides all its addresses for this peer.
+ *
+ * @param ch The communicator handle.
+ */
+void
+GNUNET_TRANSPORT_communicator_address_remove_all (
+                                                  struct GNUNET_TRANSPORT_CommunicatorHandle *ch);
 
 /**
  * The communicator asks the transport service to route a message via
diff --git a/src/include/gnunet_uri_lib.h b/src/include/gnunet_uri_lib.h
new file mode 100644
index 0000000000000000000000000000000000000000..d428bdd9ac19a4741e1606085fb3b024b7b7556d
--- /dev/null
+++ b/src/include/gnunet_uri_lib.h
@@ -0,0 +1,122 @@
+/**
+ * Copyright (C) 2016 Jack Engqvist Johansson
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+#ifndef GNUNET_URI_LIB_H
+#define GNUNET_URI_LIB_H
+
+
+/**
+ * The struct where the parsed values will be stored:
+ *
+ * scheme ":" [ "//" ] [ username ":" password "@" ] host [ ":" port ] [ "/" ] [ path ] [ "?" query ]
+ *
+ * Note: to make sure that no strings are copied, the first slash "/" in the
+ * path will be used to null terminate the hostname if no port is supplied.
+ */
+struct GNUNET_Uri {
+  char *scheme; /* scheme, without ":" and "//" */
+  char *username; /* username, default: NULL */
+  char *password; /* password, default: NULL */
+  char *host; /* hostname or IP address */
+  int port; /* port, default: 0 */
+  char *path; /* path, without leading "/", default: NULL */
+  char *query; /* query, default: NULL */
+  char *fragment; /* fragment, default: NULL */
+};
+
+
+/* A struct to hold the query string parameter values. */
+struct GNUNET_UriParam {
+  char *key;
+  char *val;
+};
+
+
+/**
+ * Parse a URL to a struct.
+ *
+ * The URL string should be in one of the following formats:
+ *
+ * Absolute URL:
+ * scheme ":" [ "//" ] [ username ":" password "@" ] host [ ":" port ] [ "/" ] [ path ] [ "?" query ] [ "#" fragment ]
+ *
+ * Relative URL:
+ * path [ "?" query ] [ "#" fragment ]
+ *
+ * The following parts will be parsed to the corresponding struct member.
+ *
+ * *url:     a pointer to the struct where to store the parsed values.
+ * *url_str: a pointer to the url to be parsed (null terminated). The string
+ *           will be modified.
+ *
+ * Returns 0 on success, otherwise -1.
+ */
+int
+GNUNET_uri_parse (struct GNUNET_Uri *url,
+                  char *url_str);
+
+
+/**
+ * Split a path into several strings.
+ *
+ * No data is copied, the slashed are used as null terminators and then
+ * pointers to each path part will be stored in **parts. Double slashes will be
+ * treated as one.
+ *
+ * *path:     the path to split. The string will be modified.
+ * **parts:   a pointer to an array of (char *) where to store the result.
+ * max_parts: max number of parts to parse.
+ *
+ * Returns the number of parsed items. -1 on error.
+ */
+int
+GNUNET_uri_split_path (char *path,
+                       char **parts,
+                       int max_parts);
+
+
+/**
+ * Parse a query string into a key/value struct.
+ *
+ * The query string should be a null terminated string of parameters separated by
+ * a delimiter. Each parameter are checked for the equal sign character. If it
+ * appears in the parameter, it will be used as a null terminator and the part
+ * that comes after it will be the value of the parameter.
+ *
+ * No data are copied, the equal sign and delimiters are used as null
+ * terminators and then pointers to each parameter key and value will be stored
+ * in the yuarel_param struct.
+ *
+ * *query:     the query string to parse. The string will be modified.
+ * delimiter:  the character that separates the key/value pairs from eachother.
+ * *params:    an array of (struct yuarel_param) where to store the result.
+ * max_values: max number of parameters to parse.
+ *
+ * Returns the number of parsed items. -1 on error.
+ */
+int
+GNUNET_uri_parse_query (char *query,
+                        char delimiter,
+                        struct GNUNET_UriParam *params,
+                        int max_params);
+
+
+#endif /* GNUNET_URI_LIB_H */
diff --git a/src/include/platform.h b/src/include/platform.h
index baaf26ad6bcaf3f331c622c49afaca1afb95eb32..10248e5bba1fdcb7b6e0d15ce1f1f5dfadc839c9 100644
--- a/src/include/platform.h
+++ b/src/include/platform.h
@@ -233,8 +233,8 @@ atoll (const char *nptr);
 
 
 #if defined(__sparc__)
-#define MAKE_UNALIGNED(val) ({ __typeof__((val))__tmp; memmove (&__tmp, &(val), \
-                                                                sizeof((val))); \
+#define MAKE_UNALIGNED(val) ({ __typeof__((val)) __tmp; memmove (&__tmp, &(val), \
+                                                                 sizeof((val))); \
                                __tmp; })
 #else
 #define MAKE_UNALIGNED(val) val
diff --git a/src/integration-tests/.gitignore b/src/integration-tests/.gitignore
new file mode 100644
index 0000000000000000000000000000000000000000..46915b2a4f2bb9c599de0c760f00587e7cf2bbe1
--- /dev/null
+++ b/src/integration-tests/.gitignore
@@ -0,0 +1,10 @@
+gnunet_testing.py
+gnunet_pyexpect.py
+gnunet_pyexpect.pyc
+gnunet_testing.pyc
+test_integration_bootstrap_and_connect.py
+test_integration_clique.py
+test_integration_disconnect_nat.py
+test_integration_disconnect.py
+test_integration_reconnect_nat.py
+test_integration_reconnect.py
diff --git a/src/json/.gitignore b/src/json/.gitignore
new file mode 100644
index 0000000000000000000000000000000000000000..347bffd7b226a5ad22fb897a35e1e46d560cdf66
--- /dev/null
+++ b/src/json/.gitignore
@@ -0,0 +1,2 @@
+test_json
+test_json_mhd
diff --git a/src/json/json.c b/src/json/json.c
index f6d2406c4137f48a9fe02d2229eed98e0f2c684b..0631c51bb442ebdafa11b7598f4bbedcbb0bf65a 100644
--- a/src/json/json.c
+++ b/src/json/json.c
@@ -41,7 +41,7 @@
  * @param[out] which index into @a spec did we encounter an error
  * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
  */
-int
+enum GNUNET_GenericReturnValue
 GNUNET_JSON_parse (const json_t *root,
                    struct GNUNET_JSON_Specification *spec,
                    const char **error_json_name,
diff --git a/src/json/json_generator.c b/src/json/json_generator.c
index 594fcaf273786679f71c23e6dbf8574b13f3c6c4..3f82a5f17bc1800b34caf0892943f3ddc9fc24d6 100644
--- a/src/json/json_generator.c
+++ b/src/json/json_generator.c
@@ -254,7 +254,9 @@ GNUNET_JSON_from_gnsrecord (const char*rname,
       rel_exp.rel_value_us = rd[i].expiration_time;
       expiration_time_str = GNUNET_STRINGS_relative_time_to_string (rel_exp,
                                                                     GNUNET_NO);
-    } else {
+    }
+    else
+    {
       abs_exp.abs_value_us = rd[i].expiration_time;
       expiration_time_str = GNUNET_STRINGS_absolute_time_to_string (abs_exp);
     }
diff --git a/src/json/json_gnsrecord.c b/src/json/json_gnsrecord.c
index fe5858f0680512346efbec61dad9bd530ed0a353..7e11aba945df86afccbc48ed6207a28969561426 100644
--- a/src/json/json_gnsrecord.c
+++ b/src/json/json_gnsrecord.c
@@ -136,8 +136,8 @@ parse_record (json_t *data, struct GNUNET_GNSRECORD_Data *rd)
   }
   else if ((1 != rel_exp) &&
            (GNUNET_OK ==
-           GNUNET_STRINGS_fancy_time_to_absolute (expiration_time,
-                                                  &abs_expiration_time)))
+            GNUNET_STRINGS_fancy_time_to_absolute (expiration_time,
+                                                   &abs_expiration_time)))
   {
     rd->expiration_time = abs_expiration_time.abs_value_us;
   }
diff --git a/src/my/.gitignore b/src/my/.gitignore
new file mode 100644
index 0000000000000000000000000000000000000000..3338ba2ea7e1942e269f342bde5e45296f6e029a
--- /dev/null
+++ b/src/my/.gitignore
@@ -0,0 +1 @@
+test_my
diff --git a/src/mysql/mysql.c b/src/mysql/mysql.c
index 7132270686d869d154727c0fcf5686c1b4d6dc4c..e20debc820e1398b05fef5ab968d6703e1cda5e3 100644
--- a/src/mysql/mysql.c
+++ b/src/mysql/mysql.c
@@ -220,7 +220,7 @@ iopen (struct GNUNET_MYSQL_Context *mc)
   char *mysql_user;
   char *mysql_password;
   unsigned long long mysql_port;
-  my_bool reconnect;
+  MYSQL_BOOL reconnect;
   unsigned int timeout;
 
   mc->dbf = mysql_init (NULL);
diff --git a/src/namecache/.gitignore b/src/namecache/.gitignore
new file mode 100644
index 0000000000000000000000000000000000000000..2abc07dfb1a0f74dfdf82ee0a510c79ee9b072ef
--- /dev/null
+++ b/src/namecache/.gitignore
@@ -0,0 +1,7 @@
+gnunet-service-namecache
+gnunet-namecache
+test_namecache_api_cache_block
+test_plugin_namecache_postgres
+test_plugin_namecache_sqlite
+zonefiles
+test_plugin_namecache_flat
diff --git a/src/namestore/.gitignore b/src/namestore/.gitignore
new file mode 100644
index 0000000000000000000000000000000000000000..f159cdaff34283e8c4fd23f381791eff4f244eac
--- /dev/null
+++ b/src/namestore/.gitignore
@@ -0,0 +1,88 @@
+gnunet-service-namestore
+gnunet-namestore
+gnunet-namestore-fcfsd
+test_namestore_api_lookup_nick.nc
+test_namestore_api_lookup_private.nc
+test_namestore_api_lookup_public.nc
+test_namestore_api_lookup_shadow.nc
+test_namestore_api_lookup_shadow_filter.nc
+test_namestore_api_monitoring.nc
+test_namestore_api_monitoring_existing.nc
+test_namestore_api_remove.nc
+test_namestore_api_remove_not_existing_record.nc
+test_namestore_api_store.nc
+test_namestore_api_store_update.nc
+test_namestore_api_zone_iteration.nc
+test_namestore_api_zone_iteration_nick.nc
+test_namestore_api_zone_iteration_specific_zone.nc
+test_namestore_api_zone_iteration_stop.nc
+test_plugin_namestore_postgres
+test_plugin_namestore_sqlite
+test_plugin_namestore_flat
+gnunet-zoneimport
+test_namestore_api_lookup_nick_flat
+test_namestore_api_lookup_nick_postgres
+test_namestore_api_lookup_nick_sqlite
+test_namestore_api_lookup_private_flat
+test_namestore_api_lookup_private_postgres
+test_namestore_api_lookup_private_sqlite
+test_namestore_api_lookup_public_flat
+test_namestore_api_lookup_public_postgres
+test_namestore_api_lookup_public_sqlite
+test_namestore_api_lookup_shadow_filter_flat
+test_namestore_api_lookup_shadow_filter_postgres
+test_namestore_api_lookup_shadow_filter_sqlite
+test_namestore_api_lookup_shadow_flat
+test_namestore_api_lookup_shadow_postgres
+test_namestore_api_lookup_shadow_sqlite
+test_namestore_api_monitoring_existing_flat
+test_namestore_api_monitoring_existing_postgres
+test_namestore_api_monitoring_existing_sqlite
+test_namestore_api_monitoring_flat
+test_namestore_api_monitoring_postgres
+test_namestore_api_monitoring_sqlite
+test_namestore_api_remove_flat
+test_namestore_api_remove_not_existing_record_flat
+test_namestore_api_remove_not_existing_record_postgres
+test_namestore_api_remove_not_existing_record_sqlite
+test_namestore_api_remove_postgres
+test_namestore_api_remove_sqlite
+test_namestore_api_store_flat
+test_namestore_api_store_postgres
+test_namestore_api_store_sqlite
+test_namestore_api_store_update_flat
+test_namestore_api_store_update_postgres
+test_namestore_api_store_update_sqlite
+test_namestore_api_zone_iteration_flat
+test_namestore_api_zone_iteration_nick_flat
+test_namestore_api_zone_iteration_nick_postgres
+test_namestore_api_zone_iteration_nick_sqlite
+test_namestore_api_zone_iteration_postgres
+test_namestore_api_zone_iteration_specific_zone_flat
+test_namestore_api_zone_iteration_specific_zone_postgres
+test_namestore_api_zone_iteration_specific_zone_sqlite
+test_namestore_api_zone_iteration_sqlite
+test_namestore_api_zone_iteration_stop_flat
+test_namestore_api_zone_iteration_stop_postgres
+test_namestore_api_zone_iteration_stop_sqlite
+test_namestore_api_zone_to_name_flat
+test_namestore_api_zone_to_name_postgres
+test_namestore_api_zone_to_name_sqlite
+test_namestore_api_lookup_nick_flat
+test_namestore_api_lookup_private_flat
+test_namestore_api_lookup_public_flat
+test_namestore_api_lookup_shadow_filter_flat
+test_namestore_api_lookup_shadow_flat
+test_namestore_api_monitoring_existing_flat
+test_namestore_api_monitoring_flat
+test_namestore_api_remove_flat
+test_namestore_api_remove_not_existing_record_flat
+test_namestore_api_store_flat
+test_namestore_api_store_update_flat
+test_namestore_api_zone_iteration_flat
+test_namestore_api_zone_iteration_nick_flat
+test_namestore_api_zone_iteration_specific_zone_flat
+test_namestore_api_zone_iteration_stop_flat
+test_namestore_api_zone_to_name_flat
+test_plugin_namestore_flat
+perf_namestore_api_zone_iteration_flat
diff --git a/src/namestore/gnunet-namestore.c b/src/namestore/gnunet-namestore.c
index 704a4abf79e062f0df124dcb36e3839b12fd6f16..07d045b907935ec08a0156a9a22160d7814ccf46 100644
--- a/src/namestore/gnunet-namestore.c
+++ b/src/namestore/gnunet-namestore.c
@@ -1048,7 +1048,8 @@ run_with_zone_pkey (const struct GNUNET_CONFIGURATION_Handle *cfg)
       return;
     }
     add = 1;
-    typestring = GNUNET_strdup (GNUNET_GNSRECORD_number_to_typename (GNUNET_GNSRECORD_TYPE_NICK));
+    typestring = GNUNET_strdup (GNUNET_GNSRECORD_number_to_typename (
+                                  GNUNET_GNSRECORD_TYPE_NICK));
     name = GNUNET_strdup (GNUNET_GNS_EMPTY_LABEL_AT);
     value = GNUNET_strdup (nickstring);
     is_public = 0;
diff --git a/src/namestore/gnunet-service-namestore.c b/src/namestore/gnunet-service-namestore.c
index ede566d405fff2fc9400695098f1a09f55bb83cb..b24bb2952be4d35d75215bbb210c5c6491253b67 100644
--- a/src/namestore/gnunet-service-namestore.c
+++ b/src/namestore/gnunet-service-namestore.c
@@ -915,7 +915,7 @@ refresh_block (struct NamestoreClient *nc,
   nick = get_nick_record (zone_key);
   res_count = rd_count;
   res = (struct GNUNET_GNSRECORD_Data *) rd;  /* fixme: a bit unclean... */
-  if (NULL != nick  && (0 != strcmp (name, GNUNET_GNS_EMPTY_LABEL_AT)))
+  if ((NULL != nick) && (0 != strcmp (name, GNUNET_GNS_EMPTY_LABEL_AT)))
   {
     nick->flags =
       (nick->flags | GNUNET_GNSRECORD_RF_PRIVATE) ^ GNUNET_GNSRECORD_RF_PRIVATE;
@@ -1809,7 +1809,7 @@ run_zone_iteration_round (struct ZoneIteration *zi, uint64_t limit)
   start = GNUNET_TIME_absolute_get ();
   GNUNET_break (GNUNET_SYSERR !=
                 GSN_database->iterate_records (GSN_database->cls,
-                                               (0 == GNUNET_is_zero (&zi->zone))
+                                               (GNUNET_YES == GNUNET_is_zero (&zi->zone))
                                                ? NULL
                                                : &zi->zone,
                                                zi->seq,
@@ -2083,7 +2083,7 @@ monitor_iteration_next (void *cls)
   else
     zm->iteration_cnt = zm->limit; /* use it all */
   ret = GSN_database->iterate_records (GSN_database->cls,
-                                       (0 == GNUNET_is_zero (&zm->zone))
+                                       (GNUNET_YES == GNUNET_is_zero (&zm->zone))
                                        ? NULL
                                        : &zm->zone,
                                        zm->seq,
diff --git a/src/namestore/namestore_api.c b/src/namestore/namestore_api.c
index 2a085cf0413069360fdc019f70e459b79ea445d2..f383f8b4a76cafe3255c55e717b215abd7d6f207 100644
--- a/src/namestore/namestore_api.c
+++ b/src/namestore/namestore_api.c
@@ -373,6 +373,8 @@ handle_record_store_response (void *cls,
     emsg = _ ("Namestore failed to store record\n");
   else
     emsg = NULL;
+  if (NULL == qe)
+    return;
   if (NULL != qe->cont)
     qe->cont (qe->cont_cls, res, emsg);
   free_qe (qe);
diff --git a/src/namestore/namestore_api_monitor.c b/src/namestore/namestore_api_monitor.c
index ab61403281ed04f3d0a363dec0eb49f9df1499b9..9dc955544d2bd1e68a0316796233eabee26abc17 100644
--- a/src/namestore/namestore_api_monitor.c
+++ b/src/namestore/namestore_api_monitor.c
@@ -139,7 +139,7 @@ check_result (void *cls, const struct RecordResultMessage *lrm)
 
   (void) cls;
   if ((0 != GNUNET_memcmp (&lrm->private_key, &zm->zone)) &&
-      (0 != GNUNET_is_zero (&zm->zone)))
+      (GNUNET_NO == GNUNET_is_zero (&zm->zone)))
   {
     GNUNET_break (0);
     return GNUNET_SYSERR;
diff --git a/src/namestore/plugin_rest_namestore.c b/src/namestore/plugin_rest_namestore.c
index 4a05b2833a55ce1ca4475e8e370afadaefc5fbd8..9354b98962f31395daad5b87de0f53b35316b97d 100644
--- a/src/namestore/plugin_rest_namestore.c
+++ b/src/namestore/plugin_rest_namestore.c
@@ -84,6 +84,31 @@ const struct GNUNET_CONFIGURATION_Handle *cfg;
  */
 static char *allow_methods;
 
+/**
+ * Ego list
+ */
+static struct EgoEntry *ego_head;
+
+/**
+ * Ego list
+ */
+static struct EgoEntry *ego_tail;
+
+/**
+ * The processing state
+ */
+static int state;
+
+/**
+ * Handle to NAMESTORE
+ */
+static struct GNUNET_NAMESTORE_Handle *ns_handle;
+
+/**
+ * Handle to Identity service.
+ */
+static struct GNUNET_IDENTITY_Handle *identity_handle;
+
 /**
  * @brief struct returned by the initialization function of the plugin
  */
@@ -135,6 +160,16 @@ enum UpdateStrategy
  */
 struct RequestHandle
 {
+  /**
+   * DLL
+   */
+  struct RequestHandle *next;
+
+  /**
+   * DLL
+   */
+  struct RequestHandle *prev;
+
   /**
    * Records to store
    */
@@ -170,15 +205,6 @@ struct RequestHandle
    */
   json_t *resp_object;
 
-  /**
-   * The processing state
-   */
-  int state;
-
-  /**
-   * Handle to NAMESTORE
-   */
-  struct GNUNET_NAMESTORE_Handle *ns_handle;
 
   /**
    * Handle to NAMESTORE it
@@ -195,26 +221,11 @@ struct RequestHandle
    */
   struct EgoEntry *ego_entry;
 
-  /**
-   * Ego list
-   */
-  struct EgoEntry *ego_head;
-
-  /**
-   * Ego list
-   */
-  struct EgoEntry *ego_tail;
-
   /**
    * IDENTITY Operation
    */
   struct GNUNET_IDENTITY_Operation *op;
 
-  /**
-   * Handle to Identity service.
-   */
-  struct GNUNET_IDENTITY_Handle *identity_handle;
-
   /**
    * Rest connection
    */
@@ -256,6 +267,17 @@ struct RequestHandle
   int response_code;
 };
 
+/**
+ * DLL
+ */
+static struct RequestHandle *requests_head;
+
+/**
+ * DLL
+ */
+static struct RequestHandle *requests_tail;
+
+
 /**
  * Cleanup lookup handle
  * @param handle Handle to clean up
@@ -264,8 +286,6 @@ static void
 cleanup_handle (void *cls)
 {
   struct RequestHandle *handle = cls;
-  struct EgoEntry *ego_entry;
-  struct EgoEntry *ego_tmp;
 
   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Cleaning up\n");
   if (NULL != handle->timeout_task)
@@ -294,27 +314,14 @@ cleanup_handle (void *cls)
     GNUNET_NAMESTORE_zone_iteration_stop (handle->list_it);
   if (NULL != handle->ns_qe)
     GNUNET_NAMESTORE_cancel (handle->ns_qe);
-  if (NULL != handle->identity_handle)
-    GNUNET_IDENTITY_disconnect (handle->identity_handle);
-  if (NULL != handle->ns_handle)
-  {
-    GNUNET_NAMESTORE_disconnect (handle->ns_handle);
-  }
-
-  for (ego_entry = handle->ego_head; NULL != ego_entry;)
-  {
-    ego_tmp = ego_entry;
-    ego_entry = ego_entry->next;
-    GNUNET_free (ego_tmp->identifier);
-    GNUNET_free (ego_tmp->keystring);
-    GNUNET_free (ego_tmp);
-  }
 
   if (NULL != handle->resp_object)
   {
     json_decref (handle->resp_object);
   }
-
+  GNUNET_CONTAINER_DLL_remove (requests_head,
+                               requests_tail,
+                               handle);
   GNUNET_free (handle);
 }
 
@@ -345,7 +352,7 @@ do_error (void *cls)
   handle->proc (handle->proc_cls, resp, handle->response_code);
   json_decref (json_error);
   GNUNET_free (response);
-  GNUNET_SCHEDULER_add_now (&cleanup_handle, handle);
+  cleanup_handle (handle);
 }
 
 
@@ -368,7 +375,7 @@ get_egoentry_namestore (struct RequestHandle *handle, char *name)
   if (NULL == name)
     return NULL;
   tmp = strtok (copy, "/");
-  for (ego_entry = handle->ego_head; NULL != ego_entry;
+  for (ego_entry = ego_head; NULL != ego_entry;
        ego_entry = ego_entry->next)
   {
     if (0 != strcasecmp (tmp, ego_entry->identifier))
@@ -536,6 +543,7 @@ namestore_list_iteration (void *cls,
   GNUNET_NAMESTORE_zone_iterator_next (handle->list_it, 1);
 }
 
+
 /**
  * Handle lookup error
  *
@@ -553,10 +561,10 @@ ns_lookup_error_cb (void *cls)
 
 static void
 ns_get_lookup_cb (void *cls,
-              const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone,
-              const char *label,
-              unsigned int rd_len,
-              const struct GNUNET_GNSRECORD_Data *rd)
+                  const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone,
+                  const char *label,
+                  unsigned int rd_len,
+                  const struct GNUNET_GNSRECORD_Data *rd)
 {
   struct RequestHandle *handle = cls;
   struct GNUNET_GNSRECORD_Data rd_filtered[rd_len];
@@ -588,8 +596,6 @@ ns_get_lookup_cb (void *cls,
 }
 
 
-
-
 /**
  * Handle namestore GET request
  *
@@ -648,7 +654,7 @@ namestore_get (struct GNUNET_REST_RequestHandle *con_handle,
   if (1 >= strlen (labelname))
   {
     handle->list_it =
-      GNUNET_NAMESTORE_zone_iteration_start (handle->ns_handle,
+      GNUNET_NAMESTORE_zone_iteration_start (ns_handle,
                                              handle->zone_pkey,
                                              &namestore_iteration_error,
                                              handle,
@@ -665,13 +671,13 @@ namestore_get (struct GNUNET_REST_RequestHandle *con_handle,
     return;
   }
   handle->record_name = GNUNET_strdup (labelname + 1);
-  handle->ns_qe = GNUNET_NAMESTORE_records_lookup (handle->ns_handle,
-                                                    handle->zone_pkey,
-                                                    handle->record_name,
-                                                    &ns_lookup_error_cb,
-                                                    handle,
-                                                    &ns_get_lookup_cb,
-                                                    handle);
+  handle->ns_qe = GNUNET_NAMESTORE_records_lookup (ns_handle,
+                                                   handle->zone_pkey,
+                                                   handle->record_name,
+                                                   &ns_lookup_error_cb,
+                                                   handle,
+                                                   &ns_get_lookup_cb,
+                                                   handle);
   if (NULL == handle->ns_qe)
   {
     handle->emsg = GNUNET_strdup (GNUNET_REST_NAMESTORE_FAILED);
@@ -681,7 +687,6 @@ namestore_get (struct GNUNET_REST_RequestHandle *con_handle,
 }
 
 
-
 static void
 ns_lookup_cb (void *cls,
               const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone,
@@ -701,13 +706,13 @@ ns_lookup_cb (void *cls,
   }
   for (j = 0; j < handle->rd_count; j++)
     rd_new[i + j] = handle->rd[j];
-  handle->ns_qe = GNUNET_NAMESTORE_records_store (handle->ns_handle,
-                                                   handle->zone_pkey,
-                                                   handle->record_name,
-                                                   i + j,
-                                                   rd_new,
-                                                   &create_finished,
-                                                   handle);
+  handle->ns_qe = GNUNET_NAMESTORE_records_store (ns_handle,
+                                                  handle->zone_pkey,
+                                                  handle->record_name,
+                                                  i + j,
+                                                  rd_new,
+                                                  &create_finished,
+                                                  handle);
   if (NULL == handle->ns_qe)
   {
     handle->emsg = GNUNET_strdup (GNUNET_REST_NAMESTORE_FAILED);
@@ -793,13 +798,13 @@ namestore_add_or_update (struct GNUNET_REST_RequestHandle *con_handle,
     return;
   }
   handle->zone_pkey = GNUNET_IDENTITY_ego_get_private_key (ego_entry->ego);
-  handle->ns_qe = GNUNET_NAMESTORE_records_lookup (handle->ns_handle,
-                                                    handle->zone_pkey,
-                                                    handle->record_name,
-                                                    &ns_lookup_error_cb,
-                                                    handle,
-                                                    &ns_lookup_cb,
-                                                    handle);
+  handle->ns_qe = GNUNET_NAMESTORE_records_lookup (ns_handle,
+                                                   handle->zone_pkey,
+                                                   handle->record_name,
+                                                   &ns_lookup_error_cb,
+                                                   handle,
+                                                   &ns_lookup_cb,
+                                                   handle);
   if (NULL == handle->ns_qe)
   {
     handle->emsg = GNUNET_strdup (GNUNET_REST_NAMESTORE_FAILED);
@@ -894,13 +899,13 @@ namestore_delete (struct GNUNET_REST_RequestHandle *con_handle,
   }
 
   handle->record_name = GNUNET_strdup (labelname + 1);
-  handle->ns_qe = GNUNET_NAMESTORE_records_store (handle->ns_handle,
+  handle->ns_qe = GNUNET_NAMESTORE_records_store (ns_handle,
                                                   handle->zone_pkey,
                                                   handle->record_name,
                                                   0,
-                                                   NULL,
-                                                   &del_finished,
-                                                   handle);
+                                                  NULL,
+                                                  &del_finished,
+                                                  handle);
   if (NULL == handle->ns_qe)
   {
     handle->emsg = GNUNET_strdup (GNUNET_REST_NAMESTORE_FAILED);
@@ -934,90 +939,79 @@ options_cont (struct GNUNET_REST_RequestHandle *con_handle,
 }
 
 
-/**
- * Handle rest request
- *
- * @param handle the request handle
- */
 static void
-init_cont (struct RequestHandle *handle)
+list_ego (void *cls,
+          struct GNUNET_IDENTITY_Ego *ego,
+          void **ctx,
+          const char *identifier)
 {
-  struct GNUNET_REST_RequestHandlerError err;
-  static const struct GNUNET_REST_RequestHandler handlers[] =
-  { { MHD_HTTP_METHOD_GET, GNUNET_REST_API_NS_NAMESTORE, &namestore_get },
-    { MHD_HTTP_METHOD_POST, GNUNET_REST_API_NS_NAMESTORE, &namestore_add },
-    { MHD_HTTP_METHOD_PUT, GNUNET_REST_API_NS_NAMESTORE, &namestore_update },
-    { MHD_HTTP_METHOD_DELETE, GNUNET_REST_API_NS_NAMESTORE, &namestore_delete },
-    { MHD_HTTP_METHOD_OPTIONS, GNUNET_REST_API_NS_NAMESTORE, &options_cont },
-    GNUNET_REST_HANDLER_END };
-
-  if (GNUNET_NO ==
-      GNUNET_REST_handle_request (handle->rest_handle, handlers, &err, handle))
-  {
-    handle->response_code = err.error_code;
-    GNUNET_SCHEDULER_add_now (&do_error, handle);
-  }
-}
-
-
-/**
- * This function is initially called for all egos and then again
- * whenever a ego's identifier changes or if it is deleted.  At the
- * end of the initial pass over all egos, the function is once called
- * with 'NULL' for 'ego'. That does NOT mean that the callback won't
- * be invoked in the future or that there was an error.
- *
- * When used with 'GNUNET_IDENTITY_create' or 'GNUNET_IDENTITY_get',
- * this function is only called ONCE, and 'NULL' being passed in
- * 'ego' does indicate an error (i.e. name is taken or no default
- * value is known).  If 'ego' is non-NULL and if '*ctx'
- * is set in those callbacks, the value WILL be passed to a subsequent
- * call to the identity callback of 'GNUNET_IDENTITY_connect' (if
- * that one was not NULL).
- *
- * When an identity is renamed, this function is called with the
- * (known) ego but the NEW identifier.
- *
- * When an identity is deleted, this function is called with the
- * (known) ego and "NULL" for the 'identifier'.  In this case,
- * the 'ego' is henceforth invalid (and the 'ctx' should also be
- * cleaned up).
- *
- * @param cls closure
- * @param ego ego handle
- * @param ctx context for application to store data for this ego
- *                 (during the lifetime of this process, initially NULL)
- * @param name identifier assigned by the user for this ego,
- *                   NULL if the user just deleted the ego and it
- *                   must thus no longer be used
- */
-static void
-id_connect_cb (void *cls,
-               struct GNUNET_IDENTITY_Ego *ego,
-               void **ctx,
-               const char *name)
-{
-  struct RequestHandle *handle = cls;
   struct EgoEntry *ego_entry;
   struct GNUNET_CRYPTO_EcdsaPublicKey pk;
 
-  if ((NULL == ego) && (ID_REST_STATE_INIT == handle->state))
+  if ((NULL == ego) && (ID_REST_STATE_INIT == state))
   {
-    handle->state = ID_REST_STATE_POST_INIT;
-    init_cont (handle);
+    state = ID_REST_STATE_POST_INIT;
     return;
   }
-  if (ID_REST_STATE_INIT == handle->state)
+  if (ID_REST_STATE_INIT == state)
   {
     ego_entry = GNUNET_new (struct EgoEntry);
     GNUNET_IDENTITY_ego_get_public_key (ego, &pk);
     ego_entry->keystring = GNUNET_CRYPTO_ecdsa_public_key_to_string (&pk);
     ego_entry->ego = ego;
-    GNUNET_asprintf (&ego_entry->identifier, "%s", name);
-    GNUNET_CONTAINER_DLL_insert_tail (handle->ego_head,
-                                      handle->ego_tail,
+    ego_entry->identifier = GNUNET_strdup (identifier);
+    GNUNET_CONTAINER_DLL_insert_tail (ego_head,
+                                      ego_tail,
                                       ego_entry);
   }
+  /* Ego renamed or added */
+  if (identifier != NULL)
+  {
+    for (ego_entry = ego_head; NULL != ego_entry;
+         ego_entry = ego_entry->next)
+    {
+      if (ego_entry->ego == ego)
+      {
+        /* Rename */
+        GNUNET_free (ego_entry->identifier);
+        ego_entry->identifier = GNUNET_strdup (identifier);
+        break;
+      }
+    }
+    if (NULL == ego_entry)
+    {
+      /* Add */
+      ego_entry = GNUNET_new (struct EgoEntry);
+      GNUNET_IDENTITY_ego_get_public_key (ego, &pk);
+      ego_entry->keystring = GNUNET_CRYPTO_ecdsa_public_key_to_string (&pk);
+      ego_entry->ego = ego;
+      ego_entry->identifier = GNUNET_strdup (identifier);
+      GNUNET_CONTAINER_DLL_insert_tail (ego_head,
+                                        ego_tail,
+                                        ego_entry);
+    }
+  }
+  else
+  {
+    /* Delete */
+    for (ego_entry = ego_head; NULL != ego_entry;
+         ego_entry = ego_entry->next)
+    {
+      if (ego_entry->ego == ego)
+        break;
+    }
+    if (NULL == ego_entry)
+      return; /* Not found */
+
+    GNUNET_CONTAINER_DLL_remove (ego_head,
+                                 ego_tail,
+                                 ego_entry);
+    GNUNET_free (ego_entry->identifier);
+    GNUNET_free (ego_entry->keystring);
+    GNUNET_free (ego_entry);
+    return;
+  }
+
 }
 
 
@@ -1032,12 +1026,20 @@ id_connect_cb (void *cls,
  * @param proc_cls closure for callback function
  * @return GNUNET_OK if request accepted
  */
-static void
+static enum GNUNET_GenericReturnValue
 rest_process_request (struct GNUNET_REST_RequestHandle *rest_handle,
                       GNUNET_REST_ResultProcessor proc,
                       void *proc_cls)
 {
   struct RequestHandle *handle = GNUNET_new (struct RequestHandle);
+  struct GNUNET_REST_RequestHandlerError err;
+  static const struct GNUNET_REST_RequestHandler handlers[] =
+  { { MHD_HTTP_METHOD_GET, GNUNET_REST_API_NS_NAMESTORE, &namestore_get },
+    { MHD_HTTP_METHOD_POST, GNUNET_REST_API_NS_NAMESTORE, &namestore_add },
+    { MHD_HTTP_METHOD_PUT, GNUNET_REST_API_NS_NAMESTORE, &namestore_update },
+    { MHD_HTTP_METHOD_DELETE, GNUNET_REST_API_NS_NAMESTORE, &namestore_delete },
+    { MHD_HTTP_METHOD_OPTIONS, GNUNET_REST_API_NS_NAMESTORE, &options_cont },
+    GNUNET_REST_HANDLER_END };
 
   handle->response_code = 0;
   handle->timeout = GNUNET_TIME_UNIT_FOREVER_REL;
@@ -1045,19 +1047,24 @@ rest_process_request (struct GNUNET_REST_RequestHandle *rest_handle,
   handle->proc = proc;
   handle->rest_handle = rest_handle;
   handle->zone_pkey = NULL;
-
+  handle->timeout_task =
+    GNUNET_SCHEDULER_add_delayed (handle->timeout, &do_error, handle);
   handle->url = GNUNET_strdup (rest_handle->url);
   if (handle->url[strlen (handle->url) - 1] == '/')
     handle->url[strlen (handle->url) - 1] = '\0';
+  GNUNET_CONTAINER_DLL_insert (requests_head,
+                               requests_tail,
+                               handle);
   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Connecting...\n");
-
-  handle->ns_handle = GNUNET_NAMESTORE_connect (cfg);
-  handle->identity_handle =
-    GNUNET_IDENTITY_connect (cfg, &id_connect_cb, handle);
-  handle->timeout_task =
-    GNUNET_SCHEDULER_add_delayed (handle->timeout, &do_error, handle);
+  if (GNUNET_NO ==
+      GNUNET_REST_handle_request (handle->rest_handle, handlers, &err, handle))
+  {
+    cleanup_handle (handle);
+    return GNUNET_NO;
+  }
 
   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Connected\n");
+  return GNUNET_YES;
 }
 
 
@@ -1082,6 +1089,7 @@ libgnunet_plugin_rest_namestore_init (void *cls)
   api->cls = &plugin;
   api->name = GNUNET_REST_API_NS_NAMESTORE;
   api->process_request = &rest_process_request;
+  state = ID_REST_STATE_INIT;
   GNUNET_asprintf (&allow_methods,
                    "%s, %s, %s, %s, %s",
                    MHD_HTTP_METHOD_GET,
@@ -1089,6 +1097,8 @@ libgnunet_plugin_rest_namestore_init (void *cls)
                    MHD_HTTP_METHOD_PUT,
                    MHD_HTTP_METHOD_DELETE,
                    MHD_HTTP_METHOD_OPTIONS);
+  ns_handle = GNUNET_NAMESTORE_connect (cfg);
+  identity_handle = GNUNET_IDENTITY_connect (cfg, &list_ego, NULL);
 
   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, _ ("Namestore REST API initialized\n"));
   return api;
@@ -1106,8 +1116,26 @@ libgnunet_plugin_rest_namestore_done (void *cls)
 {
   struct GNUNET_REST_Plugin *api = cls;
   struct Plugin *plugin = api->cls;
+  struct RequestHandle *request;
+  struct EgoEntry *ego_entry;
+  struct EgoEntry *ego_tmp;
 
   plugin->cfg = NULL;
+  while (NULL != (request = requests_head))
+    do_error (request);
+  if (NULL != identity_handle)
+    GNUNET_IDENTITY_disconnect (identity_handle);
+  if (NULL != ns_handle)
+    GNUNET_NAMESTORE_disconnect (ns_handle);
+
+  for (ego_entry = ego_head; NULL != ego_entry;)
+  {
+    ego_tmp = ego_entry;
+    ego_entry = ego_entry->next;
+    GNUNET_free (ego_tmp->identifier);
+    GNUNET_free (ego_tmp->keystring);
+    GNUNET_free (ego_tmp);
+  }
 
   GNUNET_free (allow_methods);
   GNUNET_free (api);
diff --git a/src/namestore/test_namestore_put_multiple.sh b/src/namestore/test_namestore_put_multiple.sh
new file mode 100644
index 0000000000000000000000000000000000000000..81e1ad2b5ba1ec2dbf2c10fbdfb7abdbe79dac50
--- /dev/null
+++ b/src/namestore/test_namestore_put_multiple.sh
@@ -0,0 +1,123 @@
+#!/bin/bash
+
+# Check for required packages
+if ! [ -x "$(command -v gnunet-namestore)" ]; then
+    echo 'bind/named is not installed' >&2
+    exit 1
+fi
+
+# Check if gnunet is running
+gnunet-arm -I 2&>1 /dev/null
+ret=$?
+if [ 0 -ne $ret ]; then
+    echo 'gnunet services are not running'
+    exit 1
+fi
+
+## GNUNET part
+# Check if identity exists and delets and readds it to get rid of entries in zone
+gnunet-identity -d | grep randomtestingid 2>&1 /dev/null
+ret=$?
+
+if [ 0 -ne $ret ]; then
+    gnunet-identity -D randomtestingid
+    gnunet-identity -C randomtestingid
+fi
+
+function minimize_ttl {
+    ttl=10000000
+    arr=$1
+    # parse each element and update ttl to smallest one
+    for i in "${arr[@]}"
+    do
+        currttl=$(echo -n "$i" | cut -d' ' -f1)
+        if [ "$currttl"  -lt "$ttl" ]
+        then
+            ttl=$currttl
+        fi
+
+    done
+    echo "$ttl"
+}
+
+function get_record_type {
+    arr=$1
+    typ=$(echo -n "${arr[0]}" | cut -d' ' -f2)
+    echo "$typ"
+}
+
+function get_value {
+    arr=$1
+    val=$(echo -n "${arr[0]}" | cut -d' ' -f4-)
+    echo "$val"
+}
+
+function testing {
+    label=$1
+    records=$2
+    recordstring=""
+    typ=$(get_record_type "${records[@]}")
+    for i in "${records[@]}"
+    do
+        recordstring+="-R $i"
+    done
+    #echo "$recordstring"
+    gnunet-namestore -z randomtestingid -n "$label" "$recordstring" 2>&1  /dev/null
+    if [ 0 -ne $ret ]; then
+        echo "failed to add record $label: $recordstring"
+    fi
+    gnunet-gns -t "$typ" -u foo2.randomtestingid 2>&1 /dev/null
+    if [ 0 -ne $ret ]; then
+        echo "record $label could not be found"
+    fi
+}
+
+# TEST CASES
+# 1
+echo "Testing adding of single A record with -R"
+testing test1 "${arr[@]}"
+# 2
+echo "Testing adding of multiple A records with -R"
+declare -a arr=('1200 A n 127.0.0.1' '2400 A n 127.0.0.2')
+testing test2 "${arr[@]}"
+# 3
+echo "Testing adding of multiple different records with -R"
+declare -a arr=('1200 A n 127.0.0.1' '2400 AAAA n 2002::')
+testing test3 "${arr[@]}"
+# 4
+echo "Testing adding of single GNS2DNS record with -R"
+declare -a arr=('86400 GNS2DNS n gnu.org@127.0.0.1')
+testing test4 "${arr[@]}"
+# 5
+echo "Testing adding of single GNS2DNS shadow record with -R"
+declare -a arr=('86409 GNS2DNS s gnu.org@127.0.0.250')
+testing test5 "${arr[@]}"
+# 6
+echo "Testing adding of multiple GNS2DNS record with -R"
+declare -a arr=('1 GNS2DNS n gnunet.org@127.0.0.1' '3600 GNS2DNS s gnunet.org@127.0.0.2')
+testing test6 "${arr[@]}"
+val=$(gnunet-gns -t GNS2DNS -u test6.randomtestingid)
+if [[ $val == *"127.0.0.1"* ]]; then
+    echo "shadow!"
+fi
+echo "Sleeping to let record expire"
+sleep 5
+val=$(gnunet-gns -t GNS2DNS -u test6.randomtestingid)
+if [[ $val == *"127.0.0.2"* ]]; then
+    echo "no shadow!"
+fi
+# 7
+echo "Testing adding MX record with -R"
+declare -a arr=('3600 MX n 10,mail')
+testing test7 "${arr[@]}"
+# 8
+echo "Testing adding TXT record with -R"
+declare -a arr=('3600 TXT n Pretty_Unicorns')
+testing test8 "${arr[@]}"
+# 8
+echo "Testing adding TXT record with -R"
+declare -a arr=('3600 SRV n _autodiscover_old._tcp.bfh.ch.')
+testing test8 "${arr[@]}"
+
+# CLEANUP
+gnunet-identity -D randomtestingid
diff --git a/src/nat-auto/.gitignore b/src/nat-auto/.gitignore
new file mode 100644
index 0000000000000000000000000000000000000000..6ba53d72f55180c75f6fc0fd916b705c14a40241
--- /dev/null
+++ b/src/nat-auto/.gitignore
@@ -0,0 +1,3 @@
+gnunet-service-nat-auto
+gnunet-nat-auto
+gnunet-nat-server
diff --git a/src/nat-auto/gnunet-nat-auto_legacy.c b/src/nat-auto/gnunet-nat-auto_legacy.c
new file mode 100644
index 0000000000000000000000000000000000000000..8ba50c18486b512ad8e57c7822ecd4b8ad0d9f66
--- /dev/null
+++ b/src/nat-auto/gnunet-nat-auto_legacy.c
@@ -0,0 +1,597 @@
+/*
+     This file is part of GNUnet.
+     Copyright (C) 2011, 2016 GNUnet e.V.
+
+     GNUnet is free software: you can redistribute it and/or modify it
+     under the terms of the GNU Affero General Public License as published
+     by the Free Software Foundation, either version 3 of the License,
+     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
+     Affero General Public License for more details.
+
+     You should have received a copy of the GNU Affero General Public License
+     along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+     SPDX-License-Identifier: AGPL3.0-or-later
+ */
+
+/**
+ * @file nat/nat_test.c
+ * @brief functions to test if the NAT configuration is successful at achieving NAT traversal (with the help of a gnunet-nat-server)
+ * @author Christian Grothoff
+ */
+#include "platform.h"
+#include "gnunet_util_lib.h"
+#include "gnunet_nat_lib.h"
+#include "nat.h"
+
+#define LOG(kind, ...) GNUNET_log_from (kind, "nat", __VA_ARGS__)
+
+#define NAT_SERVER_TIMEOUT \
+  GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 30)
+
+/**
+ * Entry we keep for each incoming connection.
+ */
+struct NatActivity
+{
+  /**
+   * This is a doubly-linked list.
+   */
+  struct NatActivity *next;
+
+  /**
+   * This is a doubly-linked list.
+   */
+  struct NatActivity *prev;
+
+  /**
+   * Socket of the incoming connection.
+   */
+  struct GNUNET_NETWORK_Handle *sock;
+
+  /**
+   * Handle of the master context.
+   */
+  struct GNUNET_NAT_Test *h;
+
+  /**
+   * Task reading from the incoming connection.
+   */
+  struct GNUNET_SCHEDULER_Task *rtask;
+};
+
+
+/**
+ * Entry we keep for each connection to the gnunet-nat-service.
+ */
+struct ClientActivity
+{
+  /**
+   * This is a doubly-linked list.
+   */
+  struct ClientActivity *next;
+
+  /**
+   * This is a doubly-linked list.
+   */
+  struct ClientActivity *prev;
+
+  /**
+   * Socket of the incoming connection.
+   */
+  struct GNUNET_MQ_Handle *mq;
+
+  /**
+   * Handle to overall NAT test.
+   */
+  struct GNUNET_NAT_Test *h;
+};
+
+
+/**
+ * Handle to a NAT test.
+ */
+struct GNUNET_NAT_Test
+{
+  /**
+   * Configuration used
+   */
+  const struct GNUNET_CONFIGURATION_Handle *cfg;
+
+  /**
+   * Function to call with success report
+   */
+  GNUNET_NAT_TestCallback report;
+
+  /**
+   * Closure for @e report.
+   */
+  void *report_cls;
+
+  /**
+   * Handle to NAT traversal in use
+   */
+  struct GNUNET_NAT_Handle *nat;
+
+  /**
+   * Handle to listen socket, or NULL
+   */
+  struct GNUNET_NETWORK_Handle *lsock;
+
+  /**
+   * Head of list of nat activities.
+   */
+  struct NatActivity *na_head;
+
+  /**
+   * Tail of list of nat activities.
+   */
+  struct NatActivity *na_tail;
+
+  /**
+   * Head of list of client activities.
+   */
+  struct ClientActivity *ca_head;
+
+  /**
+   * Tail of list of client activities.
+   */
+  struct ClientActivity *ca_tail;
+
+  /**
+   * Identity of task for the listen socket (if any)
+   */
+  struct GNUNET_SCHEDULER_Task *ltask;
+
+  /**
+   * Task identifier for the timeout (if any)
+   */
+  struct GNUNET_SCHEDULER_Task *ttask;
+
+  /**
+   * #GNUNET_YES if we're testing TCP
+   */
+  int is_tcp;
+
+  /**
+   * Data that should be transmitted or source-port.
+   */
+  uint16_t data;
+
+  /**
+   * Advertised port to the other peer.
+   */
+  uint16_t adv_port;
+
+  /**
+   * Status code to be reported to the timeout/status call
+   */
+  enum GNUNET_NAT_StatusCode status;
+};
+
+
+/**
+ * Function called from #GNUNET_NAT_register whenever someone asks us
+ * to do connection reversal.
+ *
+ * @param cls closure, our `struct GNUNET_NAT_Handle`
+ * @param addr public IP address of the other peer
+ * @param addrlen actual lenght of the @a addr
+ */
+static void
+reversal_cb (void *cls, const struct sockaddr *addr, socklen_t addrlen)
+{
+  struct GNUNET_NAT_Test *h = cls;
+  const struct sockaddr_in *sa;
+
+  if (sizeof(struct sockaddr_in) != addrlen)
+    return;
+  sa = (const struct sockaddr_in *) addr;
+  if (h->data != sa->sin_port)
+  {
+    LOG (GNUNET_ERROR_TYPE_DEBUG,
+         "Received connection reversal request for wrong port\n");
+    return;   /* wrong port */
+  }
+  /* report success */
+  h->report (h->report_cls, GNUNET_NAT_ERROR_SUCCESS);
+}
+
+
+/**
+ * Activity on our incoming socket.  Read data from the
+ * incoming connection.
+ *
+ * @param cls the `struct GNUNET_NAT_Test`
+ */
+static void
+do_udp_read (void *cls)
+{
+  struct GNUNET_NAT_Test *tst = cls;
+  uint16_t data;
+  const struct GNUNET_SCHEDULER_TaskContext *tc;
+
+  tc = GNUNET_SCHEDULER_get_task_context ();
+  tst->ltask = GNUNET_SCHEDULER_add_read_net (GNUNET_TIME_UNIT_FOREVER_REL,
+                                              tst->lsock,
+                                              &do_udp_read,
+                                              tst);
+  if ((NULL != tc->write_ready) &&
+      (GNUNET_NETWORK_fdset_isset (tc->read_ready, tst->lsock)) &&
+      (sizeof(data) ==
+       GNUNET_NETWORK_socket_recv (tst->lsock, &data, sizeof(data))))
+  {
+    if (data == tst->data)
+      tst->report (tst->report_cls, GNUNET_NAT_ERROR_SUCCESS);
+    else
+      LOG (GNUNET_ERROR_TYPE_DEBUG,
+           "Received data mismatches expected value\n");
+  }
+  else
+    LOG (GNUNET_ERROR_TYPE_DEBUG,
+         "Failed to receive data from inbound connection\n");
+}
+
+
+/**
+ * Activity on our incoming socket.  Read data from the
+ * incoming connection.
+ *
+ * @param cls the `struct NatActivity`
+ */
+static void
+do_read (void *cls)
+{
+  struct NatActivity *na = cls;
+  struct GNUNET_NAT_Test *tst;
+  uint16_t data;
+  const struct GNUNET_SCHEDULER_TaskContext *tc;
+
+  tc = GNUNET_SCHEDULER_get_task_context ();
+  na->rtask = NULL;
+  tst = na->h;
+  GNUNET_CONTAINER_DLL_remove (tst->na_head, tst->na_tail, na);
+  if ((NULL != tc->write_ready) &&
+      (GNUNET_NETWORK_fdset_isset (tc->read_ready, na->sock)) &&
+      (sizeof(data) ==
+       GNUNET_NETWORK_socket_recv (na->sock, &data, sizeof(data))))
+  {
+    if (data == tst->data)
+      tst->report (tst->report_cls, GNUNET_NAT_ERROR_SUCCESS);
+    else
+      LOG (GNUNET_ERROR_TYPE_DEBUG,
+           "Received data does not match expected value\n");
+  }
+  else
+    LOG (GNUNET_ERROR_TYPE_DEBUG,
+         "Failed to receive data from inbound connection\n");
+  GNUNET_NETWORK_socket_close (na->sock);
+  GNUNET_free (na);
+}
+
+
+/**
+ * Activity on our listen socket. Accept the
+ * incoming connection.
+ *
+ * @param cls the `struct GNUNET_NAT_Test`
+ */
+static void
+do_accept (void *cls)
+{
+  struct GNUNET_NAT_Test *tst = cls;
+  struct GNUNET_NETWORK_Handle *s;
+  struct NatActivity *wl;
+
+  tst->ltask = GNUNET_SCHEDULER_add_read_net (GNUNET_TIME_UNIT_FOREVER_REL,
+                                              tst->lsock,
+                                              &do_accept,
+                                              tst);
+  s = GNUNET_NETWORK_socket_accept (tst->lsock, NULL, NULL);
+  if (NULL == s)
+  {
+    GNUNET_log_strerror (GNUNET_ERROR_TYPE_INFO, "accept");
+    return;   /* odd error */
+  }
+  LOG (GNUNET_ERROR_TYPE_DEBUG,
+       "Got an inbound connection, waiting for data\n");
+  wl = GNUNET_new (struct NatActivity);
+  wl->sock = s;
+  wl->h = tst;
+  wl->rtask = GNUNET_SCHEDULER_add_read_net (GNUNET_TIME_UNIT_FOREVER_REL,
+                                             wl->sock,
+                                             &do_read,
+                                             wl);
+  GNUNET_CONTAINER_DLL_insert (tst->na_head, tst->na_tail, wl);
+}
+
+
+/**
+ * We got disconnected from the NAT server.  Stop
+ * waiting for a reply.
+ *
+ * @param cls the `struct ClientActivity`
+ * @param error error code
+ */
+static void
+mq_error_handler (void *cls, enum GNUNET_MQ_Error error)
+{
+  struct ClientActivity *ca = cls;
+  struct GNUNET_NAT_Test *tst = ca->h;
+
+  GNUNET_CONTAINER_DLL_remove (tst->ca_head, tst->ca_tail, ca);
+  GNUNET_MQ_destroy (ca->mq);
+  GNUNET_free (ca);
+}
+
+
+/**
+ * Address-callback, used to send message to gnunet-nat-server.
+ *
+ * @param cls closure
+ * @param add_remove #GNUNET_YES to mean the new public IP address, #GNUNET_NO to mean
+ *     the previous (now invalid) one
+ * @param addr either the previous or the new public IP address
+ * @param addrlen actual length of the @a addr
+ */
+static void
+addr_cb (void *cls,
+         int add_remove,
+         const struct sockaddr *addr,
+         socklen_t addrlen)
+{
+  struct GNUNET_NAT_Test *h = cls;
+  struct ClientActivity *ca;
+  struct GNUNET_MQ_Envelope *env;
+  struct GNUNET_NAT_TestMessage *msg;
+  const struct sockaddr_in *sa;
+
+  if (GNUNET_YES != add_remove)
+    return;
+  if (addrlen != sizeof(struct sockaddr_in))
+  {
+    LOG (GNUNET_ERROR_TYPE_DEBUG,
+         "NAT test ignores IPv6 address `%s' returned from NAT library\n",
+         GNUNET_a2s (addr, addrlen));
+    return;   /* ignore IPv6 here */
+  }
+  LOG (GNUNET_ERROR_TYPE_INFO,
+       "Asking gnunet-nat-server to connect to `%s'\n",
+       GNUNET_a2s (addr, addrlen));
+
+  ca = GNUNET_new (struct ClientActivity);
+  ca->h = h;
+  ca->mq = GNUNET_CLIENT_connect (h->cfg,
+                                  "gnunet-nat-server",
+                                  NULL,
+                                  &mq_error_handler,
+                                  ca);
+  if (NULL == ca->mq)
+  {
+    GNUNET_free (ca);
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                _ ("Failed to connect to `gnunet-nat-server'\n"));
+    return;
+  }
+  GNUNET_CONTAINER_DLL_insert (h->ca_head, h->ca_tail, ca);
+  sa = (const struct sockaddr_in *) addr;
+  env = GNUNET_MQ_msg (msg, GNUNET_MESSAGE_TYPE_NAT_TEST);
+  msg->dst_ipv4 = sa->sin_addr.s_addr;
+  msg->dport = sa->sin_port;
+  msg->data = h->data;
+  msg->is_tcp = htonl ((uint32_t) h->is_tcp);
+  GNUNET_MQ_send (ca->mq, env);
+}
+
+
+/**
+ * Timeout task for a nat test.
+ * Calls the report-callback with a timeout return value
+ *
+ * Destroys the nat handle after the callback has been processed.
+ *
+ * @param cls handle to the timed out NAT test
+ */
+static void
+do_timeout (void *cls)
+{
+  struct GNUNET_NAT_Test *nh = cls;
+
+  nh->ttask = NULL;
+  nh->report (nh->report_cls,
+              (GNUNET_NAT_ERROR_SUCCESS == nh->status)
+              ? GNUNET_NAT_ERROR_TIMEOUT
+              : nh->status);
+}
+
+
+/**
+ * Start testing if NAT traversal works using the
+ * given configuration (IPv4-only).
+ *
+ * ALL failures are reported directly to the report callback
+ *
+ * @param cfg configuration for the NAT traversal
+ * @param is_tcp #GNUNET_YES to test TCP, #GNUNET_NO to test UDP
+ * @param bnd_port port to bind to, 0 for connection reversal
+ * @param adv_port externally advertised port to use
+ * @param timeout delay after which the test should be aborted
+ * @param report function to call with the result of the test
+ * @param report_cls closure for @a report
+ * @return handle to cancel NAT test or NULL. The error is always indicated via the report callback
+ */
+struct GNUNET_NAT_Test *
+GNUNET_NAT_test_start (const struct GNUNET_CONFIGURATION_Handle *cfg,
+                       int is_tcp,
+                       uint16_t bnd_port,
+                       uint16_t adv_port,
+                       struct GNUNET_TIME_Relative timeout,
+                       GNUNET_NAT_TestCallback report,
+                       void *report_cls)
+{
+  struct GNUNET_NAT_Test *nh;
+  struct sockaddr_in sa;
+  const struct sockaddr *addrs[] = { (const struct sockaddr *) &sa };
+  const socklen_t addrlens[] = { sizeof(sa) };
+
+  memset (&sa, 0, sizeof(sa));
+  sa.sin_family = AF_INET;
+  sa.sin_port = htons (bnd_port);
+#if HAVE_SOCKADDR_IN_SIN_LEN
+  sa.sin_len = sizeof(sa);
+#endif
+
+  nh = GNUNET_new (struct GNUNET_NAT_Test);
+  nh->cfg = cfg;
+  nh->is_tcp = is_tcp;
+  nh->data = bnd_port;
+  nh->adv_port = adv_port;
+  nh->report = report;
+  nh->report_cls = report_cls;
+  nh->status = GNUNET_NAT_ERROR_SUCCESS;
+  if (0 == bnd_port)
+  {
+    nh->nat = GNUNET_NAT_register (cfg,
+                                   is_tcp,
+                                   0,
+                                   0,
+                                   NULL,
+                                   NULL,
+                                   &addr_cb,
+                                   &reversal_cb,
+                                   nh,
+                                   NULL);
+  }
+  else
+  {
+    nh->lsock =
+      GNUNET_NETWORK_socket_create (AF_INET,
+                                    (is_tcp == GNUNET_YES) ? SOCK_STREAM
+                                    : SOCK_DGRAM,
+                                    0);
+    if ((nh->lsock == NULL) ||
+        (GNUNET_OK != GNUNET_NETWORK_socket_bind (nh->lsock,
+                                                  (const struct sockaddr *) &sa,
+                                                  sizeof(sa))))
+    {
+      GNUNET_log (
+        GNUNET_ERROR_TYPE_ERROR,
+        _ ("Failed to create listen socket bound to `%s' for NAT test: %s\n"),
+        GNUNET_a2s ((const struct sockaddr *) &sa, sizeof(sa)),
+        strerror (errno));
+      if (NULL != nh->lsock)
+      {
+        GNUNET_NETWORK_socket_close (nh->lsock);
+        nh->lsock = NULL;
+      }
+      nh->status = GNUNET_NAT_ERROR_INTERNAL_NETWORK_ERROR;
+      nh->ttask = GNUNET_SCHEDULER_add_now (&do_timeout, nh);
+      return nh;
+    }
+    if (GNUNET_YES == is_tcp)
+    {
+      GNUNET_break (GNUNET_OK == GNUNET_NETWORK_socket_listen (nh->lsock, 5));
+      nh->ltask = GNUNET_SCHEDULER_add_read_net (GNUNET_TIME_UNIT_FOREVER_REL,
+                                                 nh->lsock,
+                                                 &do_accept,
+                                                 nh);
+    }
+    else
+    {
+      nh->ltask = GNUNET_SCHEDULER_add_read_net (GNUNET_TIME_UNIT_FOREVER_REL,
+                                                 nh->lsock,
+                                                 &do_udp_read,
+                                                 nh);
+    }
+    LOG (GNUNET_ERROR_TYPE_INFO,
+         "NAT test listens on port %u (%s)\n",
+         bnd_port,
+         (GNUNET_YES == is_tcp) ? "tcp" : "udp");
+    nh->nat = GNUNET_NAT_register (cfg,
+                                   is_tcp,
+                                   adv_port,
+                                   1,
+                                   addrs,
+                                   addrlens,
+                                   &addr_cb,
+                                   NULL,
+                                   nh,
+                                   NULL);
+    if (NULL == nh->nat)
+    {
+      LOG (GNUNET_ERROR_TYPE_INFO,
+           _ ("NAT test failed to start NAT library\n"));
+      if (NULL != nh->ltask)
+      {
+        GNUNET_SCHEDULER_cancel (nh->ltask);
+        nh->ltask = NULL;
+      }
+      if (NULL != nh->lsock)
+      {
+        GNUNET_NETWORK_socket_close (nh->lsock);
+        nh->lsock = NULL;
+      }
+      nh->status = GNUNET_NAT_ERROR_NAT_REGISTER_FAILED;
+      nh->ttask = GNUNET_SCHEDULER_add_now (&do_timeout, nh);
+      return nh;
+    }
+  }
+  nh->ttask = GNUNET_SCHEDULER_add_delayed (timeout, &do_timeout, nh);
+  return nh;
+}
+
+
+/**
+ * Stop an active NAT test.
+ *
+ * @param tst test to stop.
+ */
+void
+GNUNET_NAT_test_stop (struct GNUNET_NAT_Test *tst)
+{
+  struct NatActivity *pos;
+  struct ClientActivity *cpos;
+
+  LOG (GNUNET_ERROR_TYPE_DEBUG, "Stopping NAT test\n");
+  while (NULL != (cpos = tst->ca_head))
+  {
+    GNUNET_CONTAINER_DLL_remove (tst->ca_head, tst->ca_tail, cpos);
+    GNUNET_MQ_destroy (cpos->mq);
+    GNUNET_free (cpos);
+  }
+  while (NULL != (pos = tst->na_head))
+  {
+    GNUNET_CONTAINER_DLL_remove (tst->na_head, tst->na_tail, pos);
+    GNUNET_SCHEDULER_cancel (pos->rtask);
+    GNUNET_NETWORK_socket_close (pos->sock);
+    GNUNET_free (pos);
+  }
+  if (NULL != tst->ttask)
+  {
+    GNUNET_SCHEDULER_cancel (tst->ttask);
+    tst->ttask = NULL;
+  }
+  if (NULL != tst->ltask)
+  {
+    GNUNET_SCHEDULER_cancel (tst->ltask);
+    tst->ltask = NULL;
+  }
+  if (NULL != tst->lsock)
+  {
+    GNUNET_NETWORK_socket_close (tst->lsock);
+    tst->lsock = NULL;
+  }
+  if (NULL != tst->nat)
+  {
+    GNUNET_NAT_unregister (tst->nat);
+    tst->nat = NULL;
+  }
+  GNUNET_free (tst);
+}
+
+
+/* end of nat_test.c */
diff --git a/src/nat-auto/gnunet-service-nat-auto_legacy.c b/src/nat-auto/gnunet-service-nat-auto_legacy.c
new file mode 100644
index 0000000000000000000000000000000000000000..de79105887b8f2352c3a4cd2815dc979165e2e46
--- /dev/null
+++ b/src/nat-auto/gnunet-service-nat-auto_legacy.c
@@ -0,0 +1,1093 @@
+/*
+     This file is part of GNUnet.
+     Copyright (C) 2015 GNUnet e.V.
+
+     GNUnet is free software: you can redistribute it and/or modify it
+     under the terms of the GNU Affero General Public License as published
+     by the Free Software Foundation, either version 3 of the License,
+     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
+     Affero General Public License for more details.
+
+     You should have received a copy of the GNU Affero General Public License
+     along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+     SPDX-License-Identifier: AGPL3.0-or-later
+ */
+
+/**
+ * @file nat/nat_auto.c
+ * @brief functions for auto-configuration of the network
+ * @author Christian Grothoff
+ * @author Bruno Cabral
+ */
+#include "platform.h"
+#include "gnunet_util_lib.h"
+#include "gnunet_resolver_service.h"
+#include "gnunet_nat_lib.h"
+#include "nat.h"
+
+#define LOG(kind, ...) GNUNET_log_from (kind, "nat", __VA_ARGS__)
+
+
+/**
+ * How long do we wait for the NAT test to report success?
+ */
+#define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 15)
+
+#define NAT_SERVER_TIMEOUT GNUNET_TIME_relative_multiply ( \
+    GNUNET_TIME_UNIT_SECONDS, 10)
+
+/**
+ * Phases of the auto configuration.
+ */
+enum AutoPhase
+{
+  /**
+   * Initial start value.
+   */
+  AUTO_INIT = 0,
+
+  /**
+   * Test our external IP.
+   */
+  AUTO_EXTERNAL_IP,
+
+  /**
+   * Test our external IP.
+   */
+  AUTO_STUN,
+
+  /**
+   * Test our internal IP.
+   */
+  AUTO_LOCAL_IP,
+
+  /**
+   * Test if NAT was punched.
+   */
+  AUTO_NAT_PUNCHED,
+
+  /**
+   * Test if UPnP is working.
+   */
+  AUTO_UPNPC,
+
+  /**
+   * Test if ICMP server works.
+   */
+  AUTO_ICMP_SERVER,
+
+  /**
+   * Test if ICMP client works.
+   */
+  AUTO_ICMP_CLIENT,
+
+  /**
+   * Last phase, we're done.
+   */
+  AUTO_DONE
+};
+
+
+/**
+ * Handle to auto-configuration in progress.
+ */
+struct GNUNET_NAT_AutoHandle
+{
+  /**
+   * Handle to the active NAT test.
+   */
+  struct GNUNET_NAT_Test *tst;
+
+  /**
+   * Function to call when done.
+   */
+  GNUNET_NAT_AutoResultCallback fin_cb;
+
+  /**
+   * Closure for @e fin_cb.
+   */
+  void *fin_cb_cls;
+
+  /**
+   * Handle for active 'GNUNET_NAT_mini_get_external_ipv4'-operation.
+   */
+  struct GNUNET_NAT_ExternalHandle *eh;
+
+  /**
+   * Current configuration (with updates from previous phases)
+   */
+  struct GNUNET_CONFIGURATION_Handle *cfg;
+
+  /**
+   * Original configuration (used to calculate differences)
+   */
+  struct GNUNET_CONFIGURATION_Handle *initial_cfg;
+
+  /**
+   * Task identifier for the timeout.
+   */
+  struct GNUNET_SCHEDULER_Task *task;
+
+  /**
+   * Message queue to the gnunet-nat-server.
+   */
+  struct GNUNET_MQ_Handle *mq;
+
+  /**
+   * Where are we in the test?
+   */
+  enum AutoPhase phase;
+
+  /**
+   * Situation of the NAT
+   */
+  enum GNUNET_NAT_Type type;
+
+  /**
+   * Do we have IPv6?
+   */
+  int have_v6;
+
+  /**
+   * UPnP already set the external ip address ?
+   */
+  int upnp_set_external_address;
+
+  /**
+   * Did the external server connected back ?
+   */
+  int connected_back;
+
+  /**
+   * Address detected by STUN
+   */
+  char *stun_ip;
+
+  unsigned int stun_port;
+
+  /**
+   * Internal IP is the same as the public one ?
+   */
+  int internal_ip_is_public;
+
+  /**
+   * Error code for better debugging and user feedback
+   */
+  enum GNUNET_NAT_StatusCode ret;
+};
+
+
+/**
+ * The listen socket of the service for IPv4
+ */
+static struct GNUNET_NETWORK_Handle *lsock4;
+
+/**
+ * The listen task ID for IPv4
+ */
+static struct GNUNET_SCHEDULER_Task *ltask4;
+
+/**
+ * The port the test service is running on (default 7895)
+ */
+static unsigned long long port = 7895;
+
+static char *stun_server = "stun.ekiga.net";
+
+static unsigned int stun_port = 3478;
+
+
+/**
+ * Run the next phase of the auto test.
+ *
+ * @param ah auto test handle
+ */
+static void
+next_phase (struct GNUNET_NAT_AutoHandle *ah);
+
+
+static void
+process_stun_reply (struct sockaddr_in *answer,
+                    struct GNUNET_NAT_AutoHandle *ah)
+{
+  ah->stun_ip = inet_ntoa (answer->sin_addr);
+  ah->stun_port = ntohs (answer->sin_port);
+  GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+              "External IP is: %s , with port %u\n",
+              ah->stun_ip,
+              ah->stun_port);
+  next_phase (ah);
+}
+
+
+/**
+ * Function that terminates the test.
+ */
+static void
+stop_stun ()
+{
+  GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+              "Stopping STUN and quitting...\n");
+  /* Clean task */
+  if (NULL != ltask4)
+  {
+    GNUNET_SCHEDULER_cancel (ltask4);
+    ltask4 = NULL;
+  }
+  /* Clean socket */
+  if (NULL != lsock4)
+  {
+    GNUNET_NETWORK_socket_close (lsock4);
+    lsock4 = NULL;
+  }
+}
+
+
+/**
+ * Activity on our incoming socket.  Read data from the
+ * incoming connection.
+ *
+ * @param cls
+ */
+static void
+do_udp_read (void *cls)
+{
+  struct GNUNET_NAT_AutoHandle *ah = cls;
+  unsigned char reply_buf[1024];
+  ssize_t rlen;
+  struct sockaddr_in answer;
+  const struct GNUNET_SCHEDULER_TaskContext *tc;
+
+  tc = GNUNET_SCHEDULER_get_task_context ();
+  if ((0 != (tc->reason & GNUNET_SCHEDULER_REASON_READ_READY)) &&
+      (GNUNET_NETWORK_fdset_isset (tc->read_ready,
+                                   lsock4)))
+  {
+    rlen = GNUNET_NETWORK_socket_recv (lsock4,
+                                       reply_buf,
+                                       sizeof(reply_buf));
+
+    // Lets handle the packet
+    memset (&answer, 0, sizeof(struct sockaddr_in));
+    if (ah->phase == AUTO_NAT_PUNCHED)
+    {
+      // Destroy the connection
+      GNUNET_NETWORK_socket_close (lsock4);
+      GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+                  "The external server was able to connect back");
+      ah->connected_back = GNUNET_YES;
+      next_phase (ah);
+    }
+    else
+    {
+      if (GNUNET_OK ==
+          GNUNET_NAT_stun_handle_packet (reply_buf, rlen, &answer))
+      {
+        // Process the answer
+        process_stun_reply (&answer, ah);
+      }
+      else
+      {
+        next_phase (ah);
+      }
+    }
+  }
+  else
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+                "TIMEOUT while waiting for an answer\n");
+    if (ah->phase == AUTO_NAT_PUNCHED)
+    {
+      stop_stun ();
+    }
+
+    next_phase (ah);
+  }
+}
+
+
+/**
+ * Create an IPv4 listen socket bound to our port.
+ *
+ * @return NULL on error
+ */
+static struct GNUNET_NETWORK_Handle *
+bind_v4 ()
+{
+  struct GNUNET_NETWORK_Handle *ls;
+  struct sockaddr_in sa4;
+  int eno;
+
+  memset (&sa4, 0, sizeof(sa4));
+  sa4.sin_family = AF_INET;
+  sa4.sin_port = htons (port);
+#if HAVE_SOCKADDR_IN_SIN_LEN
+  sa4.sin_len = sizeof(sa4);
+#endif
+  ls = GNUNET_NETWORK_socket_create (AF_INET,
+                                     SOCK_DGRAM,
+                                     0);
+  if (NULL == ls)
+    return NULL;
+  if (GNUNET_OK !=
+      GNUNET_NETWORK_socket_bind (ls, (const struct sockaddr *) &sa4,
+                                  sizeof(sa4)))
+  {
+    eno = errno;
+    GNUNET_NETWORK_socket_close (ls);
+    errno = eno;
+    return NULL;
+  }
+  return ls;
+}
+
+
+static void
+request_callback (void *cls,
+                  enum GNUNET_NAT_StatusCode result)
+{
+  // struct GNUNET_NAT_AutoHandle *ah = cls;
+
+  GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+              "Request callback: stop and quit\n");
+  stop_stun ();
+
+  // next_phase (ah); FIXME this always will be NULL, as called in test_stun()
+}
+
+
+/**
+ * Function called by NAT to report the outcome of the nat-test.
+ * Clean up and update GUI.
+ *
+ * @param cls the auto handle
+ * @param success currently always #GNUNET_OK
+ * @param emsg NULL on success, otherwise an error message
+ */
+static void
+result_callback (void *cls,
+                 enum GNUNET_NAT_StatusCode ret)
+{
+  struct GNUNET_NAT_AutoHandle *ah = cls;
+
+  if (GNUNET_NAT_ERROR_SUCCESS == ret)
+    GNUNET_NAT_test_stop (ah->tst);
+  ah->tst = NULL;
+  ah->ret = ret;
+  GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+              GNUNET_NAT_ERROR_SUCCESS == ret
+              ? _ ("NAT traversal with ICMP Server succeeded.\n")
+              : _ ("NAT traversal with ICMP Server failed.\n"));
+  GNUNET_CONFIGURATION_set_value_string (ah->cfg, "nat", "ENABLE_ICMP_SERVER",
+                                         GNUNET_NAT_ERROR_SUCCESS == ret ?
+                                         "NO" : "YES");
+  next_phase (ah);
+}
+
+
+/**
+ * Main function for the connection reversal test.
+ *
+ * @param cls the `struct GNUNET_NAT_AutoHandle`
+ */
+static void
+reversal_test (void *cls)
+{
+  struct GNUNET_NAT_AutoHandle *ah = cls;
+
+  ah->task = NULL;
+  GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+              _ ("Testing connection reversal with ICMP server.\n"));
+  GNUNET_RESOLVER_connect (ah->cfg);
+  ah->tst = GNUNET_NAT_test_start (ah->cfg, GNUNET_YES, 0, 0, TIMEOUT,
+                                   &result_callback, ah);
+}
+
+
+/**
+ * Set our external IPv4 address based on the UPnP.
+ *
+ *
+ * @param cls closure with our setup context
+ * @param addr the address, NULL on errors
+ * @param emsg NULL on success, otherwise an error message
+ */
+static void
+set_external_ipv4 (void *cls,
+                   const struct in_addr *addr,
+                   enum GNUNET_NAT_StatusCode ret)
+{
+  struct GNUNET_NAT_AutoHandle *ah = cls;
+  char buf[INET_ADDRSTRLEN];
+
+  ah->eh = NULL;
+  ah->ret = ret;
+  if (GNUNET_NAT_ERROR_SUCCESS != ret)
+  {
+    next_phase (ah);
+    return;
+  }
+  /* enable 'behind nat' */
+  GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+              _ ("Detected external IP `%s'\n"),
+              inet_ntop (AF_INET,
+                         addr,
+                         buf,
+                         sizeof(buf)));
+  GNUNET_CONFIGURATION_set_value_string (ah->cfg, "nat", "BEHIND_NAT", "YES");
+
+  /* set external IP address */
+  if (NULL == inet_ntop (AF_INET, addr, buf, sizeof(buf)))
+  {
+    GNUNET_break (0);
+    /* actually, this should never happen, as the caller already executed just
+     * this check, but for consistency (eg: future changes in the caller)
+     * we still need to report this error...
+     */
+    ah->ret = GNUNET_NAT_ERROR_EXTERNAL_IP_ADDRESS_INVALID;
+    next_phase (ah);
+    return;
+  }
+  GNUNET_CONFIGURATION_set_value_string (ah->cfg, "nat", "EXTERNAL_ADDRESS",
+                                         buf);
+  ah->upnp_set_external_address = GNUNET_YES;
+  next_phase (ah);
+}
+
+
+/**
+ * Determine our external IPv4 address.
+ *
+ * @param ah auto setup context
+ */
+static void
+test_external_ip (struct GNUNET_NAT_AutoHandle *ah)
+{
+  if (GNUNET_NAT_ERROR_SUCCESS != ah->ret)
+    next_phase (ah);
+
+  // FIXME: CPS?
+  /* try to detect external IP */
+  ah->eh = GNUNET_NAT_mini_get_external_ipv4 (TIMEOUT,
+                                              &set_external_ipv4, ah);
+}
+
+
+/**
+ * Determine our external IPv4 address and port using an external STUN server
+ *
+ * @param ah auto setup context
+ */
+static void
+test_stun (struct GNUNET_NAT_AutoHandle *ah)
+{
+  GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Running STUN test\n");
+
+  /* Get port from the configuration */
+  if (GNUNET_OK !=
+      GNUNET_CONFIGURATION_get_value_number (ah->cfg,
+                                             "transport-udp",
+                                             "PORT",
+                                             &port))
+  {
+    port = 2086;
+  }
+
+  // Lets create the socket
+  lsock4 = bind_v4 ();
+  if (NULL == lsock4)
+  {
+    GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "bind");
+    next_phase (ah);
+    return;
+  }
+  else
+  {
+    // Lets call our function now when it accepts
+    ltask4 = GNUNET_SCHEDULER_add_read_net (NAT_SERVER_TIMEOUT,
+                                            lsock4,
+                                            &do_udp_read,
+                                            ah);
+  }
+
+
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "STUN service listens on port %u\n",
+              (unsigned int) port);
+  if (GNUNET_NO ==
+      GNUNET_NAT_stun_make_request (stun_server,
+                                    stun_port,
+                                    lsock4,
+                                    &request_callback,
+                                    NULL))
+  {
+    /*An error happened*/
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "STUN error, stopping\n");
+    stop_stun ();
+    next_phase (ah);
+  }
+}
+
+
+/**
+ * Process list of local IP addresses.  Find and set the
+ * one of the default interface.
+ *
+ * @param cls our `struct GNUNET_NAT_AutoHandle`
+ * @param name name of the interface (can be NULL for unknown)
+ * @param isDefault is this presumably the default interface
+ * @param addr address of this interface (can be NULL for unknown or unassigned)
+ * @param broadcast_addr the broadcast address (can be NULL for unknown or unassigned)
+ * @param netmask the network mask (can be NULL for unknown or unassigned))
+ * @param addrlen length of the @a addr and @a broadcast_addr
+ * @return #GNUNET_OK to continue iteration, #GNUNET_SYSERR to abort
+ */
+static int
+process_if (void *cls,
+            const char *name,
+            int isDefault,
+            const struct sockaddr *addr,
+            const struct sockaddr *broadcast_addr,
+            const struct sockaddr *netmask,
+            socklen_t addrlen)
+{
+  struct GNUNET_NAT_AutoHandle *ah = cls;
+  const struct sockaddr_in *in;
+  char buf[INET_ADDRSTRLEN];
+
+
+  if ((sizeof(struct sockaddr_in6) == addrlen) &&
+      (0 != GNUNET_memcmp (&in6addr_loopback, &((const struct
+                                                 sockaddr_in6 *) addr)->
+                           sin6_addr)) &&
+      (! IN6_IS_ADDR_LINKLOCAL (&((const struct
+                                   sockaddr_in6 *) addr)->sin6_addr)))
+  {
+    ah->have_v6 = GNUNET_YES;
+    GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+                _ (
+                  "This system has a global IPv6 address, setting IPv6 to supported.\n"));
+
+    return GNUNET_OK;
+  }
+  if (addrlen != sizeof(struct sockaddr_in))
+    return GNUNET_OK;
+  in = (const struct sockaddr_in *) addr;
+
+
+  /* set internal IP address */
+  if (NULL == inet_ntop (AF_INET, &in->sin_addr, buf, sizeof(buf)))
+  {
+    GNUNET_break (0);
+    return GNUNET_OK;
+  }
+  GNUNET_CONFIGURATION_set_value_string (ah->cfg, "nat", "INTERNAL_ADDRESS",
+                                         buf);
+  GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+              _ ("Detected internal network address `%s'.\n"),
+              buf);
+
+
+  ah->ret = GNUNET_NAT_ERROR_SUCCESS;
+
+  /* Check if our internal IP is the same as the External detect by STUN*/
+  if (ah->stun_ip && (strcmp (buf, ah->stun_ip) == 0))
+  {
+    ah->internal_ip_is_public = GNUNET_YES;
+    GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+                "A internal IP is the sameas the external");
+    /* No need to continue*/
+    return GNUNET_SYSERR;
+  }
+
+  /* no need to continue iteration if we found the default */
+  if (! isDefault)
+    return GNUNET_OK;
+  else
+    return GNUNET_SYSERR;
+}
+
+
+/**
+ * Determine our local IP addresses; detect internal IP & IPv6-support
+ *
+ * @param ah auto setup context
+ */
+static void
+test_local_ip (struct GNUNET_NAT_AutoHandle *ah)
+{
+  ah->have_v6 = GNUNET_NO;
+  ah->ret = GNUNET_NAT_ERROR_NO_VALID_IF_IP_COMBO; // reset to success if any of the IFs in below iterator has a valid IP
+  GNUNET_OS_network_interfaces_list (&process_if, ah);
+
+  GNUNET_CONFIGURATION_set_value_string (ah->cfg, "nat", "DISABLEV6",
+                                         (GNUNET_YES == ah->have_v6) ? "NO" :
+                                         "YES");
+  next_phase (ah);
+}
+
+
+/**
+ * We got disconnected from the NAT server.  Stop
+ * waiting for a reply.
+ *
+ * @param cls the `struct GNUNET_NAT_AutoHandle`
+ * @param error error code
+ */
+static void
+mq_error_handler (void *cls,
+                  enum GNUNET_MQ_Error error)
+{
+  struct GNUNET_NAT_AutoHandle *ah = cls;
+
+  GNUNET_MQ_destroy (ah->mq);
+  ah->mq = NULL;
+  /* wait a bit first? */
+  next_phase (ah);
+}
+
+
+/**
+ * Test if NAT has been punched
+ *
+ * @param ah auto setup context
+ */
+static void
+test_nat_punched (struct GNUNET_NAT_AutoHandle *ah)
+{
+  struct GNUNET_NAT_TestMessage *msg;
+  struct GNUNET_MQ_Envelope *env;
+
+  if (! ah->stun_ip)
+  {
+    LOG (GNUNET_ERROR_TYPE_INFO,
+         "We don't have a STUN IP");
+    next_phase (ah);
+    return;
+  }
+
+  LOG (GNUNET_ERROR_TYPE_INFO,
+       "Asking gnunet-nat-server to connect to `%s'\n",
+       ah->stun_ip);
+  ah->mq = GNUNET_CLIENT_connect (ah->cfg,
+                                  "gnunet-nat-server",
+                                  NULL,
+                                  &mq_error_handler,
+                                  ah);
+  if (NULL == ah->mq)
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                _ ("Failed to connect to `gnunet-nat-server'\n"));
+    next_phase (ah);
+    return;
+  }
+  env = GNUNET_MQ_msg (msg,
+                       GNUNET_MESSAGE_TYPE_NAT_TEST);
+  msg->dst_ipv4 = inet_addr (ah->stun_ip);
+  msg->dport = htons (ah->stun_port);
+  msg->data = port;
+  msg->is_tcp = htonl ((uint32_t) GNUNET_NO);
+  GNUNET_MQ_send (ah->mq,
+                  env);
+  if (NULL != ltask4)
+  {
+    GNUNET_SCHEDULER_cancel (ltask4);
+    ltask4 = GNUNET_SCHEDULER_add_read_net (NAT_SERVER_TIMEOUT,
+                                            lsock4,
+                                            &do_udp_read,
+                                            ah);
+  }
+}
+
+
+/**
+ * Test if UPnPC works.
+ *
+ * @param ah auto setup context
+ */
+static void
+test_upnpc (struct GNUNET_NAT_AutoHandle *ah)
+{
+  int have_upnpc;
+
+  if (GNUNET_NAT_ERROR_SUCCESS != ah->ret)
+    next_phase (ah);
+
+  // test if upnpc is available
+  have_upnpc = (GNUNET_SYSERR !=
+                GNUNET_OS_check_helper_binary ("upnpc", GNUNET_NO, NULL));
+  // FIXME: test if upnpc is actually working, that is, if transports start to work once we use UPnP
+  GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+              (have_upnpc)
+              ? _ ("upnpc found, enabling its use\n")
+              : _ ("upnpc not found\n"));
+  GNUNET_CONFIGURATION_set_value_string (ah->cfg, "nat", "ENABLE_UPNP",
+                                         (GNUNET_YES == have_upnpc) ? "YES" :
+                                         "NO");
+  next_phase (ah);
+}
+
+
+/**
+ * Test if ICMP server is working
+ *
+ * @param ah auto setup context
+ */
+static void
+test_icmp_server (struct GNUNET_NAT_AutoHandle *ah)
+{
+  int ext_ip;
+  int nated;
+  int binary;
+  char *tmp;
+  char *helper;
+
+  ext_ip = GNUNET_NO;
+  nated = GNUNET_NO;
+  binary = GNUNET_NO;
+
+  tmp = NULL;
+  helper = GNUNET_OS_get_libexec_binary_path ("gnunet-helper-nat-server");
+  if ((GNUNET_OK ==
+       GNUNET_CONFIGURATION_get_value_string (ah->cfg,
+                                              "nat",
+                                              "EXTERNAL_ADDRESS",
+                                              &tmp)) &&
+      (0 < strlen (tmp)))
+  {
+    ext_ip = GNUNET_OK;
+    GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+                _ (
+                  "test_icmp_server not possible, as we have no public IPv4 address\n"));
+  }
+  else
+    goto err;
+
+  if (GNUNET_YES ==
+      GNUNET_CONFIGURATION_get_value_yesno (ah->cfg,
+                                            "nat",
+                                            "BEHIND_NAT"))
+  {
+    nated = GNUNET_YES;
+    GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+                _ (
+                  "test_icmp_server not possible, as we are not behind NAT\n"));
+  }
+  else
+    goto err;
+
+  if (GNUNET_YES ==
+      GNUNET_OS_check_helper_binary (helper,
+                                     GNUNET_YES,
+                                     "-d 127.0.0.1"))
+  {
+    binary = GNUNET_OK;   // use localhost as source for that one udp-port, ok for testing
+    GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+                _ ("No working gnunet-helper-nat-server found\n"));
+  }
+err:
+  GNUNET_free (tmp);
+  GNUNET_free (helper);
+
+  if ((GNUNET_OK == ext_ip) &&
+      (GNUNET_YES == nated) &&
+      (GNUNET_OK == binary))
+    ah->task = GNUNET_SCHEDULER_add_now (&reversal_test,
+                                         ah);
+  else
+    next_phase (ah);
+}
+
+
+/**
+ * Test if ICMP client is working
+ *
+ * @param ah auto setup context
+ */
+static void
+test_icmp_client (struct GNUNET_NAT_AutoHandle *ah)
+{
+  char *tmp;
+  char *helper;
+
+  tmp = NULL;
+  helper = GNUNET_OS_get_libexec_binary_path ("gnunet-helper-nat-client");
+  if ((GNUNET_OK ==
+       GNUNET_CONFIGURATION_get_value_string (ah->cfg,
+                                              "nat",
+                                              "INTERNAL_ADDRESS",
+                                              &tmp)) &&
+      (0 < strlen (tmp)))
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+                _ (
+                  "test_icmp_client not possible, as we have no internal IPv4 address\n"));
+  }
+  else
+    goto err;
+
+  if (GNUNET_YES !=
+      GNUNET_CONFIGURATION_get_value_yesno (ah->cfg,
+                                            "nat",
+                                            "BEHIND_NAT"))
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+                _ (
+                  "test_icmp_server not possible, as we are not behind NAT\n"));
+  }
+  else
+    goto err;
+
+  if (GNUNET_YES ==
+      GNUNET_OS_check_helper_binary (helper,
+                                     GNUNET_YES,
+                                     "-d 127.0.0.1 127.0.0.2 42"))
+  {
+    // none of these parameters are actually used in privilege testing mode
+    GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+                _ ("No working gnunet-helper-nat-server found\n"));
+  }
+err:
+  GNUNET_free (tmp);
+  GNUNET_free (helper);
+
+  next_phase (ah);
+}
+
+
+/**
+ * Run the next phase of the auto test.
+ */
+static void
+next_phase (struct GNUNET_NAT_AutoHandle *ah)
+{
+  struct GNUNET_CONFIGURATION_Handle *diff;
+
+  ah->phase++;
+  switch (ah->phase)
+  {
+  case AUTO_INIT:
+    GNUNET_assert (0);
+    break;
+
+  case AUTO_EXTERNAL_IP:
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                "Will run AUTO_EXTERNAL_IP\n");
+    test_external_ip (ah);
+    break;
+
+  case AUTO_STUN:
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                "Will run AUTO_STUN\n");
+    test_stun (ah);
+    break;
+
+  case AUTO_LOCAL_IP:
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                "Will run AUTO_LOCAL_IP\n");
+    test_local_ip (ah);
+    break;
+
+  case AUTO_NAT_PUNCHED:
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                "Will run AUTO_NAT_PUNCHED\n");
+    test_nat_punched (ah);
+    break;
+
+  case AUTO_UPNPC:
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                "Will run AUTO_UPNPC\n");
+    test_upnpc (ah);
+    break;
+
+  case AUTO_ICMP_SERVER:
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                "Will run AUTO_ICMP_SERVER\n");
+    test_icmp_server (ah);
+    break;
+
+  case AUTO_ICMP_CLIENT:
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                "Will run AUTO_ICMP_CLIENT\n");
+    test_icmp_client (ah);
+    break;
+
+  case AUTO_DONE:
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                "Done with tests\n");
+    if (! ah->internal_ip_is_public)
+    {
+      GNUNET_CONFIGURATION_set_value_string (ah->cfg,
+                                             "nat",
+                                             "BEHIND_NAT",
+                                             "YES");
+
+      if (ah->connected_back)
+      {
+        GNUNET_CONFIGURATION_set_value_string (ah->cfg,
+                                               "nat",
+                                               "PUNCHED_NAT",
+                                               "YES");
+      }
+      else
+      {
+        GNUNET_CONFIGURATION_set_value_string (ah->cfg,
+                                               "nat",
+                                               "PUNCHED_NAT",
+                                               "NO");
+      }
+
+      if (ah->stun_ip)
+      {
+        GNUNET_CONFIGURATION_set_value_string (ah->cfg,
+                                               "nat",
+                                               "EXTERNAL_ADDRESS",
+                                               ah->stun_ip);
+        if (ah->connected_back)
+        {
+          ah->type = GNUNET_NAT_TYPE_STUN_PUNCHED_NAT;
+          GNUNET_CONFIGURATION_set_value_string (ah->cfg,
+                                                 "nat",
+                                                 "USE_STUN",
+                                                 "YES");
+        }
+        else
+        {
+          ah->type = GNUNET_NAT_TYPE_UNREACHABLE_NAT;
+          GNUNET_CONFIGURATION_set_value_string (ah->cfg,
+                                                 "nat",
+                                                 "USE_STUN",
+                                                 "NO");
+        }
+      }
+      if (0 != ah->stun_port)
+      {
+        GNUNET_CONFIGURATION_set_value_number (ah->cfg,
+                                               "transport-udp",
+                                               "ADVERTISED_PORT",
+                                               ah->stun_port);
+      }
+    }
+    else
+    {
+      // The internal IP is the same as public, but we didn't got a incoming connection
+      if (ah->connected_back)
+      {
+        ah->type = GNUNET_NAT_TYPE_NO_NAT;
+        GNUNET_CONFIGURATION_set_value_string (ah->cfg,
+                                               "nat",
+                                               "BEHIND_NAT",
+                                               "NO");
+      }
+      else
+      {
+        GNUNET_CONFIGURATION_set_value_string (ah->cfg,
+                                               "nat",
+                                               "BEHIND_NAT",
+                                               "YES");
+        ah->type = GNUNET_NAT_TYPE_UNREACHABLE_NAT;
+        if (ah->stun_ip)
+        {
+          GNUNET_CONFIGURATION_set_value_string (ah->cfg,
+                                                 "nat",
+                                                 "EXTERNAL_ADDRESS",
+                                                 ah->stun_ip);
+        }
+        if (0 != ah->stun_port)
+        {
+          GNUNET_CONFIGURATION_set_value_number (ah->cfg,
+                                                 "transport-udp",
+                                                 "ADVERTISED_PORT",
+                                                 ah->stun_port);
+        }
+      }
+    }
+
+    diff = GNUNET_CONFIGURATION_get_diff (ah->initial_cfg,
+                                          ah->cfg);
+
+
+    ah->fin_cb (ah->fin_cb_cls,
+                diff,
+                ah->ret,
+                ah->type);
+    GNUNET_CONFIGURATION_destroy (diff);
+    GNUNET_NAT_autoconfig_cancel (ah);
+  }
+}
+
+
+/**
+ * Start auto-configuration routine.  The resolver service should
+ * be available when this function is called.
+ *
+ * @param cfg initial configuration
+ * @param cb function to call with autoconfiguration result
+ * @param cb_cls closure for @a cb
+ * @return handle to cancel operation
+ */
+struct GNUNET_NAT_AutoHandle *
+GNUNET_NAT_autoconfig_start (const struct GNUNET_CONFIGURATION_Handle *cfg,
+                             GNUNET_NAT_AutoResultCallback cb,
+                             void *cb_cls)
+{
+  struct GNUNET_NAT_AutoHandle *ah;
+
+  ah = GNUNET_new (struct GNUNET_NAT_AutoHandle);
+  ah->fin_cb = cb;
+  ah->fin_cb_cls = cb_cls;
+  ah->ret = GNUNET_NAT_ERROR_SUCCESS;
+  ah->cfg = GNUNET_CONFIGURATION_dup (cfg);
+  ah->initial_cfg = GNUNET_CONFIGURATION_dup (cfg);
+
+  /* never use loopback addresses if user wanted autoconfiguration */
+  GNUNET_CONFIGURATION_set_value_string (ah->cfg,
+                                         "nat",
+                                         "USE_LOCALADDR",
+                                         "NO");
+
+  next_phase (ah);
+  return ah;
+}
+
+
+/**
+ * Abort autoconfiguration.
+ *
+ * @param ah handle for operation to abort
+ */
+void
+GNUNET_NAT_autoconfig_cancel (struct GNUNET_NAT_AutoHandle *ah)
+{
+  if (NULL != ah->tst)
+  {
+    GNUNET_NAT_test_stop (ah->tst);
+    ah->tst = NULL;
+  }
+  if (NULL != ah->eh)
+  {
+    GNUNET_NAT_mini_get_external_ipv4_cancel (ah->eh);
+    ah->eh = NULL;
+  }
+  if (NULL != ah->mq)
+  {
+    GNUNET_MQ_destroy (ah->mq);
+    ah->mq = NULL;
+  }
+  if (NULL != ah->task)
+  {
+    GNUNET_SCHEDULER_cancel (ah->task);
+    ah->task = NULL;
+  }
+  GNUNET_CONFIGURATION_destroy (ah->cfg);
+  GNUNET_CONFIGURATION_destroy (ah->initial_cfg);
+  GNUNET_free (ah);
+}
+
+
+/* end of nat_auto.c */
diff --git a/src/nat/.gitignore b/src/nat/.gitignore
new file mode 100644
index 0000000000000000000000000000000000000000..868abab4b22167ff3b29be24aae534af0ecea8d9
--- /dev/null
+++ b/src/nat/.gitignore
@@ -0,0 +1,5 @@
+gnunet-service-nat
+gnunet-helper-nat-client
+gnunet-helper-nat-server
+gnunet-nat
+gnunet-nat-server
diff --git a/src/nat/gnunet-nat-client-script.sh b/src/nat/gnunet-nat-client-script.sh
new file mode 100755
index 0000000000000000000000000000000000000000..4e4ccafadca7e07631b4cea55c97f93b024e937d
--- /dev/null
+++ b/src/nat/gnunet-nat-client-script.sh
@@ -0,0 +1,4 @@
+#!/bin/sh
+IP=`ifconfig | grep inet | head -n1 | awk '{print $2}' | sed -e "s/addr://"`
+echo "Using IP $IP, trying to connect to $1"
+./gnunet-nat-client-udp $IP $1
diff --git a/src/nat/gnunet-nat-server-script.sh b/src/nat/gnunet-nat-server-script.sh
new file mode 100755
index 0000000000000000000000000000000000000000..42a8e639a6fcf209a8103f2a9f81e42ec063a439
--- /dev/null
+++ b/src/nat/gnunet-nat-server-script.sh
@@ -0,0 +1,4 @@
+#!/bin/sh
+IP=`ifconfig | grep inet | head -n1 | awk '{print $2}' | sed -e "s/addr://"`
+echo "Using IP $IP"
+./gnunet-nat-server $IP | sed -u -e "s/.*/.\/gnunet-nat-server-udp $IP &\&/" | sh
diff --git a/src/nat/gnunet-service-nat_helper.c b/src/nat/gnunet-service-nat_helper.c
index 58d7b4c61876f79aa7c042a82b59c7c1cd84e249..bd1645d25f8a15035c2740de9e0e44de0961bae1 100644
--- a/src/nat/gnunet-service-nat_helper.c
+++ b/src/nat/gnunet-service-nat_helper.c
@@ -222,7 +222,7 @@ restart_nat_server (void *cls)
     return;
   }
   h->server_stdout =
-    GNUNET_DISK_pipe (GNUNET_YES, GNUNET_YES, GNUNET_NO, GNUNET_YES);
+    GNUNET_DISK_pipe (GNUNET_DISK_PF_BLOCKING_RW);
   if (NULL == h->server_stdout)
   {
     GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "pipe");
@@ -234,8 +234,7 @@ restart_nat_server (void *cls)
               "Starting `%s' at `%s'\n",
               "gnunet-helper-nat-server",
               ia);
-  h->server_proc = GNUNET_OS_start_process (GNUNET_NO,
-                                            0,
+  h->server_proc = GNUNET_OS_start_process (GNUNET_OS_INHERIT_STD_NONE,
                                             NULL,
                                             h->server_stdout,
                                             NULL,
@@ -378,8 +377,7 @@ GN_request_connection_reversal (const struct in_addr *internal_address,
               remv4,
               internal_port);
   binary = GNUNET_OS_get_suid_binary_path (cfg, "gnunet-helper-nat-client");
-  proc = GNUNET_OS_start_process (GNUNET_NO,
-                                  0,
+  proc = GNUNET_OS_start_process (GNUNET_OS_INHERIT_STD_NONE,
                                   NULL,
                                   NULL,
                                   NULL,
diff --git a/src/nat/gnunet-service-nat_mini.c b/src/nat/gnunet-service-nat_mini.c
index ae94e3f5b0776fbbeec5441c0bd8762140cb1021..24f77d9cc39e5980dd6a249f371ade5481d4e78b 100644
--- a/src/nat/gnunet-service-nat_mini.c
+++ b/src/nat/gnunet-service-nat_mini.c
@@ -192,15 +192,14 @@ GNUNET_NAT_mini_get_external_ipv4_ (GNUNET_NAT_IPCallback cb, void *cb_cls)
   }
   LOG (GNUNET_ERROR_TYPE_DEBUG,
        "Running `external-ip' to determine our external IP\n");
-  eh->opipe = GNUNET_DISK_pipe (GNUNET_YES, GNUNET_YES, GNUNET_NO, GNUNET_YES);
+  eh->opipe = GNUNET_DISK_pipe (GNUNET_DISK_PF_BLOCKING_RW);
   if (NULL == eh->opipe)
   {
     eh->ret = GNUNET_NAT_ERROR_IPC_FAILURE;
     eh->task = GNUNET_SCHEDULER_add_now (&signal_external_ip_error, eh);
     return eh;
   }
-  eh->eip = GNUNET_OS_start_process (GNUNET_NO,
-                                     0,
+  eh->eip = GNUNET_OS_start_process (GNUNET_OS_INHERIT_STD_NONE,
                                      NULL,
                                      eh->opipe,
                                      NULL,
diff --git a/src/nat/test_nat.c b/src/nat/test_nat.c
new file mode 100644
index 0000000000000000000000000000000000000000..a3072f71274e0d6e1720cf26396b1a63b962b956
--- /dev/null
+++ b/src/nat/test_nat.c
@@ -0,0 +1,192 @@
+/*
+     This file is part of GNUnet.
+     Copyright (C) 2009, 2011 GNUnet e.V.
+
+     GNUnet is free software: you can redistribute it and/or modify it
+     under the terms of the GNU Affero General Public License as published
+     by the Free Software Foundation, either version 3 of the License,
+     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
+     Affero General Public License for more details.
+
+     You should have received a copy of the GNU Affero General Public License
+     along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+     SPDX-License-Identifier: AGPL3.0-or-later
+ */
+
+/**
+ * Testcase for port redirection and public IP address retrieval.
+ * This test never fails, because there need to be a NAT box set up for that.
+ * So we only get IP address and open the 2086 port using any NAT traversal
+ * method available, wait for 30s, close ports and return.
+ * Have a look at the logs and use NMAP to check that it works with your box.
+ *
+ * @file nat/test_nat.c
+ * @brief Testcase for NAT library
+ * @author Milan Bouchet-Valat
+ * @author Christian Grothoff
+ *
+ * TODO: actually use ARM to start resolver service to make DNS work!
+ */
+
+#include "platform.h"
+#include "gnunet_util_lib.h"
+#include "gnunet_program_lib.h"
+#include "gnunet_scheduler_lib.h"
+#include "gnunet_nat_lib.h"
+
+
+/**
+ * Time to wait before stopping NAT, in seconds
+ */
+#define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 5)
+
+
+/**
+ * Function called on each address that the NAT service
+ * believes to be valid for the transport.
+ */
+static void
+addr_callback (void *cls, int add_remove, const struct sockaddr *addr,
+               socklen_t addrlen)
+{
+  GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+              "Address changed: %s `%s' (%u bytes)\n",
+              add_remove == GNUNET_YES ? "added" : "removed",
+              GNUNET_a2s (addr,
+                          addrlen),
+              (unsigned int) addrlen);
+}
+
+
+/**
+ * Function that terminates the test.
+ */
+static void
+stop (void *cls)
+{
+  struct GNUNET_NAT_Handle *nat = cls;
+
+  GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+              "Stopping NAT and quitting...\n");
+  GNUNET_NAT_unregister (nat);
+}
+
+
+struct addr_cls
+{
+  struct sockaddr *addr;
+  socklen_t addrlen;
+};
+
+
+/**
+ * Return the address of the default interface,
+ * or any interface with a valid address if the default is not valid
+ *
+ * @param cls the 'struct addr_cls'
+ * @param name name of the interface
+ * @param isDefault do we think this may be our default interface
+ * @param addr address of the interface
+ * @param addrlen number of bytes in @a addr
+ * @return #GNUNET_OK to continue iterating
+ */
+static int
+process_if (void *cls,
+            const char *name,
+            int isDefault,
+            const struct sockaddr *addr,
+            const struct sockaddr *broadcast_addr,
+            const struct sockaddr *netmask,
+            socklen_t addrlen)
+{
+  struct addr_cls *data = cls;
+
+  if (addr == NULL)
+    return GNUNET_OK;
+  GNUNET_free (data->addr);
+  data->addr = GNUNET_malloc (addrlen);
+  GNUNET_memcpy (data->addr, addr, addrlen);
+  data->addrlen = addrlen;
+  if (isDefault)
+    return GNUNET_SYSERR;
+  return GNUNET_OK;
+}
+
+
+/**
+ * Main function run with scheduler.
+ */
+static void
+run (void *cls,
+     char *const *args,
+     const char *cfgfile,
+     const struct GNUNET_CONFIGURATION_Handle *cfg)
+{
+  struct GNUNET_NAT_Handle *nat;
+  struct addr_cls data;
+  struct sockaddr *addr;
+
+  data.addr = NULL;
+  GNUNET_OS_network_interfaces_list (process_if, &data);
+  if (NULL == data.addr)
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                "Could not find a valid interface address!\n");
+    exit (77);  /* marks test as skipped */
+  }
+  addr = data.addr;
+  GNUNET_assert (addr->sa_family == AF_INET || addr->sa_family == AF_INET6);
+  if (addr->sa_family == AF_INET)
+    ((struct sockaddr_in *) addr)->sin_port = htons (2086);
+  else
+    ((struct sockaddr_in6 *) addr)->sin6_port = htons (2086);
+
+  GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+              "Requesting NAT redirection from address %s...\n",
+              GNUNET_a2s (addr, data.addrlen));
+
+  nat = GNUNET_NAT_register (cfg, GNUNET_YES /* tcp */,
+                             2086, 1, (const struct sockaddr **) &addr,
+                             &data.addrlen, &addr_callback, NULL, NULL, NULL);
+  GNUNET_free (addr);
+  GNUNET_SCHEDULER_add_delayed (TIMEOUT, &stop, nat);
+}
+
+
+int
+main (int argc, char *const argv[])
+{
+  struct GNUNET_GETOPT_CommandLineOption options[] = {
+    GNUNET_GETOPT_OPTION_END
+  };
+
+  char *const argv_prog[] = {
+    "test-nat",
+    "-c",
+    "test_nat_data.conf",
+    NULL
+  };
+
+  GNUNET_log_setup ("test-nat",
+                    "WARNING",
+                    NULL);
+  GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+              "Testing NAT library, timeout set to %s\n",
+              GNUNET_STRINGS_relative_time_to_string (TIMEOUT,
+                                                      GNUNET_YES));
+  GNUNET_PROGRAM_run (3,
+                      argv_prog,
+                      "test-nat",
+                      "nohelp",
+                      options,
+                      &run, NULL);
+  return 0;
+}
+
+
+/* end of test_nat.c */
diff --git a/src/nat/test_nat_mini.c b/src/nat/test_nat_mini.c
new file mode 100644
index 0000000000000000000000000000000000000000..8cbd4131dbe36d6ccc5a27dd1e4a863b6eea73f4
--- /dev/null
+++ b/src/nat/test_nat_mini.c
@@ -0,0 +1,134 @@
+/*
+     This file is part of GNUnet.
+     Copyright (C) 2009, 2011 GNUnet e.V.
+
+     GNUnet is free software: you can redistribute it and/or modify it
+     under the terms of the GNU Affero General Public License as published
+     by the Free Software Foundation, either version 3 of the License,
+     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
+     Affero General Public License for more details.
+
+     You should have received a copy of the GNU Affero General Public License
+     along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+     SPDX-License-Identifier: AGPL3.0-or-later
+ */
+
+/**
+ * Testcase for port redirection and public IP address retrieval.
+ * This test never fails, because there need to be a NAT box set up for tha *
+ * @file nat/test_nat_mini.c
+ * @brief Testcase for NAT library - mini
+ * @author Christian Grothoff
+ *
+ * TODO: actually use ARM to start resolver service to make DNS work!
+ */
+
+#include "platform.h"
+#include "gnunet_util_lib.h"
+#include "gnunet_program_lib.h"
+#include "gnunet_scheduler_lib.h"
+#include "gnunet_nat_lib.h"
+
+/* Time to wait before stopping NAT, in seconds */
+#define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 5)
+
+/**
+ * Function called on each address that the NAT service
+ * believes to be valid for the transport.
+ */
+static void
+addr_callback (void *cls, int add_remove,
+               const struct sockaddr *addr,
+               socklen_t addrlen,
+               enum GNUNET_NAT_StatusCode ret)
+{
+  if (GNUNET_NAT_ERROR_SUCCESS == ret)
+  {
+    fprintf (stderr,
+             "Address changed: %s `%s' (%u bytes)\n",
+             add_remove == GNUNET_YES
+             ? "added" : "removed",
+             GNUNET_a2s (addr,
+                         addrlen),
+             (unsigned int) addrlen);
+  }
+  else
+    ;
+  // TODO: proper error handling!
+}
+
+
+/**
+ * Function that terminates the test.
+ */
+static void
+stop (void *cls)
+{
+  struct GNUNET_NAT_MiniHandle *mini = cls;
+
+  GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Stopping NAT and quitting...\n");
+  GNUNET_NAT_mini_map_stop (mini);
+}
+
+
+#define PORT 10000
+
+/**
+ * Main function run with scheduler.
+ */
+static void
+run (void *cls, char *const *args, const char *cfgfile,
+     const struct GNUNET_CONFIGURATION_Handle *cfg)
+{
+  struct GNUNET_NAT_MiniHandle *mini;
+
+  GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+              "Requesting NAT redirection for port %u...\n",
+              PORT);
+  mini = GNUNET_NAT_mini_map_start (PORT, GNUNET_YES /* tcp */,
+                                    &addr_callback, NULL);
+  if (NULL == mini)
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Could not start UPnP interaction\n");
+    return;
+  }
+  GNUNET_SCHEDULER_add_delayed (TIMEOUT, &stop, mini);
+}
+
+
+int
+main (int argc, char *const argv[])
+{
+  struct GNUNET_GETOPT_CommandLineOption options[] = {
+    GNUNET_GETOPT_OPTION_END
+  };
+
+  char *const argv_prog[] = {
+    "test-nat-mini",
+    "-c",
+    "test_nat_data.conf",
+    "-L",
+    "WARNING",
+    NULL
+  };
+
+  GNUNET_log_setup ("test-nat-mini",
+                    "WARNING",
+                    NULL);
+
+  GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+              "UPnP test for NAT library, timeout set to %s\n",
+              GNUNET_STRINGS_relative_time_to_string (TIMEOUT,
+                                                      GNUNET_YES));
+  GNUNET_PROGRAM_run (5, argv_prog, "test-nat-mini", "nohelp", options, &run,
+                      NULL);
+  return 0;
+}
+
+
+/* end of test_nat_mini.c */
diff --git a/src/nat/test_nat_test.c b/src/nat/test_nat_test.c
new file mode 100644
index 0000000000000000000000000000000000000000..2abab4d5f78dd933d2873784276aa3400c99be1e
--- /dev/null
+++ b/src/nat/test_nat_test.c
@@ -0,0 +1,142 @@
+/*
+     This file is part of GNUnet.
+     Copyright (C) 2009, 2011, 2014 GNUnet e.V.
+
+     GNUnet is free software: you can redistribute it and/or modify it
+     under the terms of the GNU Affero General Public License as published
+     by the Free Software Foundation, either version 3 of the License,
+     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
+     Affero General Public License for more details.
+
+     You should have received a copy of the GNU Affero General Public License
+     along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+     SPDX-License-Identifier: AGPL3.0-or-later
+ */
+/**
+ * @file nat/test_nat_test.c
+ * @brief Testcase for NAT testing functions
+ * @author Christian Grothoff
+ */
+#include "platform.h"
+#include "gnunet_util_lib.h"
+#include "gnunet_nat_lib.h"
+
+/**
+ * Time to wait before stopping NAT test, in seconds
+ */
+#define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 15)
+
+
+static int ret = 1;
+
+static struct GNUNET_NAT_Test *tst;
+
+static struct GNUNET_SCHEDULER_Task *tsk;
+
+
+static void
+report_result (void *cls,
+               enum GNUNET_NAT_StatusCode aret)
+{
+  if (GNUNET_NAT_ERROR_TIMEOUT == aret)
+    fprintf (stderr,
+             "NAT test timed out\n");
+  else if (GNUNET_NAT_ERROR_SUCCESS != aret)
+    fprintf (stderr,
+             "NAT test reported error %d\n", aret);
+  else
+    ret = 0;
+  GNUNET_NAT_test_stop (tst);
+  tst = NULL;
+  GNUNET_SCHEDULER_cancel (tsk);
+  tsk = NULL;
+}
+
+
+static void
+failed_timeout (void *cls)
+{
+  tsk = NULL;
+  fprintf (stderr,
+           "NAT test failed to terminate on timeout\n");
+  ret = 2;
+  GNUNET_NAT_test_stop (tst);
+  tst = NULL;
+}
+
+
+/**
+ * Main function run with scheduler.
+ */
+static void
+run (void *cls, char *const *args, const char *cfgfile,
+     const struct GNUNET_CONFIGURATION_Handle *cfg)
+{
+  tst =
+    GNUNET_NAT_test_start (cfg, GNUNET_YES, 1285, 1285, TIMEOUT,
+                           &report_result,
+                           NULL);
+  tsk = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply (TIMEOUT,
+                                                                     2),
+                                      &failed_timeout,
+                                      NULL);
+}
+
+
+int
+main (int argc, char *const argv[])
+{
+  struct GNUNET_GETOPT_CommandLineOption options[] = {
+    GNUNET_GETOPT_OPTION_END
+  };
+  struct GNUNET_OS_Process *gns;
+  int nat_res;
+  char *const argv_prog[] = {
+    "test-nat-test",
+    "-c",
+    "test_nat_test_data.conf",
+    NULL
+  };
+
+  GNUNET_log_setup ("test-nat-test",
+                    "WARNING",
+                    NULL);
+
+  nat_res = GNUNET_OS_check_helper_binary ("gnunet-nat-server", GNUNET_NO,
+                                           NULL);
+  if (GNUNET_SYSERR == nat_res)
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+                "Cannot run NAT test: `%s' file not found\n",
+                "gnunet-nat-server");
+    return 0;
+  }
+
+  gns = GNUNET_OS_start_process (GNUNET_OS_INHERIT_STD_OUT_AND_ERR
+                                 | GNUNET_OS_USE_PIPE_CONTROL,
+                                 NULL, NULL, NULL,
+                                 "gnunet-nat-server",
+                                 "gnunet-nat-server",
+                                 "-c", "test_nat_test_data.conf",
+                                 "12345", NULL);
+  GNUNET_assert (NULL != gns);
+  GNUNET_PROGRAM_run (3, argv_prog,
+                      "test-nat-test", "nohelp",
+                      options, &run,
+                      NULL);
+  GNUNET_break (0 == GNUNET_OS_process_kill (gns, GNUNET_TERM_SIG));
+  GNUNET_break (GNUNET_OK == GNUNET_OS_process_wait (gns));
+  GNUNET_OS_process_destroy (gns);
+  if (0 != ret)
+    fprintf (stderr,
+             "NAT test failed to report success\n");
+  return ret;
+}
+
+
+/* end of test_nat_test.c */
diff --git a/src/nat/test_stun.c b/src/nat/test_stun.c
new file mode 100644
index 0000000000000000000000000000000000000000..75eb877b373df5171d8789f6c5efc3c976521d0a
--- /dev/null
+++ b/src/nat/test_stun.c
@@ -0,0 +1,313 @@
+/*
+     This file is part of GNUnet.
+     Copyright (C) 2009, 2015 GNUnet e.V.
+
+     GNUnet is free software: you can redistribute it and/or modify it
+     under the terms of the GNU Affero General Public License as published
+     by the Free Software Foundation, either version 3 of the License,
+     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
+     Affero General Public License for more details.
+
+     You should have received a copy of the GNU Affero General Public License
+     along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+     SPDX-License-Identifier: AGPL3.0-or-later
+ */
+
+/**
+ * Testcase for STUN server resolution
+ *
+ * @file nat/test_stun.c
+ * @brief Testcase for STUN library
+ * @author Bruno Souza Cabral
+ * @author Christian Grothoff
+ */
+
+
+#include "platform.h"
+#include "gnunet_util_lib.h"
+#include "gnunet_program_lib.h"
+#include "gnunet_scheduler_lib.h"
+#include "gnunet_nat_lib.h"
+
+
+#define LOG(kind, ...) GNUNET_log_from (kind, "test-stun", __VA_ARGS__)
+
+/**
+ * Time to wait before stopping NAT, in seconds
+ */
+#define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 5)
+
+
+/**
+ * The port the test service is running on (default 7895)
+ */
+static unsigned long port = 7895;
+
+static int ret = 1;
+
+static const char *stun_server = "stun.gnunet.org";
+
+static int stun_port = 3478;
+
+/**
+ * The listen socket of the service for IPv4
+ */
+static struct GNUNET_NETWORK_Handle *lsock4;
+
+/**
+ * The listen task ID for IPv4
+ */
+static struct GNUNET_SCHEDULER_Task *ltask4;
+
+/**
+ * Handle for the STUN request.
+ */
+static struct GNUNET_NAT_STUN_Handle *rh;
+
+
+static void
+print_answer (struct sockaddr_in*answer)
+{
+  GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+              "External IP is: %s , with port %d\n",
+              inet_ntoa (answer->sin_addr),
+              ntohs (answer->sin_port));
+}
+
+
+/**
+ * Function that terminates the test.
+ */
+static void
+stop ()
+{
+  GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+              "Stopping NAT and quitting...\n");
+  if (NULL != ltask4)
+  {
+    GNUNET_SCHEDULER_cancel (ltask4);
+    ltask4 = NULL;
+  }
+  if (NULL != lsock4)
+  {
+    GNUNET_NETWORK_socket_close (lsock4);
+    lsock4 = NULL;
+  }
+  if (NULL != rh)
+  {
+    GNUNET_NAT_stun_make_request_cancel (rh);
+    rh = NULL;
+  }
+}
+
+
+/**
+ * Activity on our incoming socket.  Read data from the
+ * incoming connection.
+ *
+ * @param cls
+ */
+static void
+do_udp_read (void *cls)
+{
+  // struct GNUNET_NAT_Test *tst = cls;
+  unsigned char reply_buf[1024];
+  ssize_t rlen;
+  struct sockaddr_in answer;
+  const struct GNUNET_SCHEDULER_TaskContext *tc;
+
+  ltask4 = NULL;
+  tc = GNUNET_SCHEDULER_get_task_context ();
+  if ((0 == (tc->reason & GNUNET_SCHEDULER_REASON_READ_READY)) ||
+      (! GNUNET_NETWORK_fdset_isset (tc->read_ready,
+                                     lsock4)))
+  {
+    fprintf (stderr,
+             "Timeout waiting for STUN response\n");
+    stop ();
+  }
+  rlen = GNUNET_NETWORK_socket_recv (lsock4,
+                                     reply_buf,
+                                     sizeof(reply_buf));
+  memset (&answer,
+          0,
+          sizeof(struct sockaddr_in));
+  if (GNUNET_OK !=
+      GNUNET_NAT_stun_handle_packet (reply_buf,
+                                     rlen,
+                                     &answer))
+  {
+    fprintf (stderr,
+             "Unexpected UDP packet, trying to read more\n");
+    ltask4 = GNUNET_SCHEDULER_add_read_net (TIMEOUT,
+                                            lsock4,
+                                            &do_udp_read, NULL);
+    return;
+  }
+  ret = 0;
+  print_answer (&answer);
+  stop ();
+}
+
+
+/**
+ * Create an IPv4 listen socket bound to our port.
+ *
+ * @return NULL on error
+ */
+static struct GNUNET_NETWORK_Handle *
+bind_v4 ()
+{
+  struct GNUNET_NETWORK_Handle *ls;
+  struct sockaddr_in sa4;
+  int eno;
+
+  memset (&sa4, 0, sizeof(sa4));
+  sa4.sin_family = AF_INET;
+  sa4.sin_port = htons (port);
+#if HAVE_SOCKADDR_IN_SIN_LEN
+  sa4.sin_len = sizeof(sa4);
+#endif
+  ls = GNUNET_NETWORK_socket_create (AF_INET,
+                                     SOCK_DGRAM,
+                                     0);
+  if (NULL == ls)
+    return NULL;
+  if (GNUNET_OK !=
+      GNUNET_NETWORK_socket_bind (ls,
+                                  (const struct sockaddr *) &sa4,
+                                  sizeof(sa4)))
+  {
+    eno = errno;
+    GNUNET_NETWORK_socket_close (ls);
+    errno = eno;
+    return NULL;
+  }
+  return ls;
+}
+
+
+/**
+ * Function called with the result of the STUN request transmission attempt.
+ *
+ * @param cls unused
+ * @param error status code from STUN
+ */
+static void
+request_callback (void *cls,
+                  enum GNUNET_NAT_StatusCode error)
+{
+  rh = NULL;
+  if (GNUNET_NAT_ERROR_SUCCESS == error)
+  {
+    /* all good, start to receive */
+    ltask4 = GNUNET_SCHEDULER_add_read_net (TIMEOUT,
+                                            lsock4,
+                                            &do_udp_read,
+                                            NULL);
+    return;
+  }
+  if (error == GNUNET_NAT_ERROR_NOT_ONLINE)
+  {
+    ret = 77;   /* report 'skip' */
+    fprintf (stderr,
+             "System is offline, cannot test STUN request.\n");
+  }
+  else
+  {
+    ret = error;
+  }
+  stop ();
+}
+
+
+/**
+ * Main function run with scheduler.
+ */
+static void
+run (void *cls,
+     char *const *args,
+     const char *cfgfile,
+     const struct GNUNET_CONFIGURATION_Handle *cfg)
+{
+  // Lets create the socket
+  lsock4 = bind_v4 ();
+  if (NULL == lsock4)
+  {
+    GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR,
+                         "bind");
+    GNUNET_SCHEDULER_shutdown ();
+    return;
+  }
+  GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+              "Service listens on port %u\n",
+              (unsigned int) port);
+  rh = GNUNET_NAT_stun_make_request (stun_server,
+                                     stun_port,
+                                     lsock4,
+                                     &request_callback, NULL);
+  GNUNET_SCHEDULER_add_delayed (TIMEOUT,
+                                &stop, NULL);
+}
+
+
+int
+main (int argc, char *const argv[])
+{
+  struct GNUNET_GETOPT_CommandLineOption options[] = {
+    GNUNET_GETOPT_OPTION_END
+  };
+  char *const argv_prog[] = {
+    "test-stun",
+    "-c",
+    "test_stun.conf",
+    NULL
+  };
+  char *fn;
+  struct GNUNET_OS_Process *proc;
+
+  GNUNET_log_setup ("test-stun",
+                    "WARNING",
+                    NULL);
+
+  /* Lets start resolver */
+  fn = GNUNET_OS_get_libexec_binary_path ("gnunet-service-resolver");
+  proc = GNUNET_OS_start_process (GNUNET_OS_INHERIT_STD_OUT_AND_ERR
+                                  | GNUNET_OS_USE_PIPE_CONTROL,
+                                  NULL, NULL, NULL,
+                                  fn,
+                                  "gnunet-service-resolver",
+                                  "-c", "test_stun.conf", NULL);
+
+  if (NULL == proc)
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+                "This test was unable to start gnunet-service-resolver, and it is required to run ...\n");
+    exit (1);
+  }
+
+  GNUNET_PROGRAM_run (3, argv_prog,
+                      "test-stun", "nohelp",
+                      options,
+                      &run, NULL);
+
+  /* Now kill the resolver */
+  if (0 != GNUNET_OS_process_kill (proc, GNUNET_TERM_SIG))
+  {
+    GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "kill");
+  }
+  GNUNET_OS_process_wait (proc);
+  GNUNET_OS_process_destroy (proc);
+  proc = NULL;
+  GNUNET_free (fn);
+
+  return ret;
+}
+
+
+/* end of test_stun.c */
diff --git a/src/nse/.gitignore b/src/nse/.gitignore
new file mode 100644
index 0000000000000000000000000000000000000000..a2575673c8bfc90cd623a70be9e439ce39a9e225
--- /dev/null
+++ b/src/nse/.gitignore
@@ -0,0 +1,5 @@
+gnunet-service-nse
+gnunet-nse
+gnunet-nse-profiler
+test_nse_api
+perf_kdf
diff --git a/src/nse/gnunet-service-nse.c b/src/nse/gnunet-service-nse.c
index ebf39585e8b87d94c4cbb1ad1683ce6c69819364..dfd71e57a18c19d614ad4caad95fbdb09d02b3c4 100644
--- a/src/nse/gnunet-service-nse.c
+++ b/src/nse/gnunet-service-nse.c
@@ -113,6 +113,11 @@ static struct GNUNET_BIO_WriteHandle *histogram;
 
 #endif
 
+/**
+ * Salt for PoW calcualations.
+ */
+static struct GNUNET_CRYPTO_PowSalt salt = { "gnunet-nse-proof" };
+
 
 /**
  * Per-peer information.
@@ -806,7 +811,7 @@ check_proof_of_work (const struct GNUNET_CRYPTO_EddsaPublicKey *pkey,
   GNUNET_memcpy (&buf[sizeof(val)],
                  pkey,
                  sizeof(struct GNUNET_CRYPTO_EddsaPublicKey));
-  GNUNET_CRYPTO_pow_hash ("gnunet-nse-proof",
+  GNUNET_CRYPTO_pow_hash (&salt,
                           buf,
                           sizeof(buf),
                           &result);
@@ -861,7 +866,7 @@ find_proof (void *cls)
   while ((counter != UINT64_MAX) && (i < ROUND_SIZE))
   {
     GNUNET_memcpy (buf, &counter, sizeof(uint64_t));
-    GNUNET_CRYPTO_pow_hash ("gnunet-nse-proof",
+    GNUNET_CRYPTO_pow_hash (&salt,
                             buf,
                             sizeof(buf),
                             &result);
diff --git a/src/nse/hostkeys.dat b/src/nse/hostkeys.dat
new file mode 100644
index 0000000000000000000000000000000000000000..ab407c167490dd15fa80c6082b65ef53fa1b85f3
Binary files /dev/null and b/src/nse/hostkeys.dat differ
diff --git a/src/nse/nse_infiniband.conf b/src/nse/nse_infiniband.conf
new file mode 100644
index 0000000000000000000000000000000000000000..d2c97567dfae937dee607375e43f1afaab0a5699
--- /dev/null
+++ b/src/nse/nse_infiniband.conf
@@ -0,0 +1,77 @@
+[PATHS]
+GNUNET_TEST_HOME = $GNUNET_TMP/nse-profiler/
+
+[testbed]
+START_ON_DEMAND = NO
+ORT = 12113
+ACCEPT_FROM = 127.0.0.1; 10.6.0.0/16; 192.168.0.0/16;
+HOSTNAME = localhost
+MAX_PARALLEL_OPERATIONS = 400
+OVERLAY_TOPOLOGY = 2D_TORUS
+OVERLAY_RANDOM_LINKS = 1000
+OPERATION_TIMEOUT = 45 s
+SETUP_TIMEOUT = 30m
+STATS_DIR= /home/totakura/nse/test/load
+
+[nse]
+IMMEDIATE_START = YES
+# Overriding network settings for faster testing (do NOT use
+# these values in production just because they are here)
+WORKDELAY = 60 s
+INTERVAL = 10 s
+WORKBITS = 0
+PROOFFILE = $GNUNET_TEST_HOME/nse.proof
+HISTOGRAM_DIR = /home/totakura/nse/test/histograms
+
+[nat]
+DISABLEV6 = YES
+BINDTO = 127.0.0.1
+ENABLE_UPNP = NO
+BEHIND_NAT = NO
+ALLOW_NAT = NO
+INTERNAL_ADDRESS = 127.0.0.1
+EXTERNAL_ADDRESS = 127.0.0.1
+
+[transport]
+plugins = udp
+
+[transport-udp]
+PORT = 12116
+
+[nse-profiler]
+OUTPUT_FILE = nse_output_2000_peers.dat
+TOPOLOGY_OUTPUT_FILE = nse_topo_2000_peers
+DATA_OUTPUT_FILE = nse_stats_2000_peers
+ROUND0 = 1000
+#ROUND1 = 2000
+ROUND2 = 2000
+ROUND3 = 2000
+ROUND4 = 2000
+ROUND5 = 2000
+ROUND6 = 2000
+ROUND7 = 2000
+ROUND8 = 2000
+ROUND9 = 2000
+ROUND10 = 2000
+ROUND11 = 1000
+ROUND12 = 1000
+ROUND13 = 1000
+ROUND14 = 1000
+ROUND15 = 1000
+ROUND16 = 1000
+ROUND17 = 1000
+ROUND18 = 1000
+ROUND19 = 1000
+ROUND20 = 1000
+ROUND21 = 2000
+ROUND22 = 2000
+ROUND23 = 2000
+ROUND24 = 2000
+ROUND25 = 2000
+ROUND26 = 2000
+ROUND27 = 2000
+ROUND28 = 2000
+ROUND29 = 2000
+ROUND30 = 2000
+WAIT_TIME = 1920 s
+CONNECTION_LIMIT = 10
diff --git a/src/nse/perf_kdf.c b/src/nse/perf_kdf.c
index 89b70903a1c6c0ed74927ce8a27545414904cf91..10207675fd40a4d63e7e9f42249750cbd41933a0 100644
--- a/src/nse/perf_kdf.c
+++ b/src/nse/perf_kdf.c
@@ -34,10 +34,11 @@ perfHash ()
 {
   struct GNUNET_HashCode hc;
   char buf[64];
+  struct GNUNET_CRYPTO_PowSalt salt = { "gnunet-nse-proof" };
 
   memset (buf, 1, sizeof(buf));
   for (unsigned int i = 0; i < 1024; i++)
-    GNUNET_CRYPTO_pow_hash ("gnunet-nse-proof",
+    GNUNET_CRYPTO_pow_hash (&salt,
                             buf,
                             sizeof(buf),
                             &hc);
diff --git a/src/peerinfo-tool/.gitignore b/src/peerinfo-tool/.gitignore
new file mode 100644
index 0000000000000000000000000000000000000000..d4ed4f8011e7e14d90e31962e55a8c24fe051185
--- /dev/null
+++ b/src/peerinfo-tool/.gitignore
@@ -0,0 +1,2 @@
+gnunet-peerinfo
+test_gnunet_peerinfo.py
diff --git a/src/peerinfo-tool/plugin_rest_peerinfo.c b/src/peerinfo-tool/plugin_rest_peerinfo.c
index 1ab6d6f75a6eca4fcff8d7fcc5ec6629c6c73a83..99cec7e58692d13aa122dea28e2db6fdc26f5e38 100644
--- a/src/peerinfo-tool/plugin_rest_peerinfo.c
+++ b/src/peerinfo-tool/plugin_rest_peerinfo.c
@@ -70,7 +70,12 @@ const struct GNUNET_CONFIGURATION_Handle *cfg;
 /**
  * HTTP methods allows for this plugin
  */
-static char*allow_methods;
+static char *allow_methods;
+
+/**
+ * Handle to PEERINFO
+ */
+static struct GNUNET_PEERINFO_Handle *peerinfo_handle;
 
 /**
  * @brief struct returned by the initialization function of the plugin
@@ -174,6 +179,16 @@ static struct PrintContext *pc_tail;
  */
 struct RequestHandle
 {
+  /**
+   * DLL
+   */
+  struct RequestHandle *next;
+
+  /**
+   * DLL
+   */
+  struct RequestHandle *prev;
+
   /**
    * JSON temporary array
    */
@@ -204,10 +219,6 @@ struct RequestHandle
    */
   struct GNUNET_PEERINFO_IteratorContext *list_it;
 
-  /**
-   * Handle to PEERINFO
-   */
-  struct GNUNET_PEERINFO_Handle *peerinfo_handle;
 
   /**
    * Rest connection
@@ -250,6 +261,15 @@ struct RequestHandle
   int response_code;
 };
 
+/**
+ * DLL
+ */
+static struct RequestHandle *requests_head;
+
+/**
+ * DLL
+ */
+static struct RequestHandle *requests_tail;
 
 /**
  * Cleanup lookup handle
@@ -294,12 +314,14 @@ cleanup_handle (void *cls)
     GNUNET_PEERINFO_iterate_cancel (handle->list_it);
     handle->list_it = NULL;
   }
-  if (NULL != handle->peerinfo_handle)
+  if (NULL != peerinfo_handle)
   {
-    GNUNET_PEERINFO_disconnect (handle->peerinfo_handle);
-    handle->peerinfo_handle = NULL;
+    GNUNET_PEERINFO_disconnect (peerinfo_handle);
+    peerinfo_handle = NULL;
   }
-
+  GNUNET_CONTAINER_DLL_remove (requests_head,
+                               requests_tail,
+                               handle);
   GNUNET_free (handle);
 }
 
@@ -664,7 +686,7 @@ peerinfo_get (struct GNUNET_REST_RequestHandle *con_handle,
     // specific_peer = GNUNET_PEER_resolve2(peer_id);
   }
 
-  handle->list_it = GNUNET_PEERINFO_iterate (handle->peerinfo_handle,
+  handle->list_it = GNUNET_PEERINFO_iterate (peerinfo_handle,
                                              include_friend_only,
                                              specific_peer,
                                              &peerinfo_list_iteration,
@@ -698,32 +720,6 @@ options_cont (struct GNUNET_REST_RequestHandle *con_handle,
 }
 
 
-/**
- * Handle rest request
- *
- * @param handle the request handle
- */
-static void
-init_cont (struct RequestHandle *handle)
-{
-  struct GNUNET_REST_RequestHandlerError err;
-  static const struct GNUNET_REST_RequestHandler handlers[] = {
-    { MHD_HTTP_METHOD_GET, GNUNET_REST_API_NS_PEERINFO, &peerinfo_get },
-    { MHD_HTTP_METHOD_OPTIONS, GNUNET_REST_API_NS_PEERINFO, &options_cont },
-    GNUNET_REST_HANDLER_END
-  };
-
-  if (GNUNET_NO == GNUNET_REST_handle_request (handle->rest_handle,
-                                               handlers,
-                                               &err,
-                                               handle))
-  {
-    handle->response_code = err.error_code;
-    GNUNET_SCHEDULER_add_now (&do_error, handle);
-  }
-}
-
-
 /**
  * Function processing the REST call
  *
@@ -735,12 +731,18 @@ init_cont (struct RequestHandle *handle)
  * @param proc_cls closure for callback function
  * @return GNUNET_OK if request accepted
  */
-static void
+static enum GNUNET_GenericReturnValue
 rest_process_request (struct GNUNET_REST_RequestHandle *rest_handle,
                       GNUNET_REST_ResultProcessor proc,
                       void *proc_cls)
 {
   struct RequestHandle *handle = GNUNET_new (struct RequestHandle);
+  struct GNUNET_REST_RequestHandlerError err;
+  static const struct GNUNET_REST_RequestHandler handlers[] = {
+    { MHD_HTTP_METHOD_GET, GNUNET_REST_API_NS_PEERINFO, &peerinfo_get },
+    { MHD_HTTP_METHOD_OPTIONS, GNUNET_REST_API_NS_PEERINFO, &options_cont },
+    GNUNET_REST_HANDLER_END
+  };
 
   handle->response_code = 0;
   handle->timeout = GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS,
@@ -752,15 +754,24 @@ rest_process_request (struct GNUNET_REST_RequestHandle *rest_handle,
   handle->url = GNUNET_strdup (rest_handle->url);
   if (handle->url[strlen (handle->url) - 1] == '/')
     handle->url[strlen (handle->url) - 1] = '\0';
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Connecting...\n");
-  handle->peerinfo_handle = GNUNET_PEERINFO_connect (cfg);
-  init_cont (handle);
   handle->timeout_task =
     GNUNET_SCHEDULER_add_delayed (handle->timeout,
                                   &do_error,
                                   handle);
-
+  GNUNET_CONTAINER_DLL_insert (requests_head,
+                               requests_tail,
+                               handle);
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Connecting...\n");
+  if (GNUNET_NO == GNUNET_REST_handle_request (handle->rest_handle,
+                                               handlers,
+                                               &err,
+                                               handle))
+  {
+    cleanup_handle (handle);
+    return GNUNET_NO;
+  }
   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Connected\n");
+  return GNUNET_YES;
 }
 
 
@@ -792,6 +803,7 @@ libgnunet_plugin_rest_peerinfo_init (void *cls)
                    MHD_HTTP_METHOD_PUT,
                    MHD_HTTP_METHOD_DELETE,
                    MHD_HTTP_METHOD_OPTIONS);
+  peerinfo_handle = GNUNET_PEERINFO_connect (cfg);
 
   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
               _ ("Peerinfo REST API initialized\n"));
@@ -812,6 +824,10 @@ libgnunet_plugin_rest_peerinfo_done (void *cls)
   struct Plugin *plugin = api->cls;
 
   plugin->cfg = NULL;
+  while (NULL != requests_head)
+    cleanup_handle (requests_head);
+  if (NULL != peerinfo_handle)
+    GNUNET_PEERINFO_disconnect (peerinfo_handle);
 
   GNUNET_free (allow_methods);
   GNUNET_free (api);
diff --git a/src/peerinfo/.gitignore b/src/peerinfo/.gitignore
new file mode 100644
index 0000000000000000000000000000000000000000..152ca29160654791f1f099768284c33bc2058e39
--- /dev/null
+++ b/src/peerinfo/.gitignore
@@ -0,0 +1,6 @@
+gnunet-service-peerinfo
+test_peerinfo_api
+test_peerinfo_api_friend_only
+test_peerinfo_api_notify_friend_only
+test_peerinfo_shipped_hellos
+perf_peerinfo_api
diff --git a/src/peerstore/.gitignore b/src/peerstore/.gitignore
new file mode 100644
index 0000000000000000000000000000000000000000..7fc22bbdb6d6ece1be430114bf4cc8a107e8138a
--- /dev/null
+++ b/src/peerstore/.gitignore
@@ -0,0 +1,9 @@
+gnunet-service-peerstore
+gnunet-peerstore
+perf_peerstore_store
+test_peerstore_api_iterate
+test_peerstore_api_store
+test_peerstore_api_sync
+test_peerstore_api_watch
+test_plugin_peerstore_sqlite
+test_plugin_peerstore_flat
diff --git a/src/pq/.gitignore b/src/pq/.gitignore
new file mode 100644
index 0000000000000000000000000000000000000000..8de68ddc9c814555a6a4c1b0977504338c3572c5
--- /dev/null
+++ b/src/pq/.gitignore
@@ -0,0 +1 @@
+test_pq
diff --git a/src/pq/pq_connect.c b/src/pq/pq_connect.c
index 405dca174b3de5b8669c227e4fd460f5e6220084..881a158bb4a86a232d0791f84c0443d1be21b348 100644
--- a/src/pq/pq_connect.c
+++ b/src/pq/pq_connect.c
@@ -162,8 +162,7 @@ apply_patch (struct GNUNET_PQ_Context *db,
               "Applying SQL file `%s' on database %s\n",
               buf,
               db->config_str);
-  psql = GNUNET_OS_start_process (GNUNET_NO,
-                                  GNUNET_OS_INHERIT_STD_NONE,
+  psql = GNUNET_OS_start_process (GNUNET_OS_INHERIT_STD_NONE,
                                   NULL,
                                   NULL,
                                   NULL,
@@ -173,6 +172,8 @@ apply_patch (struct GNUNET_PQ_Context *db,
                                   "-f",
                                   buf,
                                   "-q",
+                                  "--set",
+                                  "ON_ERROR_STOP=1",
                                   NULL);
   if (NULL == psql)
   {
@@ -416,7 +417,7 @@ GNUNET_PQ_reconnect (struct GNUNET_PQ_Context *db)
                            db->load_path))
     {
       GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                  "Failed to load SQL statements from `%s'\n",
+                  "Failed to load SQL statements from `%s*'\n",
                   db->load_path);
       PQfinish (db->conn);
       db->conn = NULL;
diff --git a/src/pt/.gitignore b/src/pt/.gitignore
new file mode 100644
index 0000000000000000000000000000000000000000..ea678ffe5bdff0bbda06a108b921a2780e3ef935
--- /dev/null
+++ b/src/pt/.gitignore
@@ -0,0 +1,6 @@
+gnunet-daemon-pt
+test_gns_vpn
+test_gnunet_vpn-4_over
+test_gnunet_vpn-4_to_6
+test_gnunet_vpn-6_over
+test_gnunet_vpn-6_to_4
diff --git a/src/reclaim/.gitignore b/src/reclaim/.gitignore
new file mode 100644
index 0000000000000000000000000000000000000000..46472101bee8cdf5453b49d12fd4acd61e9eb305
--- /dev/null
+++ b/src/reclaim/.gitignore
@@ -0,0 +1,2 @@
+gnunet-reclaim
+gnunet-service-reclaim
diff --git a/src/reclaim/Makefile.am b/src/reclaim/Makefile.am
index a9829c47e66a1bfc1aeede8a398da06208f53331..a58127abfaaa94ceea6ea60d359fc4a50746a8dd 100644
--- a/src/reclaim/Makefile.am
+++ b/src/reclaim/Makefile.am
@@ -13,8 +13,8 @@ REST_PLUGIN = \
   libgnunet_plugin_rest_openid_connect.la \
   libgnunet_plugin_rest_reclaim.la
 
-ATTESTATION_PLUGIN = \
-  libgnunet_plugin_reclaim_attestation_jwt.la
+CREDENTIAL_PLUGIN = \
+  libgnunet_plugin_reclaim_credential_jwt.la
 
 EXTRA_DIST = \
   reclaim.conf \
@@ -34,7 +34,7 @@ lib_LTLIBRARIES = \
 plugin_LTLIBRARIES = \
   libgnunet_plugin_gnsrecord_reclaim.la \
   libgnunet_plugin_reclaim_attribute_basic.la \
-  $(ATTESTATION_PLUGIN) \
+  $(CREDENTIAL_PLUGIN) \
   $(REST_PLUGIN)
 
 bin_PROGRAMS = \
@@ -115,8 +115,8 @@ libgnunetreclaim_la_SOURCES = \
  reclaim.h \
  reclaim_attribute.c \
  reclaim_attribute.h \
- reclaim_attestation.c \
- reclaim_attestation.h
+ reclaim_credential.c \
+ reclaim_credential.h
 libgnunetreclaim_la_LIBADD = \
   $(top_builddir)/src/util/libgnunetutil.la \
   $(GN_LIBINTL) $(XLIB)
@@ -133,14 +133,14 @@ libgnunet_plugin_reclaim_attribute_basic_la_LIBADD = \
 libgnunet_plugin_reclaim_attribute_basic_la_LDFLAGS = \
  $(GN_PLUGIN_LDFLAGS)
 
-libgnunet_plugin_reclaim_attestation_jwt_la_SOURCES = \
-  plugin_reclaim_attestation_jwt.c
-libgnunet_plugin_reclaim_attestation_jwt_la_LIBADD = \
+libgnunet_plugin_reclaim_credential_jwt_la_SOURCES = \
+  plugin_reclaim_credential_jwt.c
+libgnunet_plugin_reclaim_credential_jwt_la_LIBADD = \
   $(top_builddir)/src/util/libgnunetutil.la \
   libgnunetreclaim.la \
   -ljansson\
   $(LTLIBINTL)
-libgnunet_plugin_reclaim_attestation_jwt_la_LDFLAGS = \
+libgnunet_plugin_reclaim_credential_jwt_la_LDFLAGS = \
  $(GN_PLUGIN_LDFLAGS)
 
 gnunet_reclaim_SOURCES = \
@@ -152,11 +152,20 @@ gnunet_reclaim_LDADD = \
   $(top_builddir)/src/identity/libgnunetidentity.la \
   $(GN_LIBINTL)
 
+test_reclaim_attribute_SOURCES = \
+  test_reclaim_attribute.c
+test_reclaim_attribute_LDADD = \
+  $(top_builddir)/src/util/libgnunetutil.la \
+  libgnunetreclaim.la \
+  $(GN_LIBINTL)
+
 check_SCRIPTS = \
   test_reclaim_attribute.sh \
   test_reclaim_issue.sh \
   test_reclaim_consume.sh
-#  test_reclaim_revoke.sh
+
+check_PROGRAMS = \
+  test_reclaim_attribute
 
 if ENABLE_TEST_RUN
  AM_TESTS_ENVIRONMENT=export GNUNET_PREFIX=$${GNUNET_PREFIX:-@libdir@};export PATH=$${GNUNET_PREFIX:-@prefix@}/bin:$$PATH;unset XDG_DATA_HOME;unset XDG_CONFIG_HOME;
diff --git a/src/reclaim/gnunet-reclaim.c b/src/reclaim/gnunet-reclaim.c
index 6bef5b6fe846f3b289bfae5774ff5ad95a8a49cb..b9306b802cf0e3ef9255a9bcfa32193bb0fd14d3 100644
--- a/src/reclaim/gnunet-reclaim.c
+++ b/src/reclaim/gnunet-reclaim.c
@@ -43,29 +43,34 @@ static int ret;
 static int list;
 
 /**
- * List attestations flag
+ * List credentials flag
  */
-static int list_attestations;
+static int list_credentials;
 
 /**
- * Attestation ID string
+ * Credential ID string
  */
-static char *attestation_id;
+static char *credential_id;
 
 /**
- * Attestation ID
+ * Credential ID
  */
-static struct GNUNET_RECLAIM_Identifier attestation;
+static struct GNUNET_RECLAIM_Identifier credential;
 
 /**
- * Attestation name
+ * Credential name
  */
-static char *attestation_name;
+static char *credential_name;
 
 /**
- * Attestation exists
+ * Credential type
  */
-static int attestation_exists;
+static char *credential_type;
+
+/**
+ * Credential exists
+ */
+static int credential_exists;
 
 /**
  * Relying party
@@ -133,9 +138,9 @@ static struct GNUNET_RECLAIM_Operation *reclaim_op;
 static struct GNUNET_RECLAIM_AttributeIterator *attr_iterator;
 
 /**
- * Attestation iterator
+ * Credential iterator
  */
-static struct GNUNET_RECLAIM_AttestationIterator *attest_iterator;
+static struct GNUNET_RECLAIM_CredentialIterator *cred_iterator;
 
 
 /**
@@ -143,10 +148,6 @@ static struct GNUNET_RECLAIM_AttestationIterator *attest_iterator;
  */
 static struct GNUNET_RECLAIM_TicketIterator *ticket_iterator;
 
-/**
- * Master ABE key
- */
-static struct GNUNET_CRYPTO_AbeMasterKey *abe_key;
 
 /**
  * ego private key
@@ -208,25 +209,27 @@ do_cleanup (void *cls)
     GNUNET_RECLAIM_cancel (reclaim_op);
   if (NULL != attr_iterator)
     GNUNET_RECLAIM_get_attributes_stop (attr_iterator);
-  if (NULL != attest_iterator)
-    GNUNET_RECLAIM_get_attestations_stop (attest_iterator);
+  if (NULL != cred_iterator)
+    GNUNET_RECLAIM_get_credentials_stop (cred_iterator);
   if (NULL != ticket_iterator)
     GNUNET_RECLAIM_ticket_iteration_stop (ticket_iterator);
   if (NULL != reclaim_handle)
     GNUNET_RECLAIM_disconnect (reclaim_handle);
   if (NULL != identity_handle)
     GNUNET_IDENTITY_disconnect (identity_handle);
-  if (NULL != abe_key)
-    GNUNET_free (abe_key);
   if (NULL != attr_list)
     GNUNET_free (attr_list);
   if (NULL != attr_to_delete)
     GNUNET_free (attr_to_delete);
+  if (NULL == credential_type)
+    GNUNET_free (credential_type);
 }
 
 
 static void
-ticket_issue_cb (void *cls, const struct GNUNET_RECLAIM_Ticket *ticket)
+ticket_issue_cb (void *cls,
+                 const struct GNUNET_RECLAIM_Ticket *ticket,
+                 const struct GNUNET_RECLAIM_PresentationList *presentations)
 {
   char *ticket_str;
 
@@ -260,7 +263,7 @@ static void
 process_attrs (void *cls,
                const struct GNUNET_CRYPTO_EcdsaPublicKey *identity,
                const struct GNUNET_RECLAIM_Attribute *attr,
-               const struct GNUNET_RECLAIM_Attestation *attest)
+               const struct GNUNET_RECLAIM_Presentation *presentation)
 {
   char *value_str;
   char *id;
@@ -280,7 +283,7 @@ process_attrs (void *cls,
   attr_type = GNUNET_RECLAIM_attribute_number_to_typename (attr->type);
   id = GNUNET_STRINGS_data_to_string_alloc (&attr->id, sizeof(attr->id));
   value_str = NULL;
-  if (NULL == attest)
+  if (NULL == presentation)
   {
     value_str = GNUNET_RECLAIM_attribute_value_to_string (attr->type,
                                                           attr->data,
@@ -290,7 +293,7 @@ process_attrs (void *cls,
   {
     struct GNUNET_RECLAIM_AttributeListEntry *ale;
     struct GNUNET_RECLAIM_AttributeList *al
-      = GNUNET_RECLAIM_attestation_get_attributes (attest);
+      = GNUNET_RECLAIM_presentation_get_attributes (presentation);
 
     for (ale = al->list_head; NULL != ale; ale = ale->next)
     {
@@ -298,10 +301,8 @@ process_attrs (void *cls,
         continue;
       value_str
         = GNUNET_RECLAIM_attribute_value_to_string (ale->attribute->type,
-                                                    ale->attribute->
-                                                    data,
-                                                    ale->attribute->
-                                                    data_size);
+                                                    ale->attribute->data,
+                                                    ale->attribute->data_size);
       break;
     }
   }
@@ -312,7 +313,7 @@ process_attrs (void *cls,
            attr_type,
            attr->flag,
            id,
-           (NULL == attest) ? "" : "(ATTESTED)");
+           (NULL == presentation) ? "" : "(ATTESTED)");
   GNUNET_free (value_str);
   GNUNET_free (id);
 }
@@ -362,7 +363,7 @@ static void
 iter_error (void *cls)
 {
   attr_iterator = NULL;
-  attest_iterator = NULL;
+  cred_iterator = NULL;
   fprintf (stderr, "Failed\n");
 
   cleanup_task = GNUNET_SCHEDULER_add_now (&do_cleanup, NULL);
@@ -457,6 +458,7 @@ iter_finished (void *cls)
     if (NULL == attr_to_delete)
     {
       fprintf (stdout, "No such attribute ``%s''\n", attr_delete);
+      GNUNET_SCHEDULER_add_now (&do_cleanup, NULL);
       return;
     }
     reclaim_op = GNUNET_RECLAIM_attribute_delete (reclaim_handle,
@@ -489,9 +491,9 @@ iter_finished (void *cls)
       claim =
         GNUNET_RECLAIM_attribute_new (attr_name, NULL, type, data, data_size);
     }
-    if (NULL != attestation_id)
+    if (NULL != credential_id)
     {
-      claim->attestation = attestation;
+      claim->credential = credential;
     }
     reclaim_op = GNUNET_RECLAIM_attribute_store (reclaim_handle,
                                                  pkey,
@@ -524,7 +526,7 @@ iter_cb (void *cls,
     if (0 == strcasecmp (attr_name, attr->name))
     {
       claim = GNUNET_RECLAIM_attribute_new (attr->name,
-                                            &attr->attestation,
+                                            &attr->credential,
                                             attr->type,
                                             attr->data,
                                             attr->data_size);
@@ -543,7 +545,7 @@ iter_cb (void *cls,
       }
       le = GNUNET_new (struct GNUNET_RECLAIM_AttributeListEntry);
       le->attribute = GNUNET_RECLAIM_attribute_new (attr->name,
-                                                    &attr->attestation,
+                                                    &attr->credential,
                                                     attr->type,
                                                     attr->data,
                                                     attr->data_size);
@@ -562,7 +564,7 @@ iter_cb (void *cls,
     if (0 == strcasecmp (attr_delete, label))
     {
       attr_to_delete = GNUNET_RECLAIM_attribute_new (attr->name,
-                                                     &attr->attestation,
+                                                     &attr->credential,
                                                      attr->type,
                                                      attr->data,
                                                      attr->data_size);
@@ -577,7 +579,7 @@ iter_cb (void *cls,
                                                          attr->data_size);
     attr_type = GNUNET_RECLAIM_attribute_number_to_typename (attr->type);
     id = GNUNET_STRINGS_data_to_string_alloc (&attr->id, sizeof(attr->id));
-    if (GNUNET_YES == GNUNET_RECLAIM_id_is_zero (&attr->attestation))
+    if (GNUNET_YES == GNUNET_RECLAIM_id_is_zero (&attr->credential))
     {
       fprintf (stdout,
                "%s: ``%s'' (%s); ID: %s\n",
@@ -588,17 +590,17 @@ iter_cb (void *cls,
     }
     else
     {
-      char *attest_id =
-        GNUNET_STRINGS_data_to_string_alloc (&attr->attestation,
-                                             sizeof(attr->attestation));
+      char *cred_id =
+        GNUNET_STRINGS_data_to_string_alloc (&attr->credential,
+                                             sizeof(attr->credential));
       fprintf (stdout,
-               "%s: <``%s'' in attestation %s> (%s); ID: %s\n",
+               "%s: ``%s'' in credential presentation `%s' (%s); ID: %s\n",
                attr->name,
                attr_str,
-               attest_id,
+               cred_id,
                attr_type,
                id);
-      GNUNET_free (attest_id);
+      GNUNET_free (cred_id);
 
     }
     GNUNET_free (id);
@@ -608,29 +610,31 @@ iter_cb (void *cls,
 
 
 static void
-attest_iter_finished (void *cls)
+cred_iter_finished (void *cls)
 {
-  attest_iterator = NULL;
+  cred_iterator = NULL;
 
-  // Add new attestation
-  if ((NULL != attestation_name) &&
+  // Add new credential
+  if ((NULL != credential_name) &&
       (NULL != attr_value))
   {
-    struct GNUNET_RECLAIM_Attestation *attestation =
-      GNUNET_RECLAIM_attestation_new (attestation_name,
-                                      GNUNET_RECLAIM_ATTESTATION_TYPE_JWT, // FIXME hardcoded
-                                      attr_value,
-                                      strlen (attr_value));
-    reclaim_op = GNUNET_RECLAIM_attestation_store (reclaim_handle,
-                                                   pkey,
-                                                   attestation,
-                                                   &exp_interval,
-                                                   store_cont,
-                                                   NULL);
+    enum GNUNET_RECLAIM_CredentialType ctype =
+      GNUNET_RECLAIM_credential_typename_to_number (credential_type);
+    struct GNUNET_RECLAIM_Credential *credential =
+      GNUNET_RECLAIM_credential_new (credential_name,
+                                     ctype,
+                                     attr_value,
+                                     strlen (attr_value));
+    reclaim_op = GNUNET_RECLAIM_credential_store (reclaim_handle,
+                                                  pkey,
+                                                  credential,
+                                                  &exp_interval,
+                                                  store_cont,
+                                                  NULL);
     return;
 
   }
-  if (list_attestations)
+  if (list_credentials)
   {
     cleanup_task = GNUNET_SCHEDULER_add_now (&do_cleanup, NULL);
     return;
@@ -648,34 +652,34 @@ attest_iter_finished (void *cls)
 
 
 static void
-attest_iter_cb (void *cls,
-                const struct GNUNET_CRYPTO_EcdsaPublicKey *identity,
-                const struct GNUNET_RECLAIM_Attestation *attest)
+cred_iter_cb (void *cls,
+              const struct GNUNET_CRYPTO_EcdsaPublicKey *identity,
+              const struct GNUNET_RECLAIM_Credential *cred)
 {
-  char *attest_str;
+  char *cred_str;
   char *attr_str;
   char *id;
-  const char *attest_type;
+  const char *cred_type;
   struct GNUNET_RECLAIM_AttributeListEntry *ale;
 
-  if (GNUNET_YES == GNUNET_RECLAIM_id_is_equal (&attestation,
-                                                &attest->id))
-    attestation_exists = GNUNET_YES;
-  if (list_attestations)
+  if (GNUNET_YES == GNUNET_RECLAIM_id_is_equal (&credential,
+                                                &cred->id))
+    credential_exists = GNUNET_YES;
+  if (list_credentials)
   {
-    attest_str = GNUNET_RECLAIM_attestation_value_to_string (attest->type,
-                                                             attest->data,
-                                                             attest->data_size);
-    attest_type = GNUNET_RECLAIM_attestation_number_to_typename (attest->type);
-    id = GNUNET_STRINGS_data_to_string_alloc (&attest->id, sizeof(attest->id));
+    cred_str = GNUNET_RECLAIM_credential_value_to_string (cred->type,
+                                                          cred->data,
+                                                          cred->data_size);
+    cred_type = GNUNET_RECLAIM_credential_number_to_typename (cred->type);
+    id = GNUNET_STRINGS_data_to_string_alloc (&cred->id, sizeof(cred->id));
     fprintf (stdout,
              "%s: ``%s'' (%s); ID: %s\n",
-             attest->name,
-             attest_str,
-             attest_type,
+             cred->name,
+             cred_str,
+             cred_type,
              id);
     struct GNUNET_RECLAIM_AttributeList *attrs =
-      GNUNET_RECLAIM_attestation_get_attributes (attest);
+      GNUNET_RECLAIM_credential_get_attributes (cred);
     if (NULL != attrs)
     {
       fprintf (stdout,
@@ -684,11 +688,8 @@ attest_iter_cb (void *cls,
       {
         attr_str = GNUNET_RECLAIM_attribute_value_to_string (
           ale->attribute->type,
-          ale->attribute->
-          data,
-          ale->attribute->
-          data_size);
-
+          ale->attribute->data,
+          ale->attribute->data_size);
         fprintf (stdout,
                  "\t %s: %s\n", ale->attribute->name, attr_str);
         GNUNET_free (attr_str);
@@ -697,7 +698,7 @@ attest_iter_cb (void *cls,
     }
     GNUNET_free (id);
   }
-  GNUNET_RECLAIM_get_attestations_next (attest_iterator);
+  GNUNET_RECLAIM_get_credentials_next (cred_iterator);
 }
 
 
@@ -710,12 +711,14 @@ start_process ()
     cleanup_task = GNUNET_SCHEDULER_add_now (&do_cleanup, NULL);
     return;
   }
-  attestation = GNUNET_RECLAIM_ID_ZERO;
-  if (NULL != attestation_id)
-    GNUNET_STRINGS_string_to_data (attestation_id,
-                                   strlen (attestation_id),
-                                   &attestation, sizeof(attestation));
-  attestation_exists = GNUNET_NO;
+  if (NULL == credential_type)
+    credential_type = GNUNET_strdup ("JWT");
+  credential = GNUNET_RECLAIM_ID_ZERO;
+  if (NULL != credential_id)
+    GNUNET_STRINGS_string_to_data (credential_id,
+                                   strlen (credential_id),
+                                   &credential, sizeof(credential));
+  credential_exists = GNUNET_NO;
   if (list_tickets)
   {
     ticket_iterator = GNUNET_RECLAIM_ticket_iteration_start (reclaim_handle,
@@ -750,15 +753,14 @@ start_process ()
 
   attr_list = GNUNET_new (struct GNUNET_RECLAIM_AttributeList);
   claim = NULL;
-  attest_iterator = GNUNET_RECLAIM_get_attestations_start (reclaim_handle,
-                                                           pkey,
-                                                           &iter_error,
-                                                           NULL,
-                                                           &attest_iter_cb,
-                                                           NULL,
-                                                           &
-                                                           attest_iter_finished,
-                                                           NULL);
+  cred_iterator = GNUNET_RECLAIM_get_credentials_start (reclaim_handle,
+                                                        pkey,
+                                                        &iter_error,
+                                                        NULL,
+                                                        &cred_iter_cb,
+                                                        NULL,
+                                                        &cred_iter_finished,
+                                                        NULL);
 
 }
 
@@ -856,20 +858,20 @@ main (int argc, char *const argv[])
                                gettext_noop ("List attributes for EGO"),
                                &list),
     GNUNET_GETOPT_option_flag ('A',
-                               "attestations",
-                               gettext_noop ("List attestations for EGO"),
-                               &list_attestations),
+                               "credentials",
+                               gettext_noop ("List credentials for EGO"),
+                               &list_credentials),
     GNUNET_GETOPT_option_string ('I',
-                                 "Attestation ID",
-                                 "ATTESTATION_ID",
+                                 "credential-id",
+                                 "CREDENTIAL_ID",
                                  gettext_noop (
-                                   "Attestation to use for attribute"),
-                                 &attestation_id),
+                                   "Credential to use for attribute"),
+                                 &credential_id),
     GNUNET_GETOPT_option_string ('N',
-                                 "attestation-name",
+                                 "credential-name",
                                  "NAME",
-                                 gettext_noop ("Attestation name"),
-                                 &attestation_name),
+                                 gettext_noop ("Credential name"),
+                                 &credential_name),
     GNUNET_GETOPT_option_string ('i',
                                  "issue",
                                  "A1,A2,...",
@@ -891,6 +893,11 @@ main (int argc, char *const argv[])
                                  "TYPE",
                                  gettext_noop ("Type of attribute"),
                                  &type_str),
+    GNUNET_GETOPT_option_string ('u',
+                                 "credential-type",
+                                 "TYPE",
+                                 gettext_noop ("Type of credential"),
+                                 &credential_type),
     GNUNET_GETOPT_option_flag ('T',
                                "tickets",
                                gettext_noop ("List tickets of ego"),
diff --git a/src/reclaim/gnunet-service-reclaim.c b/src/reclaim/gnunet-service-reclaim.c
index d4d44c3fc6d4f510d2f807872041a15fbcb8e658..d2cdc62a2a4f154fa04245d0486618c8b8c6b5fa 100644
--- a/src/reclaim/gnunet-service-reclaim.c
+++ b/src/reclaim/gnunet-service-reclaim.c
@@ -170,17 +170,17 @@ struct IdpClient
 
   /**
    * Head of the DLL of
-   * Attribute iteration operations in
+   * Credential iteration operations in
    * progress initiated by this client
    */
-  struct Iterator *attest_iter_head;
+  struct Iterator *cred_iter_head;
 
   /**
    * Tail of the DLL of
-   * Attribute iteration operations
+   * Credential iteration operations
    * in progress initiated by this client
    */
-  struct Iterator *attest_iter_tail;
+  struct Iterator *cred_iter_tail;
 
   /**
    * Head of DLL of ticket iteration ops
@@ -285,9 +285,9 @@ struct AttributeDeleteHandle
   struct GNUNET_RECLAIM_Attribute *claim;
 
   /**
-   * The attestation to delete
+   * The credential to delete
    */
-  struct GNUNET_RECLAIM_Attestation *attest;
+  struct GNUNET_RECLAIM_Credential *credential;
 
   /**
    * Tickets to update
@@ -352,9 +352,9 @@ struct AttributeStoreHandle
   struct GNUNET_RECLAIM_Attribute *claim;
 
   /**
-  * The attestation to store
+  * The credential to store
   */
-  struct GNUNET_RECLAIM_Attestation *attest;
+  struct GNUNET_RECLAIM_Credential *credential;
 
   /**
    * The attribute expiration interval
@@ -488,8 +488,8 @@ cleanup_adh (struct AttributeDeleteHandle *adh)
     GNUNET_free (adh->label);
   if (NULL != adh->claim)
     GNUNET_free (adh->claim);
-  if (NULL != adh->attest)
-    GNUNET_free (adh->attest);
+  if (NULL != adh->credential)
+    GNUNET_free (adh->credential);
   while (NULL != (le = adh->tickets_to_update_head))
   {
     GNUNET_CONTAINER_DLL_remove (adh->tickets_to_update_head,
@@ -517,8 +517,8 @@ cleanup_as_handle (struct AttributeStoreHandle *ash)
     GNUNET_NAMESTORE_cancel (ash->ns_qe);
   if (NULL != ash->claim)
     GNUNET_free (ash->claim);
-  if (NULL != ash->attest)
-    GNUNET_free (ash->attest);
+  if (NULL != ash->credential)
+    GNUNET_free (ash->credential);
   GNUNET_free (ash);
 }
 
@@ -569,9 +569,9 @@ cleanup_client (struct IdpClient *idp)
     GNUNET_CONTAINER_DLL_remove (idp->attr_iter_head, idp->attr_iter_tail, ai);
     GNUNET_free (ai);
   }
-  while (NULL != (ai = idp->attest_iter_head))
+  while (NULL != (ai = idp->cred_iter_head))
   {
-    GNUNET_CONTAINER_DLL_remove (idp->attest_iter_head, idp->attest_iter_tail,
+    GNUNET_CONTAINER_DLL_remove (idp->cred_iter_head, idp->cred_iter_tail,
                                  ai);
     GNUNET_free (ai);
   }
@@ -646,19 +646,33 @@ static void
 send_ticket_result (const struct IdpClient *client,
                     uint32_t r_id,
                     const struct GNUNET_RECLAIM_Ticket *ticket,
+                    const struct GNUNET_RECLAIM_PresentationList *presentations,
                     uint32_t success)
 {
   struct TicketResultMessage *irm;
   struct GNUNET_MQ_Envelope *env;
+  size_t pres_len = 0;
 
-  env = GNUNET_MQ_msg (irm,
-                       GNUNET_MESSAGE_TYPE_RECLAIM_TICKET_RESULT);
+  if (NULL != presentations)
+  {
+    pres_len =
+      GNUNET_RECLAIM_presentation_list_serialize_get_size (presentations);
+  }
+  env = GNUNET_MQ_msg_extra (irm,
+                             pres_len,
+                             GNUNET_MESSAGE_TYPE_RECLAIM_TICKET_RESULT);
   if (NULL != ticket)
   {
     irm->ticket = *ticket;
   }
   // TODO add success member
   irm->id = htonl (r_id);
+  irm->presentations_len = htons (pres_len);
+  if (NULL != presentations)
+  {
+    GNUNET_RECLAIM_presentation_list_serialize (presentations,
+                                                (char*) &irm[1]);
+  }
   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending TICKET_RESULT message\n");
   GNUNET_MQ_send (client->mq, env);
 }
@@ -669,12 +683,14 @@ send_ticket_result (const struct IdpClient *client,
  *
  * @param cls out ticket issue operation handle
  * @param ticket the issued ticket
+ * @param presentations newly created credential presentations (NULL on error)
  * @param success issue success status (GNUNET_OK if successful)
  * @param emsg error message (NULL of success is GNUNET_OK)
  */
 static void
 issue_ticket_result_cb (void *cls,
                         struct GNUNET_RECLAIM_Ticket *ticket,
+                        struct GNUNET_RECLAIM_PresentationList *presentations,
                         int32_t success,
                         const char *emsg)
 {
@@ -682,7 +698,7 @@ issue_ticket_result_cb (void *cls,
 
   if (GNUNET_OK != success)
   {
-    send_ticket_result (tio->client, tio->r_id, NULL, GNUNET_SYSERR);
+    send_ticket_result (tio->client, tio->r_id, NULL, NULL, GNUNET_SYSERR);
     GNUNET_CONTAINER_DLL_remove (tio->client->issue_op_head,
                                  tio->client->issue_op_tail,
                                  tio);
@@ -690,7 +706,8 @@ issue_ticket_result_cb (void *cls,
     GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Error issuing ticket: %s\n", emsg);
     return;
   }
-  send_ticket_result (tio->client, tio->r_id, ticket, GNUNET_SYSERR);
+  send_ticket_result (tio->client, tio->r_id,
+                      ticket, presentations, GNUNET_SYSERR);
   GNUNET_CONTAINER_DLL_remove (tio->client->issue_op_head,
                                tio->client->issue_op_tail,
                                tio);
@@ -732,6 +749,7 @@ handle_issue_ticket_message (void *cls, const struct IssueTicketMessage *im)
   struct TicketIssueOperation *tio;
   struct IdpClient *idp = cls;
   struct GNUNET_RECLAIM_AttributeList *attrs;
+  struct GNUNET_RECLAIM_AttributeListEntry *le;
   size_t attrs_len;
 
   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received ISSUE_TICKET message\n");
@@ -739,6 +757,10 @@ handle_issue_ticket_message (void *cls, const struct IssueTicketMessage *im)
   attrs_len = ntohs (im->attr_len);
   attrs = GNUNET_RECLAIM_attribute_list_deserialize ((char *) &im[1],
                                                      attrs_len);
+  for (le = attrs->list_head; NULL != le; le = le->next)
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                "List entry: %s\n", le->attribute->name);
+
   tio->r_id = ntohl (im->id);
   tio->client = idp;
   GNUNET_CONTAINER_DLL_insert (idp->issue_op_head, idp->issue_op_tail, tio);
@@ -842,7 +864,7 @@ static void
 consume_result_cb (void *cls,
                    const struct GNUNET_CRYPTO_EcdsaPublicKey *identity,
                    const struct GNUNET_RECLAIM_AttributeList *attrs,
-                   const struct GNUNET_RECLAIM_AttestationList *attests,
+                   const struct GNUNET_RECLAIM_PresentationList *presentations,
                    int32_t success,
                    const char *emsg)
 {
@@ -850,29 +872,29 @@ consume_result_cb (void *cls,
   struct ConsumeTicketResultMessage *crm;
   struct GNUNET_MQ_Envelope *env;
   char *data_tmp;
-  size_t attrs_len;
-  size_t attests_len;
+  size_t attrs_len = 0;
+  size_t pres_len = 0;
 
   if (GNUNET_OK != success)
   {
     GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Error consuming ticket: %s\n", emsg);
   }
   attrs_len = GNUNET_RECLAIM_attribute_list_serialize_get_size (attrs);
-  attests_len = GNUNET_RECLAIM_attestation_list_serialize_get_size (attests);
+  pres_len = GNUNET_RECLAIM_presentation_list_serialize_get_size (presentations);
   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
               "Sending CONSUME_TICKET_RESULT message\n");
   env = GNUNET_MQ_msg_extra (crm,
-                             attrs_len + attests_len,
+                             attrs_len + pres_len,
                              GNUNET_MESSAGE_TYPE_RECLAIM_CONSUME_TICKET_RESULT);
   crm->id = htonl (cop->r_id);
   crm->attrs_len = htons (attrs_len);
-  crm->attestations_len = htons (attests_len);
+  crm->presentations_len = htons (pres_len);
   crm->identity = *identity;
   crm->result = htonl (success);
   data_tmp = (char *) &crm[1];
   GNUNET_RECLAIM_attribute_list_serialize (attrs, data_tmp);
   data_tmp += attrs_len;
-  GNUNET_RECLAIM_attestation_list_serialize (attests, data_tmp);
+  GNUNET_RECLAIM_presentation_list_serialize (presentations, data_tmp);
   GNUNET_MQ_send (cop->client->mq, env);
   GNUNET_CONTAINER_DLL_remove (cop->client->consume_op_head,
                                cop->client->consume_op_tail,
@@ -1053,8 +1075,9 @@ handle_attribute_store_message (void *cls,
   data_len = ntohs (sam->attr_len);
 
   ash = GNUNET_new (struct AttributeStoreHandle);
-  ash->claim = GNUNET_RECLAIM_attribute_deserialize ((char *) &sam[1],
-                                                     data_len);
+  GNUNET_RECLAIM_attribute_deserialize ((char *) &sam[1],
+                                        data_len,
+                                        &ash->claim);
 
   ash->r_id = ntohl (sam->id);
   ash->identity = sam->identity;
@@ -1069,14 +1092,14 @@ handle_attribute_store_message (void *cls,
 
 
 /**
- * Attestation store result handler
+ * Credential store result handler
  *
  * @param cls our attribute store handle
  * @param success GNUNET_OK if successful
  * @param emsg error message (NULL if success=GNUNET_OK)
  */
 static void
-attest_store_cont (void *cls, int32_t success, const char *emsg)
+cred_store_cont (void *cls, int32_t success, const char *emsg)
 {
   struct AttributeStoreHandle *ash = cls;
   struct GNUNET_MQ_Envelope *env;
@@ -1090,7 +1113,7 @@ attest_store_cont (void *cls, int32_t success, const char *emsg)
   if (GNUNET_SYSERR == success)
   {
     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                "Failed to store attestation %s\n",
+                "Failed to store credential: %s\n",
                 emsg);
     cleanup_as_handle (ash);
     GNUNET_SCHEDULER_add_now (&do_shutdown, NULL);
@@ -1107,16 +1130,16 @@ attest_store_cont (void *cls, int32_t success, const char *emsg)
 
 
 /**
- * Error looking up potential attestation. Abort.
+ * Error looking up potential credential. Abort.
  *
  * @param cls our attribute store handle
  */
 static void
-attest_error (void *cls)
+cred_error (void *cls)
 {
   struct AttributeStoreHandle *ash = cls;
   GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-              "Failed to check for existing Attestation\n");
+              "Failed to check for existing credential.\n");
   cleanup_as_handle (ash);
   GNUNET_SCHEDULER_add_now (&do_shutdown, NULL);
   return;
@@ -1124,7 +1147,7 @@ attest_error (void *cls)
 
 
 /**
-* Check for existing record before storing attestation
+* Check for existing record before storing credential
 *
 * @param cls our attribute store handle
 * @param zone zone we are iterating
@@ -1133,33 +1156,34 @@ attest_error (void *cls)
 * @param rd records
 */
 static void
-attest_add_cb (void *cls,
-               const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone,
-               const char *label,
-               unsigned int rd_count,
-               const struct GNUNET_GNSRECORD_Data *rd)
+cred_add_cb (void *cls,
+             const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone,
+             const char *label,
+             unsigned int rd_count,
+             const struct GNUNET_GNSRECORD_Data *rd)
 {
   struct AttributeStoreHandle *ash = cls;
+  struct GNUNET_GNSRECORD_Data rd_new[1];
   char *buf;
   size_t buf_size;
-  buf_size = GNUNET_RECLAIM_attestation_serialize_get_size (ash->attest);
+
+  buf_size = GNUNET_RECLAIM_credential_serialize_get_size (ash->credential);
   buf = GNUNET_malloc (buf_size);
-  GNUNET_RECLAIM_attestation_serialize (ash->attest, buf);
+  GNUNET_RECLAIM_credential_serialize (ash->credential, buf);
   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              "Storing new Attestation\n");
-  struct GNUNET_GNSRECORD_Data rd_new[1];
+              "Storing new credential under `%s'.\n",
+              label);
   rd_new[0].data_size = buf_size;
   rd_new[0].data = buf;
-  rd_new[0].record_type = GNUNET_GNSRECORD_TYPE_RECLAIM_ATTESTATION;
+  rd_new[0].record_type = GNUNET_GNSRECORD_TYPE_RECLAIM_CREDENTIAL;
   rd_new[0].flags = GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION;
   rd_new[0].expiration_time = ash->exp.rel_value_us;
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Encrypting with label %s\n", label);
   ash->ns_qe = GNUNET_NAMESTORE_records_store (nsh,
                                                &ash->identity,
                                                label,
                                                1,
                                                rd_new,
-                                               &attest_store_cont,
+                                               &cred_store_cont,
                                                ash);
   GNUNET_free (buf);
   return;
@@ -1167,44 +1191,43 @@ attest_add_cb (void *cls,
 
 
 /**
- * Add a new attestation
+ * Add a new credential
  *
  * @param cls the AttributeStoreHandle
  */
 static void
-attest_store_task (void *cls)
+cred_store_task (void *cls)
 {
   struct AttributeStoreHandle *ash = cls;
   char *label;
 
   // Give the ash a new id if unset
-  if (GNUNET_YES == GNUNET_RECLAIM_id_is_zero (&ash->attest->id))
-    GNUNET_RECLAIM_id_generate (&ash->attest->id);
-  label = GNUNET_STRINGS_data_to_string_alloc (&ash->attest->id,
-                                               sizeof (ash->attest->id));
+  if (GNUNET_YES == GNUNET_RECLAIM_id_is_zero (&ash->credential->id))
+    GNUNET_RECLAIM_id_generate (&ash->credential->id);
+  label = GNUNET_STRINGS_data_to_string_alloc (&ash->credential->id,
+                                               sizeof (ash->credential->id));
   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              "Looking up existing data under label %s\n", label);
-// Test for the content of the existing ID
+              "Looking up existing data under label `%s'\n", label);
   ash->ns_qe = GNUNET_NAMESTORE_records_lookup (nsh,
                                                 &ash->identity,
                                                 label,
-                                                &attest_error,
+                                                &cred_error,
                                                 ash,
-                                                &attest_add_cb,
+                                                &cred_add_cb,
                                                 ash);
   GNUNET_free (label);
 }
 
 
 /**
- * Check an attestation store message
+ * Check an credential store message
  *
  * @param cls unused
  * @param sam the message to check
  */
 static int
-check_attestation_store_message (void *cls,
-                                 const struct AttributeStoreMessage *sam)
+check_credential_store_message (void *cls,
+                                const struct AttributeStoreMessage *sam)
 {
   uint16_t size;
 
@@ -1219,26 +1242,26 @@ check_attestation_store_message (void *cls,
 
 
 /**
-* Handle an attestation store message
+* Handle a credential store message
 *
 * @param cls our client
 * @param sam the message to handle
 */
 static void
-handle_attestation_store_message (void *cls,
+handle_credential_store_message (void *cls,
                                   const struct AttributeStoreMessage *sam)
 {
   struct AttributeStoreHandle *ash;
   struct IdpClient *idp = cls;
   size_t data_len;
 
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received ATTESTATION_STORE message\n");
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received CREDENTIAL_STORE message\n");
 
   data_len = ntohs (sam->attr_len);
 
   ash = GNUNET_new (struct AttributeStoreHandle);
-  ash->attest = GNUNET_RECLAIM_attestation_deserialize ((char *) &sam[1],
-                                                        data_len);
+  ash->credential = GNUNET_RECLAIM_credential_deserialize ((char *) &sam[1],
+                                                           data_len);
 
   ash->r_id = ntohl (sam->id);
   ash->identity = sam->identity;
@@ -1248,7 +1271,7 @@ handle_attestation_store_message (void *cls,
   GNUNET_SERVICE_client_continue (idp->client);
   ash->client = idp;
   GNUNET_CONTAINER_DLL_insert (idp->store_op_head, idp->store_op_tail, ash);
-  GNUNET_SCHEDULER_add_now (&attest_store_task, ash);
+  GNUNET_SCHEDULER_add_now (&cred_store_task, ash);
 }
 
 
@@ -1304,12 +1327,12 @@ ticket_iter (void *cls,
       if (GNUNET_YES != GNUNET_RECLAIM_id_is_equal (rd[i].data,
                                                     &adh->claim->id))
         continue;
-    if (adh->attest != NULL)
+    if (adh->credential != NULL)
       if (GNUNET_YES != GNUNET_RECLAIM_id_is_equal (rd[i].data,
-                                                    &adh->attest->id))
+                                                    &adh->credential->id))
         continue;
     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                "Attribute or Attestation to delete found (%s)\n",
+                "Attribute to delete found (%s)\n",
                 adh->label);
     has_changed = GNUNET_YES;
     break;
@@ -1404,10 +1427,10 @@ update_tickets (void *cls)
           && (GNUNET_YES == GNUNET_RECLAIM_id_is_equal (rd[i].data,
                                                         &adh->claim->id)))
         continue;
-    if (adh->attest != NULL)
+    if (adh->credential != NULL)
       if ((GNUNET_GNSRECORD_TYPE_RECLAIM_ATTRIBUTE_REF == rd[i].record_type)
           && (GNUNET_YES == GNUNET_RECLAIM_id_is_equal (rd[i].data,
-                                                        &adh->attest->id)))
+                                                        &adh->credential->id)))
         continue;
     rd_new[j] = rd[i];
     j++;
@@ -1548,9 +1571,10 @@ handle_attribute_delete_message (void *cls,
   data_len = ntohs (dam->attr_len);
 
   adh = GNUNET_new (struct AttributeDeleteHandle);
-  adh->claim = GNUNET_RECLAIM_attribute_deserialize ((char *) &dam[1],
-                                                     data_len);
-  adh->attest = NULL;
+  GNUNET_RECLAIM_attribute_deserialize ((char *) &dam[1],
+                                        data_len,
+                                        &adh->claim);
+  adh->credential = NULL;
 
   adh->r_id = ntohl (dam->id);
   adh->identity = dam->identity;
@@ -1571,14 +1595,14 @@ handle_attribute_delete_message (void *cls,
 
 
 /**
-   * Attestation deleted callback
+   * Credential deleted callback
    *
    * @param cls our handle
    * @param success success status
    * @param emsg error message (NULL if success=GNUNET_OK)
    */
 static void
-attest_delete_cont (void *cls, int32_t success, const char *emsg)
+cred_delete_cont (void *cls, int32_t success, const char *emsg)
 {
   struct AttributeDeleteHandle *adh = cls;
 
@@ -1586,7 +1610,7 @@ attest_delete_cont (void *cls, int32_t success, const char *emsg)
   if (GNUNET_SYSERR == success)
   {
     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                "Error deleting attestation %s\n",
+                "Error deleting credential `%s'\n",
                 adh->label);
     send_delete_response (adh, GNUNET_SYSERR);
     cleanup_adh (adh);
@@ -1598,14 +1622,14 @@ attest_delete_cont (void *cls, int32_t success, const char *emsg)
 
 
 /**
- * Check attestation delete message format
+ * Check credential delete message format
  *
  * @cls unused
  * @dam message to check
  */
 static int
-check_attestation_delete_message (void *cls,
-                                  const struct AttributeDeleteMessage *dam)
+check_credential_delete_message (void *cls,
+                                 const struct AttributeDeleteMessage *dam)
 {
   uint16_t size;
 
@@ -1620,33 +1644,33 @@ check_attestation_delete_message (void *cls,
 
 
 /**
- * Handle attestation deletion
+ * Handle credential deletion
  *
  * @param cls our client
  * @param dam deletion message
  */
 static void
-handle_attestation_delete_message (void *cls,
+handle_credential_delete_message (void *cls,
                                    const struct AttributeDeleteMessage *dam)
 {
   struct AttributeDeleteHandle *adh;
   struct IdpClient *idp = cls;
   size_t data_len;
 
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received ATTESTATION_DELETE message\n");
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received CREDENTIAL_DELETE message\n");
 
   data_len = ntohs (dam->attr_len);
 
   adh = GNUNET_new (struct AttributeDeleteHandle);
-  adh->attest = GNUNET_RECLAIM_attestation_deserialize ((char *) &dam[1],
-                                                        data_len);
+  adh->credential = GNUNET_RECLAIM_credential_deserialize ((char *) &dam[1],
+                                                           data_len);
   adh->claim = NULL;
 
   adh->r_id = ntohl (dam->id);
   adh->identity = dam->identity;
   adh->label
-    = GNUNET_STRINGS_data_to_string_alloc (&adh->attest->id,
-                                           sizeof(adh->attest->id));
+    = GNUNET_STRINGS_data_to_string_alloc (&adh->credential->id,
+                                           sizeof(adh->credential->id));
   GNUNET_SERVICE_client_continue (idp->client);
   adh->client = idp;
   GNUNET_CONTAINER_DLL_insert (idp->delete_op_head, idp->delete_op_tail, adh);
@@ -1655,7 +1679,7 @@ handle_attestation_delete_message (void *cls,
                                                adh->label,
                                                0,
                                                NULL,
-                                               &attest_delete_cont,
+                                               &cred_delete_cont,
                                                adh);
 }
 
@@ -1705,7 +1729,7 @@ attr_iter_error (void *cls)
 
 
 /**
- * Got record. Return if it is an attribute or attestation.
+ * Got record. Return if it is an attribute.
  *
  * @param cls our attribute iterator
  * @param zone zone we are iterating
@@ -1845,51 +1869,51 @@ handle_iteration_next (void *cls,
 
 
 /*************************************************
-* Attestation iteration
+* Credential iteration
 *************************************************/
 
 
 /**
- * Done iterating over attestations
+ * Done iterating over credentials
  *
  * @param cls our iterator handle
  */
 static void
-attest_iter_finished (void *cls)
+cred_iter_finished (void *cls)
 {
   struct Iterator *ai = cls;
   struct GNUNET_MQ_Envelope *env;
-  struct AttestationResultMessage *arm;
+  struct CredentialResultMessage *arm;
 
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending ATTESTATION_RESULT message\n");
-  env = GNUNET_MQ_msg (arm, GNUNET_MESSAGE_TYPE_RECLAIM_ATTESTATION_RESULT);
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending CREDENTIAL_RESULT message\n");
+  env = GNUNET_MQ_msg (arm, GNUNET_MESSAGE_TYPE_RECLAIM_CREDENTIAL_RESULT);
   arm->id = htonl (ai->request_id);
-  arm->attestation_len = htons (0);
+  arm->credential_len = htons (0);
   GNUNET_MQ_send (ai->client->mq, env);
-  GNUNET_CONTAINER_DLL_remove (ai->client->attest_iter_head,
-                               ai->client->attest_iter_tail,
+  GNUNET_CONTAINER_DLL_remove (ai->client->cred_iter_head,
+                               ai->client->cred_iter_tail,
                                ai);
   GNUNET_free (ai);
 }
 
 
 /**
- * Error iterating over attestations. Abort.
+ * Error iterating over credentials. Abort.
  *
  * @param cls our attribute iteration handle
  */
 static void
-attest_iter_error (void *cls)
+cred_iter_error (void *cls)
 {
   struct Iterator *ai = cls;
 
-  GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Failed to iterate over attestations\n");
-  attest_iter_finished (ai);
+  GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Failed to iterate over credentials\n");
+  cred_iter_finished (ai);
 }
 
 
 /**
- * Got record. Return attestation.
+ * Got record. Return credential.
  *
  * @param cls our attribute iterator
  * @param zone zone we are iterating
@@ -1898,32 +1922,32 @@ attest_iter_error (void *cls)
  * @param rd records
  */
 static void
-attest_iter_cb (void *cls,
-                const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone,
-                const char *label,
-                unsigned int rd_count,
-                const struct GNUNET_GNSRECORD_Data *rd)
+cred_iter_cb (void *cls,
+              const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone,
+              const char *label,
+              unsigned int rd_count,
+              const struct GNUNET_GNSRECORD_Data *rd)
 {
   struct Iterator *ai = cls;
   struct GNUNET_MQ_Envelope *env;
-  struct AttestationResultMessage *arm;
+  struct CredentialResultMessage *arm;
   char *data_tmp;
 
   if ((rd_count != 1) ||
-      (GNUNET_GNSRECORD_TYPE_RECLAIM_ATTESTATION != rd->record_type))
+      (GNUNET_GNSRECORD_TYPE_RECLAIM_CREDENTIAL != rd->record_type))
   {
     GNUNET_NAMESTORE_zone_iterator_next (ai->ns_it, 1);
     return;
   }
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Found attestation under: %s\n",
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Found credential under: %s\n",
               label);
   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              "Sending ATTESTATION_RESULT message\n");
+              "Sending CREDENTIAL_RESULT message\n");
   env = GNUNET_MQ_msg_extra (arm,
                              rd->data_size,
-                             GNUNET_MESSAGE_TYPE_RECLAIM_ATTESTATION_RESULT);
+                             GNUNET_MESSAGE_TYPE_RECLAIM_CREDENTIAL_RESULT);
   arm->id = htonl (ai->request_id);
-  arm->attestation_len = htons (rd->data_size);
+  arm->credential_len = htons (rd->data_size);
   GNUNET_CRYPTO_ecdsa_key_get_public (zone, &arm->identity);
   data_tmp = (char *) &arm[1];
   GNUNET_memcpy (data_tmp, rd->data, rd->data_size);
@@ -1939,29 +1963,29 @@ attest_iter_cb (void *cls,
  * @param ais_msg the iteration message to start
  */
 static void
-handle_attestation_iteration_start (void *cls,
-                                    const struct
-                                    AttestationIterationStartMessage *ais_msg)
+handle_credential_iteration_start (void *cls,
+                                   const struct
+                                   CredentialIterationStartMessage *ais_msg)
 {
   struct IdpClient *idp = cls;
   struct Iterator *ai;
 
   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              "Received ATTESTATION_ITERATION_START message\n");
+              "Received CREDENTIAL_ITERATION_START message\n");
   ai = GNUNET_new (struct Iterator);
   ai->request_id = ntohl (ais_msg->id);
   ai->client = idp;
   ai->identity = ais_msg->identity;
 
-  GNUNET_CONTAINER_DLL_insert (idp->attest_iter_head, idp->attest_iter_tail,
+  GNUNET_CONTAINER_DLL_insert (idp->cred_iter_head, idp->cred_iter_tail,
                                ai);
   ai->ns_it = GNUNET_NAMESTORE_zone_iteration_start (nsh,
                                                      &ai->identity,
-                                                     &attest_iter_error,
+                                                     &cred_iter_error,
                                                      ai,
-                                                     &attest_iter_cb,
+                                                     &cred_iter_cb,
                                                      ai,
-                                                     &attest_iter_finished,
+                                                     &cred_iter_finished,
                                                      ai);
   GNUNET_SERVICE_client_continue (idp->client);
 }
@@ -1974,9 +1998,9 @@ handle_attestation_iteration_start (void *cls,
  * @param ais_msg the stop message
  */
 static void
-handle_attestation_iteration_stop (void *cls,
-                                   const struct
-                                   AttestationIterationStopMessage *ais_msg)
+handle_credential_iteration_stop (void *cls,
+                                  const struct
+                                  CredentialIterationStopMessage *ais_msg)
 {
   struct IdpClient *idp = cls;
   struct Iterator *ai;
@@ -1984,9 +2008,9 @@ handle_attestation_iteration_stop (void *cls,
 
   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
               "Received `%s' message\n",
-              "ATTESTATION_ITERATION_STOP");
+              "CREDENTIAL_ITERATION_STOP");
   rid = ntohl (ais_msg->id);
-  for (ai = idp->attest_iter_head; NULL != ai; ai = ai->next)
+  for (ai = idp->cred_iter_head; NULL != ai; ai = ai->next)
     if (ai->request_id == rid)
       break;
   if (NULL == ai)
@@ -1995,7 +2019,7 @@ handle_attestation_iteration_stop (void *cls,
     GNUNET_SERVICE_client_drop (idp->client);
     return;
   }
-  GNUNET_CONTAINER_DLL_remove (idp->attest_iter_head, idp->attest_iter_tail,
+  GNUNET_CONTAINER_DLL_remove (idp->cred_iter_head, idp->cred_iter_tail,
                                ai);
   GNUNET_free (ai);
   GNUNET_SERVICE_client_continue (idp->client);
@@ -2003,24 +2027,24 @@ handle_attestation_iteration_stop (void *cls,
 
 
 /**
- * Client requests next attestation from iterator
+ * Client requests next credential from iterator
  *
  * @param cls the client
  * @param ais_msg the message
  */
 static void
-handle_attestation_iteration_next (void *cls,
-                                   const struct
-                                   AttestationIterationNextMessage *ais_msg)
+handle_credential_iteration_next (void *cls,
+                                  const struct
+                                  CredentialIterationNextMessage *ais_msg)
 {
   struct IdpClient *idp = cls;
   struct Iterator *ai;
   uint32_t rid;
 
   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              "Received ATTESTATION_ITERATION_NEXT message\n");
+              "Received CREDENTIAL_ITERATION_NEXT message\n");
   rid = ntohl (ais_msg->id);
-  for (ai = idp->attest_iter_head; NULL != ai; ai = ai->next)
+  for (ai = idp->cred_iter_head; NULL != ai; ai = ai->next)
     if (ai->request_id == rid)
       break;
   if (NULL == ai)
@@ -2262,16 +2286,16 @@ GNUNET_SERVICE_MAIN (
                          GNUNET_MESSAGE_TYPE_RECLAIM_ATTRIBUTE_STORE,
                          struct AttributeStoreMessage,
                          NULL),
-  GNUNET_MQ_hd_var_size (attestation_store_message,
-                         GNUNET_MESSAGE_TYPE_RECLAIM_ATTESTATION_STORE,
+  GNUNET_MQ_hd_var_size (credential_store_message,
+                         GNUNET_MESSAGE_TYPE_RECLAIM_CREDENTIAL_STORE,
                          struct AttributeStoreMessage,
                          NULL),
   GNUNET_MQ_hd_var_size (attribute_delete_message,
                          GNUNET_MESSAGE_TYPE_RECLAIM_ATTRIBUTE_DELETE,
                          struct AttributeDeleteMessage,
                          NULL),
-  GNUNET_MQ_hd_var_size (attestation_delete_message,
-                         GNUNET_MESSAGE_TYPE_RECLAIM_ATTESTATION_DELETE,
+  GNUNET_MQ_hd_var_size (credential_delete_message,
+                         GNUNET_MESSAGE_TYPE_RECLAIM_CREDENTIAL_DELETE,
                          struct AttributeDeleteMessage,
                          NULL),
   GNUNET_MQ_hd_fixed_size (iteration_start,
@@ -2286,17 +2310,17 @@ GNUNET_SERVICE_MAIN (
                            GNUNET_MESSAGE_TYPE_RECLAIM_ATTRIBUTE_ITERATION_STOP,
                            struct AttributeIterationStopMessage,
                            NULL),
-  GNUNET_MQ_hd_fixed_size (attestation_iteration_start,
-                           GNUNET_MESSAGE_TYPE_RECLAIM_ATTESTATION_ITERATION_START,
-                           struct AttestationIterationStartMessage,
+  GNUNET_MQ_hd_fixed_size (credential_iteration_start,
+                           GNUNET_MESSAGE_TYPE_RECLAIM_CREDENTIAL_ITERATION_START,
+                           struct CredentialIterationStartMessage,
                            NULL),
-  GNUNET_MQ_hd_fixed_size (attestation_iteration_next,
-                           GNUNET_MESSAGE_TYPE_RECLAIM_ATTESTATION_ITERATION_NEXT,
-                           struct AttestationIterationNextMessage,
+  GNUNET_MQ_hd_fixed_size (credential_iteration_next,
+                           GNUNET_MESSAGE_TYPE_RECLAIM_CREDENTIAL_ITERATION_NEXT,
+                           struct CredentialIterationNextMessage,
                            NULL),
-  GNUNET_MQ_hd_fixed_size (attestation_iteration_stop,
-                           GNUNET_MESSAGE_TYPE_RECLAIM_ATTESTATION_ITERATION_STOP,
-                           struct AttestationIterationStopMessage,
+  GNUNET_MQ_hd_fixed_size (credential_iteration_stop,
+                           GNUNET_MESSAGE_TYPE_RECLAIM_CREDENTIAL_ITERATION_STOP,
+                           struct CredentialIterationStopMessage,
                            NULL),
 
   GNUNET_MQ_hd_var_size (issue_ticket_message,
diff --git a/src/reclaim/gnunet-service-reclaim_tickets.c b/src/reclaim/gnunet-service-reclaim_tickets.c
index f170b6d844968be020fc67fa3ee5dec42e4eb3bc..4dd8100f936b7004db1fdc9d40f5e2d0d387526a 100644
--- a/src/reclaim/gnunet-service-reclaim_tickets.c
+++ b/src/reclaim/gnunet-service-reclaim_tickets.c
@@ -114,9 +114,9 @@ struct RECLAIM_TICKETS_ConsumeHandle
   struct GNUNET_RECLAIM_AttributeList *attrs;
 
   /**
-   * Attestations
+   * Presentations
    */
-  struct GNUNET_RECLAIM_AttestationList *attests;
+  struct GNUNET_RECLAIM_PresentationList *presentations;
 
   /**
    * Lookup time
@@ -172,6 +172,11 @@ struct TicketIssueHandle
    */
   struct GNUNET_RECLAIM_AttributeList *attrs;
 
+  /**
+   * Presentations to add
+   */
+  struct GNUNET_RECLAIM_PresentationList *presentations;
+
   /**
    * Issuer Key
    */
@@ -694,8 +699,9 @@ rvk_move_attr_cb (void *cls,
     {
       /** find a new place for this attribute **/
       struct GNUNET_RECLAIM_Attribute *claim;
-      claim = GNUNET_RECLAIM_attribute_deserialize (rd[i].data,
-                                                    rd[i].data_size);
+      GNUNET_RECLAIM_attribute_deserialize (rd[i].data,
+                                            rd[i].data_size,
+                                            &claim);
       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
                   "Attribute to update: Name=%s\n",
                   claim->name);
@@ -714,20 +720,20 @@ rvk_move_attr_cb (void *cls,
       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Adding attribute %s\n", new_label);
       GNUNET_free (claim);
     }
-    else if (GNUNET_GNSRECORD_TYPE_RECLAIM_ATTESTATION == rd[i].record_type)
+    else if (GNUNET_GNSRECORD_TYPE_RECLAIM_CREDENTIAL == rd[i].record_type)
     {
-      struct GNUNET_RECLAIM_Attestation *attest;
-      attest = GNUNET_RECLAIM_attestation_deserialize (rd[i].data,
-                                                       rd[i].data_size);
+      struct GNUNET_RECLAIM_Credential *credential;
+      credential = GNUNET_RECLAIM_credential_deserialize (rd[i].data,
+                                                          rd[i].data_size);
       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                  "Attestation to update: Name=%s\n",
-                  attest->name);
-      attest->id = rvk->move_attr->new_id;
+                  "Credential to update: Name=%s\n",
+                  credential->name);
+      credential->id = rvk->move_attr->new_id;
       new_rd[i].data_size =
-        GNUNET_RECLAIM_attestation_serialize_get_size (attest);
+        GNUNET_RECLAIM_credential_serialize_get_size (credential);
       attr_data = GNUNET_malloc (rd[i].data_size);
-      new_rd[i].data_size = GNUNET_RECLAIM_attestation_serialize (attest,
-                                                                  attr_data);
+      new_rd[i].data_size = GNUNET_RECLAIM_credential_serialize (credential,
+                                                                 attr_data);
       new_rd[i].data = attr_data;
       new_rd[i].record_type = rd[i].record_type;
       new_rd[i].flags = rd[i].flags;
@@ -735,9 +741,9 @@ rvk_move_attr_cb (void *cls,
       new_label =
         GNUNET_STRINGS_data_to_string_alloc (&rvk->move_attr->new_id,
                                              sizeof (rvk->move_attr->new_id));
-      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Adding attestation %s\n",
+      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Adding credential %s\n",
                   new_label);
-      GNUNET_free (attest);
+      GNUNET_free (credential);
     }
   }
   rvk->ns_qe = GNUNET_NAMESTORE_records_store (nsh,
@@ -980,8 +986,8 @@ cleanup_cth (struct RECLAIM_TICKETS_ConsumeHandle *cth)
 
   if (NULL != cth->attrs)
     GNUNET_RECLAIM_attribute_list_destroy (cth->attrs);
-  if (NULL != cth->attests)
-    GNUNET_RECLAIM_attestation_list_destroy (cth->attests);
+  if (NULL != cth->presentations)
+    GNUNET_RECLAIM_presentation_list_destroy (cth->presentations);
   GNUNET_free (cth);
 }
 
@@ -1026,40 +1032,20 @@ process_parallel_lookup_result (void *cls,
   // REMARK: It is possible now to find rd_count > 1
   for (int i = 0; i < rd_count; i++)
   {
-    if (GNUNET_GNSRECORD_TYPE_RECLAIM_ATTRIBUTE == rd[i].record_type)
-    {
-      attr_le = GNUNET_new (struct GNUNET_RECLAIM_AttributeListEntry);
-      attr_le->attribute =
-        GNUNET_RECLAIM_attribute_deserialize (rd[i].data, rd[i].data_size);
-      GNUNET_CONTAINER_DLL_insert (cth->attrs->list_head,
-                                   cth->attrs->list_tail,
-                                   attr_le);
-    }
-    else if (GNUNET_GNSRECORD_TYPE_RECLAIM_ATTESTATION == rd[i].record_type)
-    {
-      struct GNUNET_RECLAIM_AttestationListEntry *ale;
-      ale = GNUNET_new (struct GNUNET_RECLAIM_AttestationListEntry);
-      ale->attestation =
-        GNUNET_RECLAIM_attestation_deserialize (rd[i].data,
-                                                rd[i].data_size);
-      GNUNET_CONTAINER_DLL_insert (cth->attests->list_head,
-                                   cth->attests->list_tail,
-                                   ale);
-    }
-    else
-    {
-      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                  "Parallel Lookup of Reference without Attestation");
+    if (GNUNET_GNSRECORD_TYPE_RECLAIM_ATTRIBUTE != rd[i].record_type)
       continue;
-    }
-
-
+    attr_le = GNUNET_new (struct GNUNET_RECLAIM_AttributeListEntry);
+    GNUNET_RECLAIM_attribute_deserialize (rd[i].data, rd[i].data_size,
+                                          &attr_le->attribute);
+    GNUNET_CONTAINER_DLL_insert (cth->attrs->list_head,
+                                 cth->attrs->list_tail,
+                                 attr_le);
   }
   if (NULL != cth->parallel_lookups_head)
     return; // Wait for more
   /* Else we are done */
   cth->cb (cth->cb_cls, &cth->ticket.identity,
-           cth->attrs, cth->attests, GNUNET_OK, NULL);
+           cth->attrs, cth->presentations, GNUNET_OK, NULL);
   cleanup_cth (cth);
 }
 
@@ -1109,6 +1095,7 @@ lookup_authz_cb (void *cls,
   struct RECLAIM_TICKETS_ConsumeHandle *cth = cls;
   struct ParallelLookup *parallel_lookup;
   char *lbl;
+  struct GNUNET_RECLAIM_PresentationListEntry *ale;
 
   cth->lookup_request = NULL;
 
@@ -1125,26 +1112,44 @@ lookup_authz_cb (void *cls,
 
   for (int i = 0; i < rd_count; i++)
   {
-    if ((GNUNET_GNSRECORD_TYPE_RECLAIM_ATTRIBUTE_REF != rd[i].record_type) &&
-        (GNUNET_GNSRECORD_TYPE_RECLAIM_ATTESTATION_REF != rd[i].record_type))
-      continue;
-    lbl = GNUNET_STRINGS_data_to_string_alloc (rd[i].data, rd[i].data_size);
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Ticket reference found %s\n", lbl);
-    parallel_lookup = GNUNET_new (struct ParallelLookup);
-    parallel_lookup->handle = cth;
-    parallel_lookup->label = lbl;
-    parallel_lookup->lookup_start_time = GNUNET_TIME_absolute_get ();
-    parallel_lookup->lookup_request =
-      GNUNET_GNS_lookup (gns,
-                         lbl,
-                         &cth->ticket.identity,
-                         GNUNET_GNSRECORD_TYPE_ANY,
-                         GNUNET_GNS_LO_DEFAULT,
-                         &process_parallel_lookup_result,
-                         parallel_lookup);
-    GNUNET_CONTAINER_DLL_insert (cth->parallel_lookups_head,
-                                 cth->parallel_lookups_tail,
-                                 parallel_lookup);
+    /**
+     * Check if record is a credential presentation or an attribute
+     * reference.
+     */
+    switch (rd[i].record_type)
+    {
+    case GNUNET_GNSRECORD_TYPE_RECLAIM_PRESENTATION:
+      ale = GNUNET_new (struct GNUNET_RECLAIM_PresentationListEntry);
+      ale->presentation =
+        GNUNET_RECLAIM_presentation_deserialize (rd[i].data,
+                                                 rd[i].data_size);
+      GNUNET_CONTAINER_DLL_insert (cth->presentations->list_head,
+                                   cth->presentations->list_tail,
+                                   ale);
+      break;
+    case GNUNET_GNSRECORD_TYPE_RECLAIM_ATTRIBUTE_REF:
+      lbl = GNUNET_STRINGS_data_to_string_alloc (rd[i].data, rd[i].data_size);
+      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Ticket reference found %s\n", lbl);
+      parallel_lookup = GNUNET_new (struct ParallelLookup);
+      parallel_lookup->handle = cth;
+      parallel_lookup->label = lbl;
+      parallel_lookup->lookup_start_time = GNUNET_TIME_absolute_get ();
+      parallel_lookup->lookup_request =
+        GNUNET_GNS_lookup (gns,
+                           lbl,
+                           &cth->ticket.identity,
+                           GNUNET_GNSRECORD_TYPE_ANY,
+                           GNUNET_GNS_LO_DEFAULT,
+                           &process_parallel_lookup_result,
+                           parallel_lookup);
+      GNUNET_CONTAINER_DLL_insert (cth->parallel_lookups_head,
+                                   cth->parallel_lookups_tail,
+                                   parallel_lookup);
+      break;
+    default:
+      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                  "Ignoring unknown record type %d", rd[i].record_type);
+    }
   }
   /**
    * We started lookups. Add a timeout task.
@@ -1162,7 +1167,7 @@ lookup_authz_cb (void *cls,
    * No references found, return empty attribute list
    */
   cth->cb (cth->cb_cls, &cth->ticket.identity,
-           cth->attrs, cth->attests, GNUNET_OK, NULL);
+           cth->attrs, NULL, GNUNET_OK, NULL);
   cleanup_cth (cth);
 }
 
@@ -1192,7 +1197,7 @@ RECLAIM_TICKETS_consume (const struct GNUNET_CRYPTO_EcdsaPrivateKey *id,
   cth->identity = *id;
   GNUNET_CRYPTO_ecdsa_key_get_public (&cth->identity, &cth->identity_pub);
   cth->attrs = GNUNET_new (struct GNUNET_RECLAIM_AttributeList);
-  cth->attests = GNUNET_new (struct GNUNET_RECLAIM_AttestationList);
+  cth->presentations = GNUNET_new (struct GNUNET_RECLAIM_PresentationList);
   cth->ticket = *ticket;
   cth->cb = cb;
   cth->cb_cls = cb_cls;
@@ -1230,8 +1235,8 @@ RECLAIM_TICKETS_consume_cancel (struct RECLAIM_TICKETS_ConsumeHandle *cth)
 
 
 /*******************************
-* Ticket issue
-*******************************/
+ * Ticket issue
+ *******************************/
 
 /**
  * Cleanup ticket consume handle
@@ -1264,11 +1269,15 @@ store_ticket_issue_cont (void *cls, int32_t success, const char *emsg)
   {
     handle->cb (handle->cb_cls,
                 &handle->ticket,
+                NULL,
                 GNUNET_SYSERR,
                 "Error storing AuthZ ticket in GNS");
     return;
   }
-  handle->cb (handle->cb_cls, &handle->ticket, GNUNET_OK, NULL);
+  handle->cb (handle->cb_cls,
+              &handle->ticket,
+              handle->presentations,
+              GNUNET_OK, NULL);
   cleanup_issue_handle (handle);
 }
 
@@ -1284,48 +1293,92 @@ static void
 issue_ticket (struct TicketIssueHandle *ih)
 {
   struct GNUNET_RECLAIM_AttributeListEntry *le;
+  struct GNUNET_RECLAIM_PresentationListEntry *ple;
   struct GNUNET_GNSRECORD_Data *attrs_record;
   char *label;
   int i;
+  int j;
   int attrs_count = 0;
 
   for (le = ih->attrs->list_head; NULL != le; le = le->next)
     attrs_count++;
 
-  //Worst case we have one attestation per attribute
+  // Worst case we have one presentation per attribute
   attrs_record =
     GNUNET_malloc (2 * attrs_count * sizeof(struct GNUNET_GNSRECORD_Data));
   i = 0;
   for (le = ih->attrs->list_head; NULL != le; le = le->next)
   {
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                "Adding list entry: %s\n", le->attribute->name);
+
     attrs_record[i].data = &le->attribute->id;
     attrs_record[i].data_size = sizeof(le->attribute->id);
     attrs_record[i].expiration_time = ticket_refresh_interval.rel_value_us;
     attrs_record[i].record_type = GNUNET_GNSRECORD_TYPE_RECLAIM_ATTRIBUTE_REF;
     attrs_record[i].flags = GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION;
     i++;
-    if (GNUNET_NO == GNUNET_RECLAIM_id_is_zero (&le->attribute->attestation))
+    if (GNUNET_NO == GNUNET_RECLAIM_id_is_zero (&le->attribute->credential))
     {
-      int j;
+      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                  "Attribute is backed by credential. Adding...\n");
+      struct GNUNET_RECLAIM_Presentation *pres = NULL;
       for (j = 0; j < i; j++)
       {
         if (attrs_record[j].record_type
-            != GNUNET_GNSRECORD_TYPE_RECLAIM_ATTESTATION_REF)
+            != GNUNET_GNSRECORD_TYPE_RECLAIM_PRESENTATION)
+          continue;
+        pres = GNUNET_RECLAIM_presentation_deserialize (attrs_record[j].data,
+                                                        attrs_record[j].
+                                                        data_size);
+        if (NULL == pres)
+        {
+          GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+                      "Failed to deserialize presentation\n");
           continue;
-        if (0 == memcmp (attrs_record[j].data,
-                         &le->attribute->attestation,
-                         sizeof (le->attribute->attestation)))
+        }
+        if (0 == memcmp (&pres->credential_id,
+                         &le->attribute->credential,
+                         sizeof (le->attribute->credential)))
           break;
+        GNUNET_free (pres);
+        pres = NULL;
+      }
+      if (NULL != pres)
+      {
+        GNUNET_free (pres);
+        continue; // Skip as we have already added this credential presentation.
+      }
+      for (ple = ih->presentations->list_head; NULL != ple; ple = ple->next)
+      {
+        GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                    "Checking presentation....\n");
+
+        if (0 != memcmp (&le->attribute->credential,
+                         &ple->presentation->credential_id,
+                         sizeof (le->attribute->credential)))
+        {
+          GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                      "Presentation does not match credential ID.\n");
+          continue;
+        }
+        char *pres_buf;
+        size_t pres_size;
+        pres_size =
+          GNUNET_RECLAIM_presentation_serialize_get_size (ple->presentation);
+        pres_buf = GNUNET_malloc (pres_size);
+        GNUNET_RECLAIM_presentation_serialize (ple->presentation,
+                                               pres_buf);
+        attrs_record[i].data = pres_buf;
+        attrs_record[i].data_size = pres_size;
+        attrs_record[i].expiration_time =
+          ticket_refresh_interval.rel_value_us;
+        attrs_record[i].record_type =
+          GNUNET_GNSRECORD_TYPE_RECLAIM_PRESENTATION;
+        attrs_record[i].flags = GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION;
+        i++;
+        break;
       }
-      if (j < i)
-        continue; // Skip as we have already added this attestation.
-      attrs_record[i].data = &le->attribute->attestation;
-      attrs_record[i].data_size = sizeof(le->attribute->attestation);
-      attrs_record[i].expiration_time = ticket_refresh_interval.rel_value_us;
-      attrs_record[i].record_type =
-        GNUNET_GNSRECORD_TYPE_RECLAIM_ATTESTATION_REF;
-      attrs_record[i].flags = GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION;
-      i++;
     }
   }
   attrs_record[i].data = &ih->ticket;
@@ -1347,14 +1400,23 @@ issue_ticket (struct TicketIssueHandle *ih)
                                               attrs_record,
                                               &store_ticket_issue_cont,
                                               ih);
+  for (j = 0; j > i; j++)
+  {
+    if (attrs_record[j].record_type
+        != GNUNET_GNSRECORD_TYPE_RECLAIM_PRESENTATION)
+      continue;
+    // Yes, we are allowed to do this because we allocated it above
+    char *ptr = (char*) attrs_record[j].data;
+    GNUNET_free (ptr);
+  }
   GNUNET_free (attrs_record);
   GNUNET_free (label);
 }
 
 
 /*************************************************
-* Ticket iteration (finding a specific ticket)
-*************************************************/
+ * Ticket iteration (finding a specific ticket)
+ *************************************************/
 
 
 /**
@@ -1370,6 +1432,7 @@ filter_tickets_error_cb (void *cls)
   tih->ns_it = NULL;
   tih->cb (tih->cb_cls,
            &tih->ticket,
+           NULL,
            GNUNET_SYSERR,
            "Error storing AuthZ ticket in GNS");
   cleanup_issue_handle (tih);
@@ -1397,22 +1460,25 @@ filter_tickets_cb (void *cls,
 {
   struct TicketIssueHandle *tih = cls;
   struct GNUNET_RECLAIM_Ticket *ticket = NULL;
-
-  // figure out the number of requested attributes
+  struct GNUNET_RECLAIM_Presentation *pres;
+  struct GNUNET_RECLAIM_PresentationList *ticket_presentations;
+  struct GNUNET_RECLAIM_Credential *cred;
+  struct GNUNET_RECLAIM_PresentationListEntry *ple;
   struct GNUNET_RECLAIM_AttributeListEntry *le;
   unsigned int attr_cnt = 0;
-  unsigned int attest_cnt = 0;
+  unsigned int pres_cnt = 0;
 
   for (le = tih->attrs->list_head; NULL != le; le = le->next)
   {
     attr_cnt++;
-    if (GNUNET_NO == GNUNET_RECLAIM_id_is_zero (&le->attribute->attestation))
-      attest_cnt++;
+    if (GNUNET_NO == GNUNET_RECLAIM_id_is_zero (&le->attribute->credential))
+      pres_cnt++;
   }
 
   // ticket search
   unsigned int found_attrs_cnt = 0;
-  unsigned int found_attests_cnt = 0;
+  unsigned int found_pres_cnt = 0;
+  ticket_presentations = GNUNET_new (struct GNUNET_RECLAIM_PresentationList);
 
   for (int i = 0; i < rd_count; i++)
   {
@@ -1432,20 +1498,75 @@ filter_tickets_cb (void *cls,
     }
 
     // cmp requested attributes with ticket attributes
-    if ((GNUNET_GNSRECORD_TYPE_RECLAIM_ATTRIBUTE_REF != rd[i].record_type) &&
-        (GNUNET_GNSRECORD_TYPE_RECLAIM_ATTESTATION_REF != rd[i].record_type))
-      continue;
-    for (le = tih->attrs->list_head; NULL != le; le = le->next)
+    if (GNUNET_GNSRECORD_TYPE_RECLAIM_ATTRIBUTE_REF == rd[i].record_type)
     {
-      if (GNUNET_YES == GNUNET_RECLAIM_id_is_equal (rd[i].data,
-                                                    &le->attribute->id))
-        found_attrs_cnt++;
+      for (le = tih->attrs->list_head; NULL != le; le = le->next)
+      {
+        if (GNUNET_YES == GNUNET_RECLAIM_id_is_equal (rd[i].data,
+                                                      &le->attribute->id))
+          found_attrs_cnt++;
+      }
+    }
+    if (GNUNET_GNSRECORD_TYPE_RECLAIM_CREDENTIAL == rd[i].record_type)
+    {
+      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                  "Found credential...\n");
+
+      for (le = tih->attrs->list_head; NULL != le; le = le->next)
+      {
+        cred = GNUNET_RECLAIM_credential_deserialize (rd[i].data,
+                                                      rd[i].data_size);
+        if (GNUNET_YES != GNUNET_RECLAIM_id_is_equal (&cred->id,
+                                                      &le->attribute->credential))
+        {
+          GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                      "No match.\n");
+          GNUNET_free (cred);
+          continue;
+        }
+        GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                    "Match, creating presentation...\n");
+        if (GNUNET_OK != GNUNET_RECLAIM_credential_get_presentation (
+              cred,
+              tih->attrs,
+              &pres))
+        {
+          GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                      "Unable to retrieve presentation from credential\n");
+          GNUNET_free (cred);
+          continue;
+        }
+        ple = GNUNET_new (struct GNUNET_RECLAIM_PresentationListEntry);
+        ple->presentation = pres;
+        GNUNET_CONTAINER_DLL_insert (tih->presentations->list_head,
+                                     tih->presentations->list_tail,
+                                     ple);
+        GNUNET_free (cred);
+      }
     }
-    for (le = tih->attrs->list_head; NULL != le; le = le->next)
+    if (GNUNET_GNSRECORD_TYPE_RECLAIM_PRESENTATION == rd[i].record_type)
     {
-      if (GNUNET_YES == GNUNET_RECLAIM_id_is_equal (rd[i].data,
-                                                    &le->attribute->attestation))
-        found_attests_cnt++;
+      for (le = tih->attrs->list_head; NULL != le; le = le->next)
+      {
+        pres = GNUNET_RECLAIM_presentation_deserialize (rd[i].data,
+                                                        rd[i].data_size);
+        if (NULL == pres)
+        {
+          GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+                      "Failed to deserialize presentation\n");
+          continue;
+        }
+        if (GNUNET_YES == GNUNET_RECLAIM_id_is_equal (&pres->credential_id,
+                                                      &le->attribute->credential))
+        {
+          found_pres_cnt++;
+          ple = GNUNET_new (struct GNUNET_RECLAIM_PresentationListEntry);
+          ple->presentation = pres;
+          GNUNET_CONTAINER_DLL_insert (ticket_presentations->list_head,
+                                       ticket_presentations->list_tail,
+                                       ple);
+        }
+      }
     }
   }
 
@@ -1454,11 +1575,12 @@ filter_tickets_cb (void *cls,
    * we are done.
    */
   if ((attr_cnt == found_attrs_cnt) &&
-      (attest_cnt == found_attests_cnt) &&
+      (pres_cnt == found_pres_cnt) &&
       (NULL != ticket))
   {
     GNUNET_NAMESTORE_zone_iteration_stop (tih->ns_it);
-    tih->cb (tih->cb_cls, &tih->ticket, GNUNET_OK, NULL);
+    tih->cb (tih->cb_cls, &tih->ticket, ticket_presentations, GNUNET_OK, NULL);
+    GNUNET_RECLAIM_presentation_list_destroy (ticket_presentations);
     cleanup_issue_handle (tih);
     return;
   }
@@ -1510,6 +1632,7 @@ RECLAIM_TICKETS_issue (const struct GNUNET_CRYPTO_EcdsaPrivateKey *identity,
   tih->cb = cb;
   tih->cb_cls = cb_cls;
   tih->attrs = GNUNET_RECLAIM_attribute_list_dup (attrs);
+  tih->presentations = GNUNET_new (struct GNUNET_RECLAIM_PresentationList);
   tih->identity = *identity;
   tih->ticket.audience = *audience;
 
@@ -1527,8 +1650,8 @@ RECLAIM_TICKETS_issue (const struct GNUNET_CRYPTO_EcdsaPrivateKey *identity,
 
 
 /************************************
-* Ticket iteration
-************************************/
+ * Ticket iteration
+ ************************************/
 
 /**
  * Cleanup ticket iterator
diff --git a/src/reclaim/gnunet-service-reclaim_tickets.h b/src/reclaim/gnunet-service-reclaim_tickets.h
index 1c7214d4216fbeebcf26ed7ae925646adc88144b..0dd790fc7c6a18b82ff7422c4bdb099c44361f33 100644
--- a/src/reclaim/gnunet-service-reclaim_tickets.h
+++ b/src/reclaim/gnunet-service-reclaim_tickets.h
@@ -113,6 +113,7 @@ typedef void (*RECLAIM_TICKETS_TicketIter) (
  *
  * @param cls closure
  * @param ticket the ticket
+ * @param presentations new presentations for ticket (NULL on error)
  * @param success #GNUNET_SYSERR on failure (including timeout/queue
  * drop/failure to validate) #GNUNET_OK on success
  * @param emsg NULL on success, otherwise an error message
@@ -120,6 +121,7 @@ typedef void (*RECLAIM_TICKETS_TicketIter) (
 typedef void (*RECLAIM_TICKETS_TicketResult) (
   void *cls,
   struct GNUNET_RECLAIM_Ticket *ticket,
+  struct GNUNET_RECLAIM_PresentationList *presentations,
   int32_t success,
   const char *emsg);
 
@@ -129,7 +131,8 @@ typedef void (*RECLAIM_TICKETS_TicketResult) (
  *
  * @param cls closure
  * @param identity the issuer of the ticket/attributes
- * @param l attribute list retrieved through ticket
+ * @param attributes attribute list retrieved through ticket
+ * @param presentations attribute presentations (may be NULL)
  * @param success GNUNET_OK on success
  * @param emsg error message (NULL on success)
  */
@@ -137,7 +140,7 @@ typedef void (*RECLAIM_TICKETS_ConsumeCallback) (
   void *cls,
   const struct GNUNET_CRYPTO_EcdsaPublicKey *identity,
   const struct GNUNET_RECLAIM_AttributeList *attributes,
-  const struct GNUNET_RECLAIM_AttestationList *attestations,
+  const struct GNUNET_RECLAIM_PresentationList *presentations,
   int32_t success,
   const char *emsg);
 
diff --git a/src/reclaim/json_reclaim.c b/src/reclaim/json_reclaim.c
index c470ea5671582ea4e2a7d5492365012166ea166d..8a3479b8ae96b24154671be1ad0b5296e5eebdd5 100644
--- a/src/reclaim/json_reclaim.c
+++ b/src/reclaim/json_reclaim.c
@@ -46,7 +46,7 @@ parse_attr (void *cls, json_t *root, struct GNUNET_JSON_Specification *spec)
   const char *val_str = NULL;
   const char *type_str = NULL;
   const char *id_str = NULL;
-  const char *attest_str = NULL;
+  const char *cred_str = NULL;
   const char *flag_str = NULL;
   char *data;
   int unpack_state;
@@ -68,8 +68,8 @@ parse_attr (void *cls, json_t *root, struct GNUNET_JSON_Specification *spec)
                               &name_str,
                               "id",
                               &id_str,
-                              "attestation",
-                              &attest_str,
+                              "credential",
+                              &cred_str,
                               "type",
                               &type_str,
                               "value",
@@ -95,12 +95,12 @@ parse_attr (void *cls, json_t *root, struct GNUNET_JSON_Specification *spec)
   }
   attr = GNUNET_RECLAIM_attribute_new (name_str, NULL,
                                        type, data, data_size);
-  if ((NULL != attest_str) && (0 != strlen (attest_str)))
+  if ((NULL != cred_str) && (0 != strlen (cred_str)))
   {
-    GNUNET_STRINGS_string_to_data (attest_str,
-                                   strlen (attest_str),
-                                   &attr->attestation,
-                                   sizeof(attr->attestation));
+    GNUNET_STRINGS_string_to_data (cred_str,
+                                   strlen (cred_str),
+                                   &attr->credential,
+                                   sizeof(attr->credential));
   }
   if ((NULL == id_str) || (0 == strlen (id_str)))
     memset (&attr->id, 0, sizeof (attr->id));
@@ -142,7 +142,7 @@ clean_attr (void *cls, struct GNUNET_JSON_Specification *spec)
  * @return JSON Specification
  */
 struct GNUNET_JSON_Specification
-GNUNET_RECLAIM_JSON_spec_claim (struct GNUNET_RECLAIM_Attribute **attr)
+GNUNET_RECLAIM_JSON_spec_attribute (struct GNUNET_RECLAIM_Attribute **attr)
 {
   struct GNUNET_JSON_Specification ret = { .parser = &parse_attr,
                                            .cleaner = &clean_attr,
@@ -279,7 +279,7 @@ GNUNET_RECLAIM_JSON_spec_ticket (struct GNUNET_RECLAIM_Ticket **ticket)
 
 
 /**
-   * Parse given JSON object to an attestation claim
+   * Parse given JSON object to a credential claim
    *
    * @param cls closure, NULL
    * @param root the json object representing data
@@ -287,9 +287,9 @@ GNUNET_RECLAIM_JSON_spec_ticket (struct GNUNET_RECLAIM_Ticket **ticket)
    * @return #GNUNET_OK upon successful parsing; #GNUNET_SYSERR upon error
    */
 static int
-parse_attest (void *cls, json_t *root, struct GNUNET_JSON_Specification *spec)
+parse_credential (void *cls, json_t *root, struct GNUNET_JSON_Specification *spec)
 {
-  struct GNUNET_RECLAIM_Attestation *attr;
+  struct GNUNET_RECLAIM_Credential *cred;
   const char *name_str = NULL;
   const char *val_str = NULL;
   const char *type_str = NULL;
@@ -325,26 +325,26 @@ parse_attest (void *cls, json_t *root, struct GNUNET_JSON_Specification *spec)
                 "Error json object has a wrong format!\n");
     return GNUNET_SYSERR;
   }
-  type = GNUNET_RECLAIM_attestation_typename_to_number (type_str);
+  type = GNUNET_RECLAIM_credential_typename_to_number (type_str);
   if (GNUNET_SYSERR ==
-      (GNUNET_RECLAIM_attestation_string_to_value (type,
-                                                   val_str,
-                                                   (void **) &data,
-                                                   &data_size)))
+      (GNUNET_RECLAIM_credential_string_to_value (type,
+                                                  val_str,
+                                                  (void **) &data,
+                                                  &data_size)))
   {
-    GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Attestation value invalid!\n");
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Credential value invalid!\n");
     return GNUNET_SYSERR;
   }
-  attr = GNUNET_RECLAIM_attestation_new (name_str, type, data, data_size);
+  cred = GNUNET_RECLAIM_credential_new (name_str, type, data, data_size);
   if ((NULL == id_str) || (0 == strlen (id_str)))
-    memset (&attr->id, 0, sizeof (attr->id));
+    memset (&cred->id, 0, sizeof (cred->id));
   else
     GNUNET_STRINGS_string_to_data (id_str,
                                    strlen (id_str),
-                                   &attr->id,
-                                   sizeof(attr->id));
+                                   &cred->id,
+                                   sizeof(cred->id));
 
-  *(struct GNUNET_RECLAIM_Attestation **) spec->ptr = attr;
+  *(struct GNUNET_RECLAIM_Credential **) spec->ptr = cred;
   return GNUNET_OK;
 }
 
@@ -356,11 +356,11 @@ parse_attest (void *cls, json_t *root, struct GNUNET_JSON_Specification *spec)
  * @param[out] spec where to free the data
  */
 static void
-clean_attest (void *cls, struct GNUNET_JSON_Specification *spec)
+clean_credential (void *cls, struct GNUNET_JSON_Specification *spec)
 {
-  struct GNUNET_RECLAIM_Attestation **attr;
+  struct GNUNET_RECLAIM_Credential **attr;
 
-  attr = (struct GNUNET_RECLAIM_Attestation **) spec->ptr;
+  attr = (struct GNUNET_RECLAIM_Credential **) spec->ptr;
   if (NULL != *attr)
   {
     GNUNET_free (*attr);
@@ -370,23 +370,23 @@ clean_attest (void *cls, struct GNUNET_JSON_Specification *spec)
 
 
 /**
- * JSON Specification for Reclaim attestation claims.
+ * JSON Specification for credential claims.
  *
- * @param ticket struct of GNUNET_RECLAIM_ATTESTATION_Claim to fill
+ * @param attr struct of GNUNET_RECLAIM_Credential to fill
  * @return JSON Specification
  */
 struct GNUNET_JSON_Specification
-GNUNET_RECLAIM_JSON_spec_claim_attest (struct
-                                       GNUNET_RECLAIM_Attestation **attr)
+GNUNET_RECLAIM_JSON_spec_credential (struct
+                                     GNUNET_RECLAIM_Credential **cred)
 {
-  struct GNUNET_JSON_Specification ret = { .parser = &parse_attest,
-                                           .cleaner = &clean_attest,
+  struct GNUNET_JSON_Specification ret = { .parser = &parse_credential,
+                                           .cleaner = &clean_credential,
                                            .cls = NULL,
                                            .field = NULL,
-                                           .ptr = attr,
+                                           .ptr = cred,
                                            .ptr_size = 0,
                                            .size_ptr = NULL };
 
-  *attr = NULL;
+  *cred = NULL;
   return ret;
 }
diff --git a/src/reclaim/json_reclaim.h b/src/reclaim/json_reclaim.h
index 61ddb4378c3976176353caf2c7435322b0725273..613ddf8737f8afba3b0fcdb715a2359f9e4f489f 100644
--- a/src/reclaim/json_reclaim.h
+++ b/src/reclaim/json_reclaim.h
@@ -32,11 +32,11 @@
 /**
  * JSON Specification for Reclaim claims.
  *
- * @param ticket struct of GNUNET_RECLAIM_ATTRIBUTE_Claim to fill
+ * @param attr struct of GNUNET_RECLAIM_Attribute to fill
  * @return JSON Specification
  */
 struct GNUNET_JSON_Specification
-GNUNET_RECLAIM_JSON_spec_claim (struct GNUNET_RECLAIM_Attribute **attr);
+GNUNET_RECLAIM_JSON_spec_attribute (struct GNUNET_RECLAIM_Attribute **attr);
 
 /**
  * JSON Specification for Reclaim tickets.
@@ -48,12 +48,10 @@ struct GNUNET_JSON_Specification
 GNUNET_RECLAIM_JSON_spec_ticket (struct GNUNET_RECLAIM_Ticket **ticket);
 
 /**
-    * JSON Specification for Reclaim attestation claims.
+    * JSON Specification for credentials.
     *
-    * @param ticket struct of GNUNET_RECLAIM_Attestation to fill
+    * @param cred struct of GNUNET_RECLAIM_Credential to fill
     * @return JSON Specification
     */
 struct GNUNET_JSON_Specification
-GNUNET_RECLAIM_JSON_spec_claim_attest (struct
-                                       GNUNET_RECLAIM_Attestation **attr);
-
+GNUNET_RECLAIM_JSON_spec_credential (struct  GNUNET_RECLAIM_Credential **cred);
diff --git a/src/reclaim/oidc_helper.c b/src/reclaim/oidc_helper.c
index ad28392007b11af99b2bfdb42812cdfaba535d16..b307a358c9ae64bc9f17890f819f46ff1074f7a5 100644
--- a/src/reclaim/oidc_helper.c
+++ b/src/reclaim/oidc_helper.c
@@ -47,9 +47,9 @@ struct OIDC_Parameters
   struct GNUNET_RECLAIM_Ticket ticket;
 
   /**
-   * The nonce
+   * The nonce length
    */
-  uint32_t nonce GNUNET_PACKED;
+  uint32_t nonce_len GNUNET_PACKED;
 
   /**
    * The length of the PKCE code_challenge
@@ -62,13 +62,58 @@ struct OIDC_Parameters
   uint32_t attr_list_len GNUNET_PACKED;
 
   /**
-   * The length of the attestation list
+   * The length of the presentation list
    */
-  uint32_t attest_list_len GNUNET_PACKED;
+  uint32_t pres_list_len GNUNET_PACKED;
 };
 
 GNUNET_NETWORK_STRUCT_END
 
+/**
+ * Standard claims represented by the "profile" scope in OIDC
+ */
+static char OIDC_profile_claims[14][32] = {
+  "name", "family_name", "given_name", "middle_name", "nickname",
+  "preferred_username", "profile", "picture", "website", "gender", "birthdate",
+  "zoneinfo", "locale", "updated_at"
+};
+
+/**
+ * Standard claims represented by the "email" scope in OIDC
+ */
+static char OIDC_email_claims[2][16] = {
+  "email", "email_verified"
+};
+
+/**
+ * Standard claims represented by the "phone" scope in OIDC
+ */
+static char OIDC_phone_claims[2][32] = {
+  "phone_number", "phone_number_verified"
+};
+
+/**
+ * Standard claims represented by the "address" scope in OIDC
+ */
+static char OIDC_address_claims[5][32] = {
+  "street_address", "locality", "region", "postal_code", "country"
+};
+
+static enum GNUNET_GenericReturnValue
+is_claim_in_address_scope (const char *claim)
+{
+  int i;
+  for (i = 0; i < 5; i++)
+  {
+    if (0 == strcmp (claim, OIDC_address_claims[i]))
+    {
+      return GNUNET_YES;
+    }
+  }
+  return GNUNET_NO;
+}
+
+
 static char *
 create_jwt_header (void)
 {
@@ -109,72 +154,33 @@ fix_base64 (char *str)
   replace_char (str, '/', '_');
 }
 
-
-/**
- * Create a JWT from attributes
- *
- * @param aud_key the public of the audience
- * @param sub_key the public key of the subject
- * @param attrs the attribute list
- * @param expiration_time the validity of the token
- * @param secret_key the key used to sign the JWT
- * @return a new base64-encoded JWT string.
- */
-char *
-OIDC_id_token_new (const struct GNUNET_CRYPTO_EcdsaPublicKey *aud_key,
-                   const struct GNUNET_CRYPTO_EcdsaPublicKey *sub_key,
-                   struct GNUNET_RECLAIM_AttributeList *attrs,
-                   struct GNUNET_RECLAIM_AttestationList *attests,
-                   const struct GNUNET_TIME_Relative *expiration_time,
-                   const char *nonce,
-                   const char *secret_key)
+static json_t*
+generate_userinfo_json(const struct GNUNET_CRYPTO_EcdsaPublicKey *sub_key,
+                       const struct GNUNET_RECLAIM_AttributeList *attrs,
+                       const struct GNUNET_RECLAIM_PresentationList *presentations)
 {
   struct GNUNET_RECLAIM_AttributeListEntry *le;
-  struct GNUNET_RECLAIM_AttestationListEntry *ale;
-  struct GNUNET_HashCode signature;
-  struct GNUNET_TIME_Absolute exp_time;
-  struct GNUNET_TIME_Absolute time_now;
-  char *audience;
+  struct GNUNET_RECLAIM_PresentationListEntry *ple;
   char *subject;
-  char *header;
-  char *body_str;
-  char *aggr_names_str;
-  char *aggr_sources_str;
   char *source_name;
-  char *result;
-  char *header_base64;
-  char *body_base64;
-  char *signature_target;
-  char *signature_base64;
   char *attr_val_str;
-  char *attest_val_str;
+  char *pres_val_str;
   json_t *body;
   json_t *aggr_names;
   json_t *aggr_sources;
   json_t *aggr_sources_jwt;
-  int num_attestations = 0;
+  json_t *addr_claim = NULL;
+  int num_presentations = 0;
   for (le = attrs->list_head; NULL != le; le = le->next)
   {
-    if (GNUNET_NO == GNUNET_RECLAIM_id_is_zero (&le->attribute->attestation))
-      num_attestations++;
+    if (GNUNET_NO == GNUNET_RECLAIM_id_is_zero (&le->attribute->credential))
+      num_presentations++;
   }
 
-  // iat REQUIRED time now
-  time_now = GNUNET_TIME_absolute_get ();
-  // exp REQUIRED time expired from config
-  exp_time = GNUNET_TIME_absolute_add (time_now, *expiration_time);
-  // auth_time only if max_age
-  // nonce only if nonce
-  // OPTIONAL acr,amr,azp
   subject =
     GNUNET_STRINGS_data_to_string_alloc (sub_key,
                                          sizeof(struct
                                                 GNUNET_CRYPTO_EcdsaPublicKey));
-  audience =
-    GNUNET_STRINGS_data_to_string_alloc (aud_key,
-                                         sizeof(struct
-                                                GNUNET_CRYPTO_EcdsaPublicKey));
-  header = create_jwt_header ();
   body = json_object ();
   aggr_names = json_object ();
   aggr_sources = json_object ();
@@ -185,42 +191,25 @@ OIDC_id_token_new (const struct GNUNET_CRYPTO_EcdsaPublicKey *aud_key,
   json_object_set_new (body, "iss", json_string (SERVER_ADDRESS));
   // sub REQUIRED public key identity, not exceed 255 ASCII  length
   json_object_set_new (body, "sub", json_string (subject));
-  // aud REQUIRED public key client_id must be there
-  json_object_set_new (body, "aud", json_string (audience));
-  // iat
-  json_object_set_new (body,
-                       "iat",
-                       json_integer (time_now.abs_value_us / (1000 * 1000)));
-  // exp
-  json_object_set_new (body,
-                       "exp",
-                       json_integer (exp_time.abs_value_us / (1000 * 1000)));
-  // nbf
-  json_object_set_new (body,
-                       "nbf",
-                       json_integer (time_now.abs_value_us / (1000 * 1000)));
-  // nonce
-  if (NULL != nonce)
-    json_object_set_new (body, "nonce", json_string (nonce));
-  attest_val_str = NULL;
-  aggr_names_str = NULL;
-  aggr_sources_str = NULL;
+  pres_val_str = NULL;
   source_name = NULL;
   int i = 0;
-  for (ale = attests->list_head; NULL != ale; ale = ale->next)
+  for (ple = presentations->list_head; NULL != ple; ple = ple->next)
   {
-    // New Attestation
+    // New presentation
     GNUNET_asprintf (&source_name,
                      "src%d",
                      i);
     aggr_sources_jwt = json_object ();
-    attest_val_str =
-      GNUNET_RECLAIM_attestation_value_to_string (ale->attestation->type,
-                                                  ale->attestation->data,
-                                                  ale->attestation->data_size);
-    json_object_set_new (aggr_sources_jwt, "JWT",
-                         json_string (attest_val_str) );
+    pres_val_str =
+      GNUNET_RECLAIM_presentation_value_to_string (ple->presentation->type,
+                                                   ple->presentation->data,
+                                                   ple->presentation->data_size);
+    json_object_set_new (aggr_sources_jwt,
+                         GNUNET_RECLAIM_presentation_number_to_typename (ple->presentation->type),
+                         json_string (pres_val_str) );
     json_object_set_new (aggr_sources, source_name, aggr_sources_jwt);
+    GNUNET_free (pres_val_str);
     GNUNET_free (source_name);
     source_name = NULL;
     i++;
@@ -229,31 +218,55 @@ OIDC_id_token_new (const struct GNUNET_CRYPTO_EcdsaPublicKey *aud_key,
   for (le = attrs->list_head; NULL != le; le = le->next)
   {
 
-    if (GNUNET_YES == GNUNET_RECLAIM_id_is_zero (&le->attribute->attestation))
+    if (GNUNET_YES == GNUNET_RECLAIM_id_is_zero (&le->attribute->credential))
     {
 
       attr_val_str =
         GNUNET_RECLAIM_attribute_value_to_string (le->attribute->type,
                                                   le->attribute->data,
                                                   le->attribute->data_size);
-      json_object_set_new (body, le->attribute->name,
-                           json_string (attr_val_str));
+      /**
+       * There is this wierd quirk that the individual address claim(s) must be
+       * inside a JSON object of the "address" claim.
+       * FIXME: Possibly include formatted claim here
+       */
+      if (GNUNET_YES == is_claim_in_address_scope (le->attribute->name))
+      {
+        if (NULL == addr_claim)
+        {
+          addr_claim = json_object ();
+        }
+        json_object_set_new (addr_claim, le->attribute->name,
+                             json_string (attr_val_str));
+
+      }
+      else
+      {
+        json_object_set_new (body, le->attribute->name,
+                             json_string (attr_val_str));
+      }
       GNUNET_free (attr_val_str);
     }
     else
     {
-      // Check if attest is there
+      // Check if presentation is there
       int j = 0;
-      for (ale = attests->list_head; NULL != ale; ale = ale->next)
+      for (ple = presentations->list_head; NULL != ple; ple = ple->next)
       {
         if (GNUNET_YES ==
-            GNUNET_RECLAIM_id_is_equal (&ale->attestation->id,
-                                        &le->attribute->attestation))
+            GNUNET_RECLAIM_id_is_equal (&ple->presentation->credential_id,
+                                        &le->attribute->credential))
           break;
         j++;
       }
-      GNUNET_assert (NULL != ale);
-      // Attestation is existing, hence take the respective source str
+      if (NULL == ple)
+      {
+        GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+                    "Presentation for `%s' missing...\n",
+                    le->attribute->name);
+        continue;
+      }
+      // Presentation exists, hence take the respective source str
       GNUNET_asprintf (&source_name,
                        "src%d",
                        j);
@@ -262,21 +275,111 @@ OIDC_id_token_new (const struct GNUNET_CRYPTO_EcdsaPublicKey *aud_key,
       GNUNET_free (source_name);
     }
   }
-
-  if (NULL != attest_val_str)
-    GNUNET_free (attest_val_str);
+  if (NULL != addr_claim)
+    json_object_set_new (body, "address", addr_claim);
   if (0 != i)
   {
-    aggr_names_str = json_dumps (aggr_names, JSON_INDENT (0) | JSON_COMPACT);
-    aggr_sources_str = json_dumps (aggr_sources, JSON_INDENT (0)
-                                   | JSON_COMPACT);
-    json_object_set_new (body, "_claim_names", json_string (aggr_names_str));
-    json_object_set_new (body, "_claim_sources", json_string (
-                           aggr_sources_str));
+    json_object_set_new (body, "_claim_names", aggr_names);
+    json_object_set_new (body, "_claim_sources", aggr_sources);
   }
 
-  json_decref (aggr_names);
-  json_decref (aggr_sources);
+  return body;
+}
+
+/**
+ * Generate userinfo JSON as string
+ *
+ * @param sub_key the subject (user)
+ * @param attrs user attribute list
+ * @param presentations credential presentation list (may be empty)
+ * @return Userinfo JSON
+ */
+char *
+OIDC_generate_userinfo (const struct GNUNET_CRYPTO_EcdsaPublicKey *sub_key,
+                        const struct GNUNET_RECLAIM_AttributeList *attrs,
+                        const struct GNUNET_RECLAIM_PresentationList *presentations)
+{
+  char *body_str;
+  json_t* body = generate_userinfo_json (sub_key,
+                                         attrs,
+                                         presentations);
+  body_str = json_dumps (body, JSON_INDENT (0) | JSON_COMPACT);
+  json_decref (body);
+  return body_str;
+}
+
+
+/**
+ * Create a JWT from attributes
+ *
+ * @param aud_key the public of the audience
+ * @param sub_key the public key of the subject
+ * @param attrs the attribute list
+ * @param presentations credential presentation list (may be empty)
+ * @param expiration_time the validity of the token
+ * @param secret_key the key used to sign the JWT
+ * @return a new base64-encoded JWT string.
+ */
+char *
+OIDC_generate_id_token (const struct GNUNET_CRYPTO_EcdsaPublicKey *aud_key,
+                        const struct GNUNET_CRYPTO_EcdsaPublicKey *sub_key,
+                        const struct GNUNET_RECLAIM_AttributeList *attrs,
+                        const struct GNUNET_RECLAIM_PresentationList *presentations,
+                        const struct GNUNET_TIME_Relative *expiration_time,
+                        const char *nonce,
+                        const char *secret_key)
+{
+  struct GNUNET_HashCode signature;
+  struct GNUNET_TIME_Absolute exp_time;
+  struct GNUNET_TIME_Absolute time_now;
+  char *audience;
+  char *subject;
+  char *header;
+  char *body_str;
+  char *result;
+  char *header_base64;
+  char *body_base64;
+  char *signature_target;
+  char *signature_base64;
+  json_t *body;
+
+  body = generate_userinfo_json (sub_key,
+                                 attrs,
+                                 presentations);
+  // iat REQUIRED time now
+  time_now = GNUNET_TIME_absolute_get ();
+  // exp REQUIRED time expired from config
+  exp_time = GNUNET_TIME_absolute_add (time_now, *expiration_time);
+  // auth_time only if max_age
+  // nonce only if nonce
+  // OPTIONAL acr,amr,azp
+  subject =
+    GNUNET_STRINGS_data_to_string_alloc (sub_key,
+                                         sizeof(struct
+                                                GNUNET_CRYPTO_EcdsaPublicKey));
+  audience =
+    GNUNET_STRINGS_data_to_string_alloc (aud_key,
+                                         sizeof(struct
+                                                GNUNET_CRYPTO_EcdsaPublicKey));
+  header = create_jwt_header ();
+
+  // aud REQUIRED public key client_id must be there
+  json_object_set_new (body, "aud", json_string (audience));
+  // iat
+  json_object_set_new (body,
+                       "iat",
+                       json_integer (time_now.abs_value_us / (1000 * 1000)));
+  // exp
+  json_object_set_new (body,
+                       "exp",
+                       json_integer (exp_time.abs_value_us / (1000 * 1000)));
+  // nbf
+  json_object_set_new (body,
+                       "nbf",
+                       json_integer (time_now.abs_value_us / (1000 * 1000)));
+  // nonce
+  if (NULL != nonce)
+    json_object_set_new (body, "nonce", json_string (nonce));
 
   body_str = json_dumps (body, JSON_INDENT (0) | JSON_COMPACT);
   json_decref (body);
@@ -315,10 +418,6 @@ OIDC_id_token_new (const struct GNUNET_CRYPTO_EcdsaPublicKey *aud_key,
   GNUNET_free (signature_target);
   GNUNET_free (header);
   GNUNET_free (body_str);
-  if (NULL != aggr_sources_str)
-    GNUNET_free (aggr_sources_str);
-  if (NULL != aggr_names_str)
-    GNUNET_free (aggr_names_str);
   GNUNET_free (signature_base64);
   GNUNET_free (body_base64);
   GNUNET_free (header_base64);
@@ -326,89 +425,6 @@ OIDC_id_token_new (const struct GNUNET_CRYPTO_EcdsaPublicKey *aud_key,
 }
 
 
-static void
-derive_aes_key (struct GNUNET_CRYPTO_SymmetricSessionKey *key,
-                struct GNUNET_CRYPTO_SymmetricInitializationVector *iv,
-                struct GNUNET_HashCode *key_material)
-{
-  static const char ctx_key[] = "reclaim-aes-ctx-key";
-  static const char ctx_iv[] = "reclaim-aes-ctx-iv";
-
-  GNUNET_CRYPTO_kdf (key,
-                     sizeof(struct GNUNET_CRYPTO_SymmetricSessionKey),
-                     ctx_key,
-                     strlen (ctx_key),
-                     key_material,
-                     sizeof(struct GNUNET_HashCode),
-                     NULL);
-  GNUNET_CRYPTO_kdf (iv,
-                     sizeof(
-                       struct GNUNET_CRYPTO_SymmetricInitializationVector),
-                     ctx_iv,
-                     strlen (ctx_iv),
-                     key_material,
-                     sizeof(struct GNUNET_HashCode),
-                     NULL);
-}
-
-
-static void
-calculate_key_priv (struct GNUNET_CRYPTO_SymmetricSessionKey *key,
-                    struct GNUNET_CRYPTO_SymmetricInitializationVector *iv,
-                    const struct GNUNET_CRYPTO_EcdsaPrivateKey *ecdsa_priv,
-                    const struct GNUNET_CRYPTO_EcdhePublicKey *ecdh_pub)
-{
-  struct GNUNET_HashCode key_material;
-
-  GNUNET_CRYPTO_ecdsa_ecdh (ecdsa_priv, ecdh_pub, &key_material);
-  derive_aes_key (key, iv, &key_material);
-}
-
-
-static void
-calculate_key_pub (struct GNUNET_CRYPTO_SymmetricSessionKey *key,
-                   struct GNUNET_CRYPTO_SymmetricInitializationVector *iv,
-                   const struct GNUNET_CRYPTO_EcdsaPublicKey *ecdsa_pub,
-                   const struct GNUNET_CRYPTO_EcdhePrivateKey *ecdh_priv)
-{
-  struct GNUNET_HashCode key_material;
-
-  GNUNET_CRYPTO_ecdh_ecdsa (ecdh_priv, ecdsa_pub, &key_material);
-  derive_aes_key (key, iv, &key_material);
-}
-
-
-static void
-decrypt_payload (const struct GNUNET_CRYPTO_EcdsaPrivateKey *ecdsa_priv,
-                 const struct GNUNET_CRYPTO_EcdhePublicKey *ecdh_pub,
-                 const char *ct,
-                 size_t ct_len,
-                 char *buf)
-{
-  struct GNUNET_CRYPTO_SymmetricSessionKey key;
-  struct GNUNET_CRYPTO_SymmetricInitializationVector iv;
-
-  calculate_key_priv (&key, &iv, ecdsa_priv, ecdh_pub);
-  GNUNET_break (GNUNET_CRYPTO_symmetric_decrypt (ct, ct_len, &key, &iv, buf));
-}
-
-
-static void
-encrypt_payload (const struct GNUNET_CRYPTO_EcdsaPublicKey *ecdsa_pub,
-                 const struct GNUNET_CRYPTO_EcdhePrivateKey *ecdh_priv,
-                 const char *payload,
-                 size_t payload_len,
-                 char *buf)
-{
-  struct GNUNET_CRYPTO_SymmetricSessionKey key;
-  struct GNUNET_CRYPTO_SymmetricInitializationVector iv;
-
-  calculate_key_pub (&key, &iv, ecdsa_pub, ecdh_priv);
-  GNUNET_break (
-    GNUNET_CRYPTO_symmetric_encrypt (payload, payload_len, &key, &iv, buf));
-}
-
-
 /**
  * Builds an OIDC authorization code including
  * a reclaim ticket and nonce
@@ -416,6 +432,7 @@ encrypt_payload (const struct GNUNET_CRYPTO_EcdsaPublicKey *ecdsa_pub,
  * @param issuer the issuer of the ticket, used to sign the ticket and nonce
  * @param ticket the ticket to include in the code
  * @param attrs list of attributes which are shared
+ * @param presentations credential presentation list (may be empty)
  * @param nonce the nonce to include in the code
  * @param code_challenge PKCE code challenge
  * @return a new authorization code (caller must free)
@@ -423,8 +440,8 @@ encrypt_payload (const struct GNUNET_CRYPTO_EcdsaPublicKey *ecdsa_pub,
 char *
 OIDC_build_authz_code (const struct GNUNET_CRYPTO_EcdsaPrivateKey *issuer,
                        const struct GNUNET_RECLAIM_Ticket *ticket,
-                       struct GNUNET_RECLAIM_AttributeList *attrs,
-                       struct GNUNET_RECLAIM_AttestationList *attests,
+                       const struct GNUNET_RECLAIM_AttributeList *attrs,
+                       const struct GNUNET_RECLAIM_PresentationList *presentations,
                        const char *nonce_str,
                        const char *code_challenge)
 {
@@ -437,36 +454,23 @@ OIDC_build_authz_code (const struct GNUNET_CRYPTO_EcdsaPrivateKey *issuer,
   size_t payload_len;
   size_t code_payload_len;
   size_t attr_list_len = 0;
-  size_t attests_list_len = 0;
+  size_t pres_list_len = 0;
   size_t code_challenge_len = 0;
-  uint32_t nonce;
-  uint32_t nonce_tmp;
+  uint32_t nonce_len = 0;
   struct GNUNET_CRYPTO_EccSignaturePurpose *purpose;
-  struct GNUNET_CRYPTO_EcdhePrivateKey ecdh_priv;
-  struct GNUNET_CRYPTO_EcdhePublicKey ecdh_pub;
 
   /** PLAINTEXT **/
   // Assign ticket
   memset (&params, 0, sizeof(params));
   params.ticket = *ticket;
   // Assign nonce
-  nonce = 0;
   payload_len = sizeof(struct OIDC_Parameters);
   if ((NULL != nonce_str) && (strcmp ("", nonce_str) != 0))
   {
-    if ((1 != sscanf (nonce_str, "%u", &nonce)) || (nonce > UINT32_MAX))
-    {
-      GNUNET_break (0);
-      GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Invalid nonce %s\n", nonce_str);
-      return NULL;
-    }
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                "Got nonce: %u from %s\n",
-                nonce,
-                nonce_str);
+    nonce_len = strlen (nonce_str);
+    payload_len += nonce_len;
   }
-  nonce_tmp = htonl (nonce);
-  params.nonce = nonce_tmp;
+  params.nonce_len = htonl (nonce_len);
   // Assign code challenge
   if (NULL != code_challenge)
     code_challenge_len = strlen (code_challenge);
@@ -484,17 +488,17 @@ OIDC_build_authz_code (const struct GNUNET_CRYPTO_EcdsaPrivateKey *issuer,
     // Get serialized attributes
     payload_len += attr_list_len;
   }
-  if (NULL != attests)
+  if (NULL != presentations)
   {
     // Get length
-    attests_list_len =
-      GNUNET_RECLAIM_attestation_list_serialize_get_size (attests);
-    params.attest_list_len = htonl (attests_list_len);
+    pres_list_len =
+      GNUNET_RECLAIM_presentation_list_serialize_get_size (presentations);
+    params.pres_list_len = htonl (pres_list_len);
     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                "Length of serialized attestations: %lu\n",
-                attests_list_len);
+                "Length of serialized presentations: %lu\n",
+                pres_list_len);
     // Get serialized attributes
-    payload_len += attests_list_len;
+    payload_len += pres_list_len;
   }
 
   // Get plaintext length
@@ -506,43 +510,36 @@ OIDC_build_authz_code (const struct GNUNET_CRYPTO_EcdsaPrivateKey *issuer,
     memcpy (tmp, code_challenge, code_challenge_len);
     tmp += code_challenge_len;
   }
+  if (0 < nonce_len)
+  {
+    memcpy (tmp, nonce_str, nonce_len);
+    tmp += nonce_len;
+  }
   if (0 < attr_list_len)
     GNUNET_RECLAIM_attribute_list_serialize (attrs, tmp);
-  if (0 < attests_list_len)
-    GNUNET_RECLAIM_attestation_list_serialize (attests, tmp);
+  if (0 < pres_list_len)
+    GNUNET_RECLAIM_presentation_list_serialize (presentations, tmp);
 
   /** END **/
 
-  /** ENCRYPT **/
   // Get length
   code_payload_len = sizeof(struct GNUNET_CRYPTO_EccSignaturePurpose)
-                     + sizeof(struct GNUNET_CRYPTO_EcdhePublicKey)
                      + payload_len + sizeof(struct
                                             GNUNET_CRYPTO_EcdsaSignature);
   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
               "Length of data to encode: %lu\n",
               code_payload_len);
 
-  // Generate ECDH key
-  GNUNET_CRYPTO_ecdhe_key_create (&ecdh_priv);
-  GNUNET_CRYPTO_ecdhe_key_get_public (&ecdh_priv, &ecdh_pub);
   // Initialize code payload
   code_payload = GNUNET_malloc (code_payload_len);
   GNUNET_assert (NULL != code_payload);
   purpose = (struct GNUNET_CRYPTO_EccSignaturePurpose *) code_payload;
   purpose->size = htonl (sizeof(struct GNUNET_CRYPTO_EccSignaturePurpose)
-                         + sizeof(ecdh_pub) + payload_len);
+                         + payload_len);
   purpose->purpose = htonl (GNUNET_SIGNATURE_PURPOSE_RECLAIM_CODE_SIGN);
   // Store pubkey
   buf_ptr = (char *) &purpose[1];
-  memcpy (buf_ptr, &ecdh_pub, sizeof(ecdh_pub));
-  buf_ptr += sizeof(ecdh_pub);
-  // Encrypt plaintext and store
-  encrypt_payload (&ticket->audience,
-                   &ecdh_priv,
-                   payload,
-                   payload_len,
-                   buf_ptr);
+  memcpy (buf_ptr, payload, payload_len);
   GNUNET_free (payload);
   buf_ptr += payload_len;
   // Sign and store signature
@@ -570,39 +567,39 @@ OIDC_build_authz_code (const struct GNUNET_CRYPTO_EcdsaPrivateKey *issuer,
  *
  * @param audience the expected audience of the code
  * @param code the string representation of the code
- * @param code_verfier PKCE code verifier
+ * @param code_verfier PKCE code verifier. Optional, must be provided
+ *                     if used in request.
  * @param ticket where to store the ticket
  * @param attrs the attributes in the code
- * @param nonce where to store the nonce
+ * @param presentations credential presentation list
+ * @param nonce_str where to store the nonce (if contained)
  * @return GNUNET_OK if successful, else GNUNET_SYSERR
  */
 int
-OIDC_parse_authz_code (const struct GNUNET_CRYPTO_EcdsaPrivateKey *ecdsa_priv,
+OIDC_parse_authz_code (const struct GNUNET_CRYPTO_EcdsaPublicKey *audience,
                        const char *code,
                        const char *code_verifier,
                        struct GNUNET_RECLAIM_Ticket *ticket,
                        struct GNUNET_RECLAIM_AttributeList **attrs,
-                       struct GNUNET_RECLAIM_AttestationList **attests,
+                       struct GNUNET_RECLAIM_PresentationList **presentations,
                        char **nonce_str)
 {
   char *code_payload;
   char *ptr;
   char *plaintext;
   char *attrs_ser;
-  char *attests_ser;
+  char *presentations_ser;
   char *expected_code_challenge;
   char *code_challenge;
   char *code_verifier_hash;
   struct GNUNET_CRYPTO_EccSignaturePurpose *purpose;
   struct GNUNET_CRYPTO_EcdsaSignature *signature;
-  struct GNUNET_CRYPTO_EcdsaPublicKey ecdsa_pub;
-  struct GNUNET_CRYPTO_EcdhePublicKey *ecdh_pub;
   uint32_t code_challenge_len;
   uint32_t attrs_ser_len;
-  uint32_t attests_ser_len;
+  uint32_t pres_ser_len;
   size_t plaintext_len;
   size_t code_payload_len;
-  uint32_t nonce = 0;
+  uint32_t nonce_len = 0;
   struct OIDC_Parameters *params;
 
   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Trying to decode `%s'\n", code);
@@ -611,7 +608,6 @@ OIDC_parse_authz_code (const struct GNUNET_CRYPTO_EcdsaPrivateKey *ecdsa_priv,
     GNUNET_STRINGS_base64url_decode (code, strlen (code),
                                      (void **) &code_payload);
   if (code_payload_len < sizeof(struct GNUNET_CRYPTO_EccSignaturePurpose)
-      + sizeof(struct GNUNET_CRYPTO_EcdhePublicKey)
       + sizeof(struct OIDC_Parameters)
       + sizeof(struct GNUNET_CRYPTO_EcdsaSignature))
   {
@@ -624,22 +620,15 @@ OIDC_parse_authz_code (const struct GNUNET_CRYPTO_EcdsaPrivateKey *ecdsa_priv,
   plaintext_len = code_payload_len;
   plaintext_len -= sizeof(struct GNUNET_CRYPTO_EccSignaturePurpose);
   ptr = (char *) &purpose[1];
-  // Public ECDH key
-  ecdh_pub = (struct GNUNET_CRYPTO_EcdhePublicKey *) ptr;
-  ptr += sizeof(struct GNUNET_CRYPTO_EcdhePublicKey);
-  plaintext_len -= sizeof(struct GNUNET_CRYPTO_EcdhePublicKey);
-
-  // Decrypt ciphertext
   plaintext_len -= sizeof(struct GNUNET_CRYPTO_EcdsaSignature);
-  plaintext = GNUNET_malloc (plaintext_len);
-  decrypt_payload (ecdsa_priv, ecdh_pub, ptr, plaintext_len, plaintext);
-  // ptr = plaintext;
+  plaintext = ptr;
   ptr += plaintext_len;
   signature = (struct GNUNET_CRYPTO_EcdsaSignature *) ptr;
   params = (struct OIDC_Parameters *) plaintext;
 
   // cmp code_challenge code_verifier
   code_challenge_len = ntohl (params->code_challenge_len);
+  code_challenge = ((char *) &params[1]);
   if (0 != code_challenge_len) /* Only check if this code requires a CV */
   {
     if (NULL == code_verifier)
@@ -658,11 +647,9 @@ OIDC_parse_authz_code (const struct GNUNET_CRYPTO_EcdsaPrivateKey *ecdsa_priv,
     // encode code verifier
     GNUNET_STRINGS_base64url_encode (code_verifier_hash, 256 / 8,
                                      &expected_code_challenge);
-    code_challenge = (char *) &params[1];
     GNUNET_free (code_verifier_hash);
-    if ((strlen (expected_code_challenge) != code_challenge_len) ||
-        (0 !=
-         strncmp (expected_code_challenge, code_challenge, code_challenge_len)))
+    if (0 !=
+        strncmp (expected_code_challenge, code_challenge, code_challenge_len))
     {
       GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
                   "Invalid code verifier! Expected: %s, Got: %.*s\n",
@@ -675,17 +662,23 @@ OIDC_parse_authz_code (const struct GNUNET_CRYPTO_EcdsaPrivateKey *ecdsa_priv,
     }
     GNUNET_free (expected_code_challenge);
   }
+  nonce_len = ntohl (params->nonce_len);
+  if (0 != nonce_len)
+  {
+    *nonce_str = GNUNET_strndup (code_challenge + code_challenge_len,
+                                 nonce_len);
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Got nonce: %s\n", *nonce_str);
+  }
+
   // Ticket
   memcpy (ticket, &params->ticket, sizeof(params->ticket));
-  // Nonce
-  nonce = ntohl (params->nonce);  // ntohl (*((uint32_t *) ptr));
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Got nonce: %u\n", nonce);
   // Signature
-  GNUNET_CRYPTO_ecdsa_key_get_public (ecdsa_priv, &ecdsa_pub);
-  if (0 != GNUNET_memcmp (&ecdsa_pub, &ticket->audience))
+  // GNUNET_CRYPTO_ecdsa_key_get_public (ecdsa_priv, &ecdsa_pub);
+  if (0 != GNUNET_memcmp (audience, &ticket->audience))
   {
     GNUNET_free (code_payload);
-    GNUNET_free (plaintext);
+    if (NULL != *nonce_str)
+      GNUNET_free (*nonce_str);
     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
                 "Audience in ticket does not match client!\n");
     return GNUNET_SYSERR;
@@ -697,24 +690,22 @@ OIDC_parse_authz_code (const struct GNUNET_CRYPTO_EcdsaPrivateKey *ecdsa_priv,
                                    &ticket->identity))
   {
     GNUNET_free (code_payload);
-    GNUNET_free (plaintext);
+    if (NULL != *nonce_str)
+      GNUNET_free (*nonce_str);
     GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Signature of AuthZ code invalid!\n");
     return GNUNET_SYSERR;
   }
   // Attributes
-  attrs_ser = ((char *) &params[1]) + code_challenge_len;
+  attrs_ser = ((char *) &params[1]) + code_challenge_len + nonce_len;
   attrs_ser_len = ntohl (params->attr_list_len);
   *attrs = GNUNET_RECLAIM_attribute_list_deserialize (attrs_ser, attrs_ser_len);
-  attests_ser = ((char*) attrs_ser) + attrs_ser_len;
-  attests_ser_len = ntohl (params->attest_list_len);
-  *attests = GNUNET_RECLAIM_attestation_list_deserialize (attests_ser,
-                                                          attests_ser_len);
-
-  *nonce_str = NULL;
-  if (nonce != 0)
-    GNUNET_asprintf (nonce_str, "%u", nonce);
+  presentations_ser = ((char*) attrs_ser) + attrs_ser_len;
+  pres_ser_len = ntohl (params->pres_list_len);
+  *presentations =
+    GNUNET_RECLAIM_presentation_list_deserialize (presentations_ser,
+                                                  pres_ser_len);
+
   GNUNET_free (code_payload);
-  GNUNET_free (plaintext);
   return GNUNET_OK;
 }
 
@@ -757,15 +748,107 @@ OIDC_build_token_response (const char *access_token,
  * Generate a new access token
  */
 char *
-OIDC_access_token_new ()
+OIDC_access_token_new (const struct GNUNET_RECLAIM_Ticket *ticket)
 {
   char *access_token;
-  uint64_t random_number;
 
-  random_number =
-    GNUNET_CRYPTO_random_u64 (GNUNET_CRYPTO_QUALITY_NONCE, UINT64_MAX);
-  GNUNET_STRINGS_base64_encode (&random_number,
-                                sizeof(uint64_t),
+  GNUNET_STRINGS_base64_encode (ticket,
+                                sizeof(*ticket),
                                 &access_token);
   return access_token;
 }
+
+
+/**
+ * Parse an access token
+ */
+int
+OIDC_access_token_parse (const char *token,
+                         struct GNUNET_RECLAIM_Ticket **ticket)
+{
+  if (sizeof (struct GNUNET_RECLAIM_Ticket) !=
+      GNUNET_STRINGS_base64_decode (token,
+                                    strlen (token),
+                                    (void**) ticket))
+    return GNUNET_SYSERR;
+  return GNUNET_OK;
+}
+
+
+/**
+ * Checks if a claim is implicitly requested through standard
+ * scope(s) or explicitly through non-standard scope.
+ *
+ * @param scopes the scopes which have been requested
+ * @param attr the attribute name to check
+ * @return GNUNET_YES if attribute is implcitly requested
+ */
+enum GNUNET_GenericReturnValue
+OIDC_check_scopes_for_claim_request (const char*scopes,
+                                     const char*attr)
+{
+  char *scope_variables;
+  char *scope_variable;
+  char delimiter[] = " ";
+  int i;
+
+  scope_variables = GNUNET_strdup (scopes);
+  scope_variable = strtok (scope_variables, delimiter);
+  while (NULL != scope_variable)
+  {
+    if (0 == strcmp ("profile", scope_variable))
+    {
+      for (i = 0; i < 14; i++)
+      {
+        if (0 == strcmp (attr, OIDC_profile_claims[i]))
+        {
+          GNUNET_free (scope_variables);
+          return GNUNET_YES;
+        }
+      }
+    }
+    else if (0 == strcmp ("address", scope_variable))
+    {
+      for (i = 0; i < 5; i++)
+      {
+        if (0 == strcmp (attr, OIDC_address_claims[i]))
+        {
+          GNUNET_free (scope_variables);
+          return GNUNET_YES;
+        }
+      }
+    }
+    else if (0 == strcmp ("email", scope_variable))
+    {
+      for (i = 0; i < 2; i++)
+      {
+        if (0 == strcmp (attr, OIDC_email_claims[i]))
+        {
+          GNUNET_free (scope_variables);
+          return GNUNET_YES;
+        }
+      }
+    }
+    else if (0 == strcmp ("phone", scope_variable))
+    {
+      for (i = 0; i < 2; i++)
+      {
+        if (0 == strcmp (attr, OIDC_phone_claims[i]))
+        {
+          GNUNET_free (scope_variables);
+          return GNUNET_YES;
+        }
+      }
+
+    } else if (0 == strcmp (attr, scope_variable))
+    {
+      /** attribute matches requested scope **/
+      GNUNET_free (scope_variables);
+      return GNUNET_YES;
+    }
+    scope_variable = strtok (NULL, delimiter);
+  }
+  GNUNET_free (scope_variables);
+  return GNUNET_NO;
+
+}
diff --git a/src/reclaim/oidc_helper.h b/src/reclaim/oidc_helper.h
index 2c533357e005837235c912ea0a305b2ab55ce01a..10a6f3d1fc6ea95dd36e9b3e628f8c9c70028247 100644
--- a/src/reclaim/oidc_helper.h
+++ b/src/reclaim/oidc_helper.h
@@ -44,15 +44,16 @@
  * @param aud_key the public of the audience
  * @param sub_key the public key of the subject
  * @param attrs the attribute list
+ * @param presentations credential presentation list (may be empty)
  * @param expiration_time the validity of the token
  * @param secret_key the key used to sign the JWT
  * @return a new base64-encoded JWT string.
  */
 char*
-OIDC_id_token_new (const struct GNUNET_CRYPTO_EcdsaPublicKey *aud_key,
+OIDC_generate_id_token (const struct GNUNET_CRYPTO_EcdsaPublicKey *aud_key,
                    const struct GNUNET_CRYPTO_EcdsaPublicKey *sub_key,
-                   struct GNUNET_RECLAIM_AttributeList *attrs,
-                   struct GNUNET_RECLAIM_AttestationList *attests,
+                   const struct GNUNET_RECLAIM_AttributeList *attrs,
+                   const struct GNUNET_RECLAIM_PresentationList *presentations,
                    const struct GNUNET_TIME_Relative *expiration_time,
                    const char *nonce,
                    const char *secret_key);
@@ -64,6 +65,7 @@ OIDC_id_token_new (const struct GNUNET_CRYPTO_EcdsaPublicKey *aud_key,
  * @param issuer the issuer of the ticket, used to sign the ticket and nonce
  * @param ticket the ticket to include in the code
  * @param attrs list of attributes to share
+ * @param presentations credential presentation list
  * @param nonce the nonce to include in the code
  * @param code_challenge PKCE code challenge
  * @return a new authorization code (caller must free)
@@ -71,8 +73,8 @@ OIDC_id_token_new (const struct GNUNET_CRYPTO_EcdsaPublicKey *aud_key,
 char*
 OIDC_build_authz_code (const struct GNUNET_CRYPTO_EcdsaPrivateKey *issuer,
                        const struct GNUNET_RECLAIM_Ticket *ticket,
-                       struct GNUNET_RECLAIM_AttributeList *attrs,
-                       struct GNUNET_RECLAIM_AttestationList *attests,
+                       const struct GNUNET_RECLAIM_AttributeList *attrs,
+                       const struct GNUNET_RECLAIM_PresentationList *presentations,
                        const char *nonce,
                        const char *code_challenge);
 
@@ -86,16 +88,17 @@ OIDC_build_authz_code (const struct GNUNET_CRYPTO_EcdsaPrivateKey *issuer,
  * @param code_verfier PKCE code verifier
  * @param ticket where to store the ticket
  * @param attrs the attributes found in the code
+ * @param presentations credential presentation list
  * @param nonce where to store the nonce
  * @return GNUNET_OK if successful, else GNUNET_SYSERR
  */
 int
-OIDC_parse_authz_code (const struct GNUNET_CRYPTO_EcdsaPrivateKey *ecdsa_priv,
+OIDC_parse_authz_code (const struct GNUNET_CRYPTO_EcdsaPublicKey *ecdsa_pub,
                        const char *code,
                        const char *code_verifier,
                        struct GNUNET_RECLAIM_Ticket *ticket,
                        struct GNUNET_RECLAIM_AttributeList **attrs,
-                       struct GNUNET_RECLAIM_AttestationList **attests,
+                       struct GNUNET_RECLAIM_PresentationList **presentations,
                        char **nonce);
 
 /**
@@ -117,7 +120,40 @@ OIDC_build_token_response (const char *access_token,
  * Generate a new access token
  */
 char*
-OIDC_access_token_new ();
+OIDC_access_token_new (const struct GNUNET_RECLAIM_Ticket *ticket);
 
+/**
+ * Parse an access token
+ */
+int
+OIDC_access_token_parse (const char* token,
+                         struct GNUNET_RECLAIM_Ticket **ticket);
+
+
+/**
+ * Checks if a claim is implicitly requested through standard
+ * scope(s)
+ *
+ * @param scopes the scopes which have been requested
+ * @param attr the attribute name to check
+ * @return GNUNET_YES if attribute is implcitly requested
+ */
+enum GNUNET_GenericReturnValue
+OIDC_check_scopes_for_claim_request (const char *scopes,
+                                     const char *attr);
+
+
+/**
+ * Generate userinfo JSON as string
+ *
+ * @param sub_key the subject (user)
+ * @param attrs user attribute list
+ * @param presentations credential presentation list
+ * @return Userinfo JSON
+ */
+char *
+OIDC_generate_userinfo (const struct GNUNET_CRYPTO_EcdsaPublicKey *sub_key,
+                        const struct GNUNET_RECLAIM_AttributeList *attrs,
+                        const struct GNUNET_RECLAIM_PresentationList *presentations);
 
 #endif
diff --git a/src/reclaim/plugin_gnsrecord_reclaim.c b/src/reclaim/plugin_gnsrecord_reclaim.c
index b91e123a3c23f8cfd73391b6dfe950f3c75ffa53..60c49fd6a0d3fbebc81ab2b070e3d0c46b1786c9 100644
--- a/src/reclaim/plugin_gnsrecord_reclaim.c
+++ b/src/reclaim/plugin_gnsrecord_reclaim.c
@@ -51,8 +51,8 @@ value_to_string (void *cls, uint32_t type, const void *data, size_t data_size)
   case GNUNET_GNSRECORD_TYPE_RECLAIM_ATTRIBUTE_REF:
   case GNUNET_GNSRECORD_TYPE_RECLAIM_TICKET:
   case GNUNET_GNSRECORD_TYPE_RECLAIM_MASTER:
-  case GNUNET_GNSRECORD_TYPE_RECLAIM_ATTESTATION:
-  case GNUNET_GNSRECORD_TYPE_RECLAIM_ATTESTATION_REF:
+  case GNUNET_GNSRECORD_TYPE_RECLAIM_CREDENTIAL:
+  case GNUNET_GNSRECORD_TYPE_RECLAIM_PRESENTATION:
     return GNUNET_STRINGS_data_to_string_alloc (data, data_size);
 
   default:
@@ -89,8 +89,8 @@ string_to_value (void *cls, uint32_t type, const char *s, void **data,
   case GNUNET_GNSRECORD_TYPE_RECLAIM_ATTRIBUTE_REF:
   case GNUNET_GNSRECORD_TYPE_RECLAIM_MASTER:
   case GNUNET_GNSRECORD_TYPE_RECLAIM_TICKET:
-  case GNUNET_GNSRECORD_TYPE_RECLAIM_ATTESTATION:
-  case GNUNET_GNSRECORD_TYPE_RECLAIM_ATTESTATION_REF:
+  case GNUNET_GNSRECORD_TYPE_RECLAIM_CREDENTIAL:
+  case GNUNET_GNSRECORD_TYPE_RECLAIM_PRESENTATION:
     return GNUNET_STRINGS_string_to_data (s, strlen (s), *data, *data_size);
 
   default:
@@ -110,8 +110,8 @@ static struct
 } name_map[] = {
   { "RECLAIM_ATTRIBUTE", GNUNET_GNSRECORD_TYPE_RECLAIM_ATTRIBUTE },
   { "RECLAIM_ATTRIBUTE_REF", GNUNET_GNSRECORD_TYPE_RECLAIM_ATTRIBUTE_REF },
-  { "RECLAIM_ATTESTATION", GNUNET_GNSRECORD_TYPE_RECLAIM_ATTESTATION },
-  { "RECLAIM_ATTESTATION_REF", GNUNET_GNSRECORD_TYPE_RECLAIM_ATTESTATION_REF },
+  { "RECLAIM_CREDENTIAL", GNUNET_GNSRECORD_TYPE_RECLAIM_CREDENTIAL },
+  { "RECLAIM_PRESENTATION", GNUNET_GNSRECORD_TYPE_RECLAIM_PRESENTATION },
   { "RECLAIM_MASTER", GNUNET_GNSRECORD_TYPE_RECLAIM_MASTER },
   { "RECLAIM_OIDC_CLIENT", GNUNET_GNSRECORD_TYPE_RECLAIM_OIDC_CLIENT },
   { "RECLAIM_OIDC_REDIRECT", GNUNET_GNSRECORD_TYPE_RECLAIM_OIDC_REDIRECT },
diff --git a/src/reclaim/plugin_reclaim_attribute_basic.c b/src/reclaim/plugin_reclaim_attribute_basic.c
index 47fdd5f1106a498ba11f60a4cf1fef20afb9fc77..286186a9337cd6f7a1ed98d616b29245ee3e7972 100644
--- a/src/reclaim/plugin_reclaim_attribute_basic.c
+++ b/src/reclaim/plugin_reclaim_attribute_basic.c
@@ -90,6 +90,7 @@ basic_string_to_value (void *cls,
   }
 }
 
+
 /**
  * Mapping of attribute type numbers to human-readable
  * attribute type names.
diff --git a/src/reclaim/plugin_reclaim_credential_jwt.c b/src/reclaim/plugin_reclaim_credential_jwt.c
new file mode 100644
index 0000000000000000000000000000000000000000..6f52f3a4e4667687bad30bb5ebab5b9b61513e7f
--- /dev/null
+++ b/src/reclaim/plugin_reclaim_credential_jwt.c
@@ -0,0 +1,435 @@
+/*
+     This file is part of GNUnet
+     Copyright (C) 2013, 2014, 2016 GNUnet e.V.
+
+     GNUnet is free software: you can redistribute it and/or modify it
+     under the terms of the GNU Affero General Public License as published
+     by the Free Software Foundation, either version 3 of the License,
+     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
+     Affero General Public License for more details.
+
+     You should have received a copy of the GNU Affero General Public License
+     along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+     SPDX-License-Identifier: AGPL3.0-or-later
+ */
+
+/**
+ * @file reclaim/plugin_reclaim_credential_jwt.c
+ * @brief reclaim-credential-plugin-jwt attribute plugin to provide the API for
+ *                                      JWT credentials.
+ *
+ * @author Martin Schanzenbach
+ */
+#include "platform.h"
+#include "gnunet_util_lib.h"
+#include "gnunet_reclaim_plugin.h"
+#include <inttypes.h>
+#include <jansson.h>
+
+/**
+   * Convert the 'value' of an credential to a string.
+   *
+   * @param cls closure, unused
+   * @param type type of the credential
+   * @param data value in binary encoding
+   * @param data_size number of bytes in @a data
+   * @return NULL on error, otherwise human-readable representation of the value
+   */
+static char *
+jwt_value_to_string (void *cls,
+                     uint32_t type,
+                     const void *data,
+                     size_t data_size)
+{
+  switch (type)
+  {
+  case GNUNET_RECLAIM_CREDENTIAL_TYPE_JWT:
+    return GNUNET_strndup (data, data_size);
+
+  default:
+    return NULL;
+  }
+}
+
+
+/**
+ * Convert human-readable version of a 'value' of an credential to the binary
+ * representation.
+ *
+ * @param cls closure, unused
+ * @param type type of the credential
+ * @param s human-readable string
+ * @param data set to value in binary encoding (will be allocated)
+ * @param data_size set to number of bytes in @a data
+ * @return #GNUNET_OK on success
+ */
+static int
+jwt_string_to_value (void *cls,
+                     uint32_t type,
+                     const char *s,
+                     void **data,
+                     size_t *data_size)
+{
+  if (NULL == s)
+    return GNUNET_SYSERR;
+  switch (type)
+  {
+  case GNUNET_RECLAIM_CREDENTIAL_TYPE_JWT:
+    *data = GNUNET_strdup (s);
+    *data_size = strlen (s);
+    return GNUNET_OK;
+
+  default:
+    return GNUNET_SYSERR;
+  }
+}
+
+
+/**
+ * Mapping of credential type numbers to human-readable
+ * credential type names.
+ */
+static struct
+{
+  const char *name;
+  uint32_t number;
+} jwt_cred_name_map[] = { { "JWT", GNUNET_RECLAIM_CREDENTIAL_TYPE_JWT },
+                          { NULL, UINT32_MAX } };
+
+/**
+   * Convert a type name to the corresponding number.
+   *
+   * @param cls closure, unused
+   * @param jwt_typename name to convert
+   * @return corresponding number, UINT32_MAX on error
+   */
+static uint32_t
+jwt_typename_to_number (void *cls, const char *jwt_typename)
+{
+  unsigned int i;
+
+  i = 0;
+  while ((NULL != jwt_cred_name_map[i].name) &&
+         (0 != strcasecmp (jwt_typename, jwt_cred_name_map[i].name)))
+    i++;
+  return jwt_cred_name_map[i].number;
+}
+
+
+/**
+ * Convert a type number (i.e. 1) to the corresponding type string
+ *
+ * @param cls closure, unused
+ * @param type number of a type to convert
+ * @return corresponding typestring, NULL on error
+ */
+static const char *
+jwt_number_to_typename (void *cls, uint32_t type)
+{
+  unsigned int i;
+
+  i = 0;
+  while ((NULL != jwt_cred_name_map[i].name) && (type !=
+                                                 jwt_cred_name_map[i].
+                                                 number))
+    i++;
+  return jwt_cred_name_map[i].name;
+}
+
+
+/**
+ * Parse a JWT and return the respective claim value as Attribute
+ *
+ * @param cls the plugin
+ * @param cred the jwt credential
+ * @return a GNUNET_RECLAIM_Attribute, containing the new value
+ */
+struct GNUNET_RECLAIM_AttributeList *
+jwt_parse_attributes (void *cls,
+                      const char *data)
+{
+  char *jwt_string;
+  struct GNUNET_RECLAIM_AttributeList *attrs;
+  char delim[] = ".";
+  char *val_str = NULL;
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Parsing JWT attributes.\n");
+  char *decoded_jwt;
+  json_t *json_val;
+  json_error_t *json_err = NULL;
+
+  attrs = GNUNET_new (struct GNUNET_RECLAIM_AttributeList);
+
+  jwt_string = GNUNET_strdup (data);
+  const char *jwt_body = strtok (jwt_string, delim);
+  jwt_body = strtok (NULL, delim);
+  GNUNET_STRINGS_base64url_decode (jwt_body, strlen (jwt_body),
+                                   (void **) &decoded_jwt);
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Decoded JWT: %s\n", decoded_jwt);
+  GNUNET_assert (NULL != decoded_jwt);
+  json_val = json_loads (decoded_jwt, JSON_DECODE_ANY, json_err);
+  const char *key;
+  json_t *value;
+  json_object_foreach (json_val, key, value) {
+    if (0 == strcmp ("iss", key))
+      continue;
+    if (0 == strcmp ("jti", key))
+      continue;
+    if (0 == strcmp ("exp", key))
+      continue;
+    if (0 == strcmp ("iat", key))
+      continue;
+    if (0 == strcmp ("nbf", key))
+      continue;
+    if (0 == strcmp ("aud", key))
+      continue;
+    val_str = json_dumps (value, JSON_ENCODE_ANY);
+    GNUNET_RECLAIM_attribute_list_add (attrs,
+                                       key,
+                                       NULL,
+                                       GNUNET_RECLAIM_ATTRIBUTE_TYPE_STRING,// FIXME
+                                       val_str,
+                                       strlen (val_str));
+    GNUNET_free (val_str);
+  }
+  GNUNET_free (jwt_string);
+  return attrs;
+}
+
+
+/**
+ * Parse a JWT and return the respective claim value as Attribute
+ *
+ * @param cls the plugin
+ * @param cred the jwt credential
+ * @return a GNUNET_RECLAIM_Attribute, containing the new value
+ */
+struct GNUNET_RECLAIM_AttributeList *
+jwt_parse_attributes_c (void *cls,
+                        const struct GNUNET_RECLAIM_Credential *cred)
+{
+  return jwt_parse_attributes (cls, cred->data);
+}
+
+
+/**
+ * Parse a JWT and return the respective claim value as Attribute
+ *
+ * @param cls the plugin
+ * @param cred the jwt credential
+ * @return a GNUNET_RECLAIM_Attribute, containing the new value
+ */
+struct GNUNET_RECLAIM_AttributeList *
+jwt_parse_attributes_p (void *cls,
+                        const struct GNUNET_RECLAIM_Presentation *cred)
+{
+  return jwt_parse_attributes (cls, cred->data);
+}
+
+
+/**
+ * Parse a JWT and return the issuer
+ *
+ * @param cls the plugin
+ * @param cred the jwt credential
+ * @return a string, containing the isser
+ */
+char *
+jwt_get_issuer (void *cls,
+                const char *data)
+{
+  const char *jwt_body;
+  char *jwt_string;
+  char delim[] = ".";
+  char *issuer = NULL;
+  char *decoded_jwt;
+  json_t *issuer_json;
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Parsing JWT attributes.\n");
+  json_t *json_val;
+  json_error_t *json_err = NULL;
+
+  jwt_string = GNUNET_strdup (data);
+  jwt_body = strtok (jwt_string, delim);
+  jwt_body = strtok (NULL, delim);
+  GNUNET_STRINGS_base64url_decode (jwt_body, strlen (jwt_body),
+                                   (void **) &decoded_jwt);
+  json_val = json_loads (decoded_jwt, JSON_DECODE_ANY, json_err);
+  issuer_json = json_object_get (json_val, "iss");
+  if ((NULL == issuer_json) || (! json_is_string (issuer_json)))
+    return NULL;
+  issuer = GNUNET_strdup (json_string_value (issuer_json));
+  GNUNET_free (jwt_string);
+  return issuer;
+}
+
+
+/**
+ * Parse a JWT and return the issuer
+ *
+ * @param cls the plugin
+ * @param cred the jwt credential
+ * @return a string, containing the isser
+ */
+char *
+jwt_get_issuer_c (void *cls,
+                  const struct GNUNET_RECLAIM_Credential *cred)
+{
+  if (GNUNET_RECLAIM_CREDENTIAL_TYPE_JWT != cred->type)
+    return NULL;
+  return jwt_get_issuer (cls, cred->data);
+}
+
+
+/**
+ * Parse a JWT and return the issuer
+ *
+ * @param cls the plugin
+ * @param cred the jwt credential
+ * @return a string, containing the isser
+ */
+char *
+jwt_get_issuer_p (void *cls,
+                  const struct GNUNET_RECLAIM_Presentation *cred)
+{
+  if (GNUNET_RECLAIM_CREDENTIAL_TYPE_JWT != cred->type)
+    return NULL;
+  return jwt_get_issuer (cls, cred->data);
+}
+
+
+/**
+ * Parse a JWT and return the expiration
+ *
+ * @param cls the plugin
+ * @param cred the jwt credential
+ * @return a string, containing the isser
+ */
+int
+jwt_get_expiration (void *cls,
+                    const char *data,
+                    struct GNUNET_TIME_Absolute *exp)
+{
+  const char *jwt_body;
+  char *jwt_string;
+  char delim[] = ".";
+  char *decoded_jwt;
+  json_t *exp_json;
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Parsing JWT attributes.\n");
+  json_t *json_val;
+  json_error_t *json_err = NULL;
+
+  jwt_string = GNUNET_strdup (data);
+  jwt_body = strtok (jwt_string, delim);
+  jwt_body = strtok (NULL, delim);
+  GNUNET_STRINGS_base64url_decode (jwt_body, strlen (jwt_body),
+                                   (void **) &decoded_jwt);
+  json_val = json_loads (decoded_jwt, JSON_DECODE_ANY, json_err);
+  exp_json = json_object_get (json_val, "exp");
+  if ((NULL == exp_json) || (! json_is_integer (exp_json)))
+    return GNUNET_SYSERR;
+  exp->abs_value_us = json_integer_value (exp_json) * 1000 * 1000;
+  GNUNET_free (jwt_string);
+  return GNUNET_OK;
+}
+
+
+/**
+ * Parse a JWT and return the expiration
+ *
+ * @param cls the plugin
+ * @param cred the jwt credential
+ * @return a string, containing the isser
+ */
+int
+jwt_get_expiration_c (void *cls,
+                      const struct GNUNET_RECLAIM_Credential *cred,
+                      struct GNUNET_TIME_Absolute *exp)
+{
+  return jwt_get_expiration (cls, cred->data, exp);
+}
+
+
+/**
+ * Parse a JWT and return the expiration
+ *
+ * @param cls the plugin
+ * @param cred the jwt credential
+ * @return a string, containing the isser
+ */
+int
+jwt_get_expiration_p (void *cls,
+                      const struct GNUNET_RECLAIM_Presentation *cred,
+                      struct GNUNET_TIME_Absolute *exp)
+{
+  return jwt_get_expiration (cls, cred->data, exp);
+}
+
+
+int
+jwt_create_presentation (void *cls,
+                         const struct GNUNET_RECLAIM_Credential *cred,
+                         const struct GNUNET_RECLAIM_AttributeList *attrs,
+                         struct GNUNET_RECLAIM_Presentation **pres)
+{
+  // FIXME sanity checks??
+  if (GNUNET_RECLAIM_CREDENTIAL_TYPE_JWT != cred->type)
+    return GNUNET_NO;
+  *pres = GNUNET_RECLAIM_presentation_new (GNUNET_RECLAIM_CREDENTIAL_TYPE_JWT,
+                                           cred->data,
+                                           cred->data_size);
+  return GNUNET_OK;
+}
+
+
+/**
+ * Entry point for the plugin.
+ *
+ * @param cls NULL
+ * @return the exported block API
+ */
+void *
+libgnunet_plugin_reclaim_credential_jwt_init (void *cls)
+{
+  struct GNUNET_RECLAIM_CredentialPluginFunctions *api;
+
+  api = GNUNET_new (struct GNUNET_RECLAIM_CredentialPluginFunctions);
+  api->value_to_string = &jwt_value_to_string;
+  api->string_to_value = &jwt_string_to_value;
+  api->typename_to_number = &jwt_typename_to_number;
+  api->number_to_typename = &jwt_number_to_typename;
+  api->get_attributes = &jwt_parse_attributes_c;
+  api->get_issuer = &jwt_get_issuer_c;
+  api->get_expiration = &jwt_get_expiration_c;
+  api->value_to_string_p = &jwt_value_to_string;
+  api->string_to_value_p = &jwt_string_to_value;
+  api->typename_to_number_p = &jwt_typename_to_number;
+  api->number_to_typename_p = &jwt_number_to_typename;
+  api->get_attributes_p = &jwt_parse_attributes_p;
+  api->get_issuer_p = &jwt_get_issuer_p;
+  api->get_expiration_p = &jwt_get_expiration_p;
+  api->create_presentation = &jwt_create_presentation;
+  return api;
+}
+
+
+/**
+ * Exit point from the plugin.
+ *
+ * @param cls the return value from #libgnunet_plugin_block_test_init()
+ * @return NULL
+ */
+void *
+libgnunet_plugin_reclaim_credential_jwt_done (void *cls)
+{
+  struct GNUNET_RECLAIM_CredentialPluginFunctions *api = cls;
+
+  GNUNET_free (api);
+  return NULL;
+}
+
+
+/* end of plugin_reclaim_credential_type_jwt.c */
diff --git a/src/reclaim/plugin_rest_openid_connect.c b/src/reclaim/plugin_rest_openid_connect.c
index 36ae937c1731700f3660a85f77c61216cf2c4648..5b0bb2b6f37130c2e05d753f165e2f0246223590 100644
--- a/src/reclaim/plugin_rest_openid_connect.c
+++ b/src/reclaim/plugin_rest_openid_connect.c
@@ -28,6 +28,8 @@
 #include <inttypes.h>
 #include <jansson.h>
 
+#include "gnunet_buffer_lib.h"
+#include "gnunet_strings_lib.h"
 #include "gnunet_gns_service.h"
 #include "gnunet_gnsrecord_lib.h"
 #include "gnunet_identity_service.h"
@@ -39,11 +41,17 @@
 #include "gnunet_signatures.h"
 #include "microhttpd.h"
 #include "oidc_helper.h"
+
 /**
  * REST root namespace
  */
 #define GNUNET_REST_API_NS_OIDC "/openid"
 
+/**
+ * OIDC config
+ */
+#define GNUNET_REST_API_NS_OIDC_CONFIG "/.well-known/openid-configuration"
+
 /**
  * Authorize endpoint
  */
@@ -236,12 +244,6 @@ static char *OIDC_ignored_parameter_array[] = { "display",
  */
 struct GNUNET_CONTAINER_MultiHashMap *OIDC_cookie_jar_map;
 
-/**
- * Hash map that links the issued access token to the corresponding ticket and
- * ego
- */
-struct GNUNET_CONTAINER_MultiHashMap *OIDC_access_token_map;
-
 /**
  * The configuration handle
  */
@@ -252,6 +254,36 @@ const struct GNUNET_CONFIGURATION_Handle *cfg;
  */
 static char *allow_methods;
 
+/**
+ * Ego list
+ */
+static struct EgoEntry *ego_head;
+
+/**
+ * Ego list
+ */
+static struct EgoEntry *ego_tail;
+
+/**
+ * The processing state
+ */
+static int state;
+
+/**
+ * Handle to Identity service.
+  */
+static struct GNUNET_IDENTITY_Handle *identity_handle;
+
+/**
+ * GNS handle
+ */
+static struct GNUNET_GNS_Handle *gns_handle;
+
+/**
+ * Identity Provider
+ */
+static struct GNUNET_RECLAIM_Handle *idp;
+
 /**
  * @brief struct returned by the initialization function of the plugin
  */
@@ -325,10 +357,6 @@ struct OIDC_Variables
    */
   char *code_verifier;
 
-  /**
-   * The response JSON
-   */
-  json_t *response;
 };
 
 /**
@@ -366,14 +394,14 @@ struct EgoEntry
 struct RequestHandle
 {
   /**
-   * Ego list
+   * DLL
    */
-  struct EgoEntry *ego_head;
+  struct RequestHandle *next;
 
   /**
-   * Ego list
+   * DLL
    */
-  struct EgoEntry *ego_tail;
+  struct RequestHandle *prev;
 
   /**
    * Selected ego
@@ -390,40 +418,15 @@ struct RequestHandle
    */
   struct OIDC_Variables *oidc;
 
-  /**
-   * The processing state
-   */
-  int state;
-
-  /**
-   * Handle to Identity service.
-   */
-  struct GNUNET_IDENTITY_Handle *identity_handle;
-
-  /**
-   * Rest connection
-   */
-  struct GNUNET_REST_RequestHandle *rest_handle;
-
-  /**
-   * GNS handle
-   */
-  struct GNUNET_GNS_Handle *gns_handle;
-
   /**
    * GNS lookup op
    */
   struct GNUNET_GNS_LookupRequest *gns_op;
 
   /**
-   * Handle to NAMESTORE
-   */
-  struct GNUNET_NAMESTORE_Handle *namestore_handle;
-
-  /**
-   * Iterator for NAMESTORE
+   * Rest connection
    */
-  struct GNUNET_NAMESTORE_ZoneIterator *namestore_handle_it;
+  struct GNUNET_REST_RequestHandle *rest_handle;
 
   /**
    * Attribute claim list for id_token
@@ -436,20 +439,20 @@ struct RequestHandle
   struct GNUNET_RECLAIM_AttributeList *attr_userinfo_list;
 
   /**
-   * Attestation list
+   * Credentials
    */
-  struct GNUNET_RECLAIM_AttestationList *attests_list;
+  struct GNUNET_RECLAIM_CredentialList *credentials;
 
+  /**
+   * Presentations
+   */
+  struct GNUNET_RECLAIM_PresentationList *presentations;
 
   /**
    * IDENTITY Operation
    */
   struct GNUNET_IDENTITY_Operation *op;
 
-  /**
-   * Identity Provider
-   */
-  struct GNUNET_RECLAIM_Handle *idp;
 
   /**
    * Idp Operation
@@ -462,9 +465,9 @@ struct RequestHandle
   struct GNUNET_RECLAIM_AttributeIterator *attr_it;
 
   /**
-   * Attestation iterator
+   * Credential iterator
    */
-  struct GNUNET_RECLAIM_AttestationIterator *attest_it;
+  struct GNUNET_RECLAIM_CredentialIterator *cred_it;
 
 
   /**
@@ -531,8 +534,24 @@ struct RequestHandle
    * Reponse code
    */
   int response_code;
+
+  /**
+   * Public client
+   */
+  int public_client;
 };
 
+/**
+ * DLL
+ */
+static struct RequestHandle *requests_head;
+
+/**
+ * DLL
+ */
+static struct RequestHandle *requests_tail;
+
+
 /**
  * Cleanup lookup handle
  * @param handle Handle to clean up
@@ -540,23 +559,18 @@ struct RequestHandle
 static void
 cleanup_handle (struct RequestHandle *handle)
 {
-  struct EgoEntry *ego_entry;
 
   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Cleaning up\n");
   if (NULL != handle->timeout_task)
     GNUNET_SCHEDULER_cancel (handle->timeout_task);
-  if (NULL != handle->identity_handle)
-    GNUNET_IDENTITY_disconnect (handle->identity_handle);
   if (NULL != handle->attr_it)
     GNUNET_RECLAIM_get_attributes_stop (handle->attr_it);
-  if (NULL != handle->attest_it)
-    GNUNET_RECLAIM_get_attestations_stop (handle->attest_it);
+  if (NULL != handle->cred_it)
+    GNUNET_RECLAIM_get_credentials_stop (handle->cred_it);
   if (NULL != handle->ticket_it)
     GNUNET_RECLAIM_ticket_iteration_stop (handle->ticket_it);
   if (NULL != handle->idp_op)
     GNUNET_RECLAIM_cancel (handle->idp_op);
-  if (NULL != handle->idp)
-    GNUNET_RECLAIM_disconnect (handle->idp);
   GNUNET_free (handle->url);
   GNUNET_free (handle->tld);
   GNUNET_free (handle->redirect_prefix);
@@ -565,11 +579,6 @@ cleanup_handle (struct RequestHandle *handle)
   GNUNET_free (handle->edesc);
   if (NULL != handle->gns_op)
     GNUNET_GNS_lookup_cancel (handle->gns_op);
-  if (NULL != handle->gns_handle)
-    GNUNET_GNS_disconnect (handle->gns_handle);
-
-  if (NULL != handle->namestore_handle)
-    GNUNET_NAMESTORE_disconnect (handle->namestore_handle);
   if (NULL != handle->oidc)
   {
     GNUNET_free (handle->oidc->client_id);
@@ -579,36 +588,23 @@ cleanup_handle (struct RequestHandle *handle)
     GNUNET_free (handle->oidc->response_type);
     GNUNET_free (handle->oidc->scope);
     GNUNET_free (handle->oidc->state);
-    json_decref (handle->oidc->response);
     GNUNET_free (handle->oidc);
   }
   if (NULL!=handle->attr_idtoken_list)
     GNUNET_RECLAIM_attribute_list_destroy (handle->attr_idtoken_list);
   if (NULL!=handle->attr_userinfo_list)
     GNUNET_RECLAIM_attribute_list_destroy (handle->attr_userinfo_list);
-  if (NULL!=handle->attests_list)
-    GNUNET_RECLAIM_attestation_list_destroy (handle->attests_list);
-
-  while (NULL != (ego_entry = handle->ego_head))
-  {
-    GNUNET_CONTAINER_DLL_remove (handle->ego_head,
-                                 handle->ego_tail,
-                                 ego_entry);
-    GNUNET_free (ego_entry->identifier);
-    GNUNET_free (ego_entry->keystring);
-    GNUNET_free (ego_entry);
-  }
+  if (NULL!=handle->credentials)
+    GNUNET_RECLAIM_credential_list_destroy (handle->credentials);
+  if (NULL!=handle->presentations)
+    GNUNET_RECLAIM_presentation_list_destroy (handle->presentations);
+  GNUNET_CONTAINER_DLL_remove (requests_head,
+                               requests_tail,
+                               handle);
   GNUNET_free (handle);
 }
 
 
-static void
-cleanup_handle_delayed (void *cls)
-{
-  cleanup_handle (cls);
-}
-
-
 /**
  * Task run on error, sends error message.  Cleans up everything.
  *
@@ -637,7 +633,7 @@ do_error (void *cls)
                            MHD_HTTP_HEADER_CONTENT_TYPE,
                            "application/json");
   handle->proc (handle->proc_cls, resp, handle->response_code);
-  GNUNET_SCHEDULER_add_now (&cleanup_handle_delayed, handle);
+  cleanup_handle (handle);
   GNUNET_free (json_error);
 }
 
@@ -655,6 +651,8 @@ do_userinfo_error (void *cls)
   struct MHD_Response *resp;
   char *error;
 
+  GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+              "Error: %s\n", handle->edesc);
   GNUNET_asprintf (&error,
                    "error=\"%s\", error_description=\"%s\"",
                    handle->emsg,
@@ -662,7 +660,7 @@ do_userinfo_error (void *cls)
   resp = GNUNET_REST_create_response ("");
   MHD_add_response_header (resp, MHD_HTTP_HEADER_WWW_AUTHENTICATE, "Bearer");
   handle->proc (handle->proc_cls, resp, handle->response_code);
-  GNUNET_SCHEDULER_add_now (&cleanup_handle_delayed, handle);
+  cleanup_handle (handle);
   GNUNET_free (error);
 }
 
@@ -689,7 +687,7 @@ do_redirect_error (void *cls)
   resp = GNUNET_REST_create_response ("");
   MHD_add_response_header (resp, "Location", redirect);
   handle->proc (handle->proc_cls, resp, MHD_HTTP_FOUND);
-  GNUNET_SCHEDULER_add_now (&cleanup_handle_delayed, handle);
+  cleanup_handle (handle);
   GNUNET_free (redirect);
 }
 
@@ -709,27 +707,6 @@ do_timeout (void *cls)
 }
 
 
-/**
- * Return attributes for claim
- *
- * @param cls the request handle
- */
-static void
-return_userinfo_response (void *cls)
-{
-  char *result_str;
-  struct RequestHandle *handle = cls;
-  struct MHD_Response *resp;
-
-  result_str = json_dumps (handle->oidc->response, 0);
-  GNUNET_log (GNUNET_ERROR_TYPE_ERROR,"ID-Token: %s\n",result_str);
-  resp = GNUNET_REST_create_response (result_str);
-  handle->proc (handle->proc_cls, resp, MHD_HTTP_OK);
-  GNUNET_free (result_str);
-  cleanup_handle (handle);
-}
-
-
 /**
  * Respond to OPTIONS request
  *
@@ -854,7 +831,9 @@ login_redirect (void *cls)
 {
   char *login_base_url;
   char *new_redirect;
+  char *tmp;
   struct MHD_Response *resp;
+  struct GNUNET_Buffer buf = { 0 };
   struct RequestHandle *handle = cls;
 
   if (GNUNET_OK == GNUNET_CONFIGURATION_get_value_string (cfg,
@@ -862,27 +841,68 @@ login_redirect (void *cls)
                                                           "address",
                                                           &login_base_url))
   {
-    GNUNET_asprintf (&new_redirect,
-                     "%s?%s=%s&%s=%s&%s=%s&%s=%s&%s=%s&%s=%s&%s=%s&%s=%s",
-                     login_base_url,
-                     OIDC_RESPONSE_TYPE_KEY,
-                     handle->oidc->response_type,
-                     OIDC_CLIENT_ID_KEY,
-                     handle->oidc->client_id,
-                     OIDC_REDIRECT_URI_KEY,
-                     handle->oidc->redirect_uri,
-                     OIDC_SCOPE_KEY,
-                     handle->oidc->scope,
-                     OIDC_STATE_KEY,
-                     (NULL != handle->oidc->state) ? handle->oidc->state : "",
-                     OIDC_CODE_CHALLENGE_KEY,
-                     (NULL != handle->oidc->code_challenge) ?
-                     handle->oidc->code_challenge : "",
-                     OIDC_NONCE_KEY,
-                     (NULL != handle->oidc->nonce) ? handle->oidc->nonce : "",
-                     OIDC_CLAIMS_KEY,
-                     (NULL != handle->oidc->claims) ? handle->oidc->claims :
-                     "");
+    GNUNET_buffer_write_str (&buf, login_base_url);
+    GNUNET_buffer_write_fstr (&buf,
+                              "?%s=%s",
+                              OIDC_RESPONSE_TYPE_KEY,
+                              handle->oidc->response_type);
+    GNUNET_buffer_write_fstr (&buf,
+                              "&%s=%s",
+                              OIDC_CLIENT_ID_KEY,
+                              handle->oidc->client_id);
+    GNUNET_STRINGS_urlencode (handle->oidc->redirect_uri,
+                              strlen (handle->oidc->redirect_uri),
+                              &tmp);
+    GNUNET_buffer_write_fstr (&buf,
+                              "&%s=%s",
+                              OIDC_REDIRECT_URI_KEY,
+                              tmp);
+    GNUNET_free (tmp);
+    GNUNET_STRINGS_urlencode (handle->oidc->scope,
+                              strlen (handle->oidc->scope),
+                              &tmp);
+    GNUNET_buffer_write_fstr (&buf,
+                              "&%s=%s",
+                              OIDC_SCOPE_KEY,
+                              tmp);
+    GNUNET_free (tmp);
+    if (NULL != handle->oidc->state)
+    {
+      GNUNET_STRINGS_urlencode (handle->oidc->state,
+                                strlen (handle->oidc->state),
+                                &tmp);
+      GNUNET_buffer_write_fstr (&buf,
+                                "&%s=%s",
+                                OIDC_STATE_KEY,
+                                handle->oidc->state);
+      GNUNET_free (tmp);
+    }
+    if (NULL != handle->oidc->code_challenge)
+    {
+      GNUNET_buffer_write_fstr (&buf,
+                                "&%s=%s",
+                                OIDC_CODE_CHALLENGE_KEY,
+                                handle->oidc->code_challenge);
+    }
+    if (NULL != handle->oidc->nonce)
+    {
+      GNUNET_buffer_write_fstr (&buf,
+                                "&%s=%s",
+                                OIDC_NONCE_KEY,
+                                handle->oidc->nonce);
+    }
+    if (NULL != handle->oidc->claims)
+    {
+      GNUNET_STRINGS_urlencode (handle->oidc->claims,
+                                strlen (handle->oidc->claims),
+                                &tmp);
+      GNUNET_buffer_write_fstr (&buf,
+                                "&%s=%s",
+                                OIDC_CLAIMS_KEY,
+                                tmp);
+      GNUNET_free (tmp);
+    }
+    new_redirect = GNUNET_buffer_reap_str (&buf);
     resp = GNUNET_REST_create_response ("");
     MHD_add_response_header (resp, "Location", new_redirect);
     GNUNET_free (login_base_url);
@@ -897,7 +917,7 @@ login_redirect (void *cls)
   }
   handle->proc (handle->proc_cls, resp, MHD_HTTP_FOUND);
   GNUNET_free (new_redirect);
-  GNUNET_SCHEDULER_add_now (&cleanup_handle_delayed, handle);
+  cleanup_handle (handle);
 }
 
 
@@ -920,7 +940,9 @@ oidc_iteration_error (void *cls)
  * parameter. Otherwise redirects with error
  */
 static void
-oidc_ticket_issue_cb (void *cls, const struct GNUNET_RECLAIM_Ticket *ticket)
+oidc_ticket_issue_cb (void *cls,
+                      const struct GNUNET_RECLAIM_Ticket *ticket,
+                      const struct GNUNET_RECLAIM_PresentationList *pres)
 {
   struct RequestHandle *handle = cls;
   struct MHD_Response *resp;
@@ -943,7 +965,7 @@ oidc_ticket_issue_cb (void *cls, const struct GNUNET_RECLAIM_Ticket *ticket)
   code_string = OIDC_build_authz_code (&handle->priv_key,
                                        &handle->ticket,
                                        handle->attr_idtoken_list,
-                                       handle->attests_list,
+                                       pres,
                                        handle->oidc->nonce,
                                        handle->oidc->code_challenge);
   if ((NULL != handle->redirect_prefix) && (NULL != handle->redirect_suffix) &&
@@ -954,6 +976,8 @@ oidc_ticket_issue_cb (void *cls, const struct GNUNET_RECLAIM_Ticket *ticket)
                      handle->redirect_prefix,
                      handle->tld,
                      handle->redirect_suffix,
+                     (NULL == strchr (handle->redirect_suffix, '?') ? "?" :
+                      "&"),
                      handle->oidc->response_type,
                      code_string,
                      handle->oidc->state);
@@ -961,8 +985,10 @@ oidc_ticket_issue_cb (void *cls, const struct GNUNET_RECLAIM_Ticket *ticket)
   else
   {
     GNUNET_asprintf (&redirect_uri,
-                     "%s?%s=%s&state=%s",
+                     "%s%s%s=%s&state=%s",
                      handle->oidc->redirect_uri,
+                     (NULL == strchr (handle->oidc->redirect_uri, '?') ? "?" :
+                      "&"),
                      handle->oidc->response_type,
                      code_string,
                      handle->oidc->state);
@@ -970,7 +996,7 @@ oidc_ticket_issue_cb (void *cls, const struct GNUNET_RECLAIM_Ticket *ticket)
   resp = GNUNET_REST_create_response ("");
   MHD_add_response_header (resp, "Location", redirect_uri);
   handle->proc (handle->proc_cls, resp, MHD_HTTP_FOUND);
-  GNUNET_SCHEDULER_add_now (&cleanup_handle_delayed, handle);
+  cleanup_handle (handle);
   GNUNET_free (redirect_uri);
   GNUNET_free (ticket_str);
   GNUNET_free (code_string);
@@ -992,13 +1018,13 @@ attribute_list_merge (struct GNUNET_RECLAIM_AttributeList *list_a,
     le_m = GNUNET_new (struct GNUNET_RECLAIM_AttributeListEntry);
     le_m->attribute = GNUNET_RECLAIM_attribute_new (le_a->attribute->name,
                                                     &le_a->attribute->
-                                                    attestation,
+                                                    credential,
                                                     le_a->attribute->type,
                                                     le_a->attribute->data,
                                                     le_a->attribute->data_size);
     le_m->attribute->id = le_a->attribute->id;
     le_m->attribute->flag = le_a->attribute->flag;
-    le_m->attribute->attestation = le_a->attribute->attestation;
+    le_m->attribute->credential = le_a->attribute->credential;
     GNUNET_CONTAINER_DLL_insert (merged_list->list_head,
                                  merged_list->list_tail,
                                  le_m);
@@ -1017,13 +1043,13 @@ attribute_list_merge (struct GNUNET_RECLAIM_AttributeList *list_a,
     le_m = GNUNET_new (struct GNUNET_RECLAIM_AttributeListEntry);
     le_m->attribute = GNUNET_RECLAIM_attribute_new (le_b->attribute->name,
                                                     &le_b->attribute->
-                                                    attestation,
+                                                    credential,
                                                     le_b->attribute->type,
                                                     le_b->attribute->data,
                                                     le_b->attribute->data_size);
     le_m->attribute->id = le_b->attribute->id;
     le_m->attribute->flag = le_b->attribute->flag;
-    le_m->attribute->attestation = le_b->attribute->attestation;
+    le_m->attribute->credential = le_b->attribute->credential;
     GNUNET_CONTAINER_DLL_insert (merged_list->list_head,
                                  merged_list->list_tail,
                                  le_m);
@@ -1033,15 +1059,20 @@ attribute_list_merge (struct GNUNET_RECLAIM_AttributeList *list_a,
 
 
 static void
-oidc_attest_collect_finished_cb (void *cls)
+oidc_cred_collect_finished_cb (void *cls)
 {
   struct RequestHandle *handle = cls;
   struct GNUNET_RECLAIM_AttributeList *merged_list;
+  struct GNUNET_RECLAIM_AttributeListEntry *le_m;
 
-  handle->attest_it = NULL;
+  handle->cred_it = NULL;
   merged_list = attribute_list_merge (handle->attr_idtoken_list,
                                       handle->attr_userinfo_list);
-  handle->idp_op = GNUNET_RECLAIM_ticket_issue (handle->idp,
+  for (le_m = merged_list->list_head; NULL != le_m; le_m = le_m->next)
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                "List Attibute in ticket to issue: %s\n",
+                le_m->attribute->name);
+  handle->idp_op = GNUNET_RECLAIM_ticket_issue (idp,
                                                 &handle->priv_key,
                                                 &handle->oidc->client_pkey,
                                                 merged_list,
@@ -1055,40 +1086,40 @@ oidc_attest_collect_finished_cb (void *cls)
  * Collects all attributes for an ego if in scope parameter
  */
 static void
-oidc_attest_collect (void *cls,
-                     const struct GNUNET_CRYPTO_EcdsaPublicKey *identity,
-                     const struct GNUNET_RECLAIM_Attestation *attest)
+oidc_cred_collect (void *cls,
+                   const struct GNUNET_CRYPTO_EcdsaPublicKey *identity,
+                   const struct GNUNET_RECLAIM_Credential *cred)
 {
   struct RequestHandle *handle = cls;
   struct GNUNET_RECLAIM_AttributeListEntry *le;
-  struct GNUNET_RECLAIM_AttestationListEntry *ale;
+  struct GNUNET_RECLAIM_CredentialListEntry *ale;
 
-  for (ale = handle->attests_list->list_head; NULL != ale; ale = ale->next)
+  for (ale = handle->credentials->list_head; NULL != ale; ale = ale->next)
   {
-    if (GNUNET_NO == GNUNET_RECLAIM_id_is_equal (&ale->attestation->id,
-                                                 &attest->id))
+    if (GNUNET_NO == GNUNET_RECLAIM_id_is_equal (&ale->credential->id,
+                                                 &cred->id))
       continue;
-    /** Attestation already in list **/
-    GNUNET_RECLAIM_get_attestations_next (handle->attest_it);
+    /** Credential already in list **/
+    GNUNET_RECLAIM_get_credentials_next (handle->cred_it);
     return;
   }
 
   for (le = handle->attr_idtoken_list->list_head; NULL != le; le = le->next)
   {
-    if (GNUNET_NO == GNUNET_RECLAIM_id_is_equal (&le->attribute->attestation,
-                                                 &attest->id))
+    if (GNUNET_NO == GNUNET_RECLAIM_id_is_equal (&le->attribute->credential,
+                                                 &cred->id))
       continue;
-    /** Attestation matches for attribute, add **/
-    ale = GNUNET_new (struct GNUNET_RECLAIM_AttestationListEntry);
-    ale->attestation = GNUNET_RECLAIM_attestation_new (attest->name,
-                                                       attest->type,
-                                                       attest->data,
-                                                       attest->data_size);
-    GNUNET_CONTAINER_DLL_insert (handle->attests_list->list_head,
-                                 handle->attests_list->list_tail,
+    /** Credential matches for attribute, add **/
+    ale = GNUNET_new (struct GNUNET_RECLAIM_CredentialListEntry);
+    ale->credential = GNUNET_RECLAIM_credential_new (cred->name,
+                                                     cred->type,
+                                                     cred->data,
+                                                     cred->data_size);
+    GNUNET_CONTAINER_DLL_insert (handle->credentials->list_head,
+                                 handle->credentials->list_tail,
                                  ale);
   }
-  GNUNET_RECLAIM_get_attestations_next (handle->attest_it);
+  GNUNET_RECLAIM_get_credentials_next (handle->cred_it);
 }
 
 
@@ -1106,16 +1137,16 @@ oidc_attr_collect_finished_cb (void *cls)
     GNUNET_SCHEDULER_add_now (&do_redirect_error, handle);
     return;
   }
-  handle->attests_list = GNUNET_new (struct GNUNET_RECLAIM_AttestationList);
-  handle->attest_it =
-    GNUNET_RECLAIM_get_attestations_start (handle->idp,
-                                           &handle->priv_key,
-                                           &oidc_iteration_error,
-                                           handle,
-                                           &oidc_attest_collect,
-                                           handle,
-                                           &oidc_attest_collect_finished_cb,
-                                           handle);
+  handle->credentials = GNUNET_new (struct GNUNET_RECLAIM_CredentialList);
+  handle->cred_it =
+    GNUNET_RECLAIM_get_credentials_start (idp,
+                                          &handle->priv_key,
+                                          &oidc_iteration_error,
+                                          handle,
+                                          &oidc_cred_collect,
+                                          handle,
+                                          &oidc_cred_collect_finished_cb,
+                                          handle);
 
 }
 
@@ -1125,9 +1156,6 @@ attr_in_claims_request (struct RequestHandle *handle,
                         const char *attr_name,
                         const char *claims_parameter)
 {
-  char *scope_variables;
-  char *scope_variable;
-  char delimiter[] = " ";
   int ret = GNUNET_NO;
   json_t *root;
   json_error_t error;
@@ -1135,19 +1163,12 @@ attr_in_claims_request (struct RequestHandle *handle,
   const char *key;
   json_t *value;
 
-  scope_variables = GNUNET_strdup (handle->oidc->scope);
-  scope_variable = strtok (scope_variables, delimiter);
-  while (NULL != scope_variable)
-  {
-    if (0 == strcmp (attr_name, scope_variable))
-      break;
-    scope_variable = strtok (NULL, delimiter);
-  }
-  if (NULL != scope_variable)
-    ret = GNUNET_YES;
-  GNUNET_free (scope_variables);
+  /** Check if attribute is requested through a scope **/
+  if (GNUNET_YES == OIDC_check_scopes_for_claim_request (handle->oidc->scope,
+                                                         attr_name))
+    return GNUNET_YES;
 
-  /** Try claims parameter if no in scope */
+  /** Try claims parameter if not in scope */
   if ((NULL != handle->oidc->claims) &&
       (GNUNET_YES != ret))
   {
@@ -1199,13 +1220,13 @@ oidc_attr_collect (void *cls,
   {
     le = GNUNET_new (struct GNUNET_RECLAIM_AttributeListEntry);
     le->attribute = GNUNET_RECLAIM_attribute_new (attr->name,
-                                                  &attr->attestation,
+                                                  &attr->credential,
                                                   attr->type,
                                                   attr->data,
                                                   attr->data_size);
     le->attribute->id = attr->id;
     le->attribute->flag = attr->flag;
-    le->attribute->attestation = attr->attestation;
+    le->attribute->credential = attr->credential;
     GNUNET_CONTAINER_DLL_insert (handle->attr_idtoken_list->list_head,
                                  handle->attr_idtoken_list->list_tail,
                                  le);
@@ -1214,13 +1235,13 @@ oidc_attr_collect (void *cls,
   {
     le = GNUNET_new (struct GNUNET_RECLAIM_AttributeListEntry);
     le->attribute = GNUNET_RECLAIM_attribute_new (attr->name,
-                                                  &attr->attestation,
+                                                  &attr->credential,
                                                   attr->type,
                                                   attr->data,
                                                   attr->data_size);
     le->attribute->id = attr->id;
     le->attribute->flag = attr->flag;
-    le->attribute->attestation = attr->attestation;
+    le->attribute->credential = attr->credential;
     GNUNET_CONTAINER_DLL_insert (handle->attr_userinfo_list->list_head,
                                  handle->attr_userinfo_list->list_tail,
                                  le);
@@ -1274,7 +1295,7 @@ code_redirect (void *cls)
         return;
       }
       // iterate over egos and compare their public key
-      for (handle->ego_entry = handle->ego_head; NULL != handle->ego_entry;
+      for (handle->ego_entry = ego_head; NULL != handle->ego_entry;
            handle->ego_entry = handle->ego_entry->next)
       {
         GNUNET_IDENTITY_ego_get_public_key (handle->ego_entry->ego, &ego_pkey);
@@ -1282,13 +1303,12 @@ code_redirect (void *cls)
         {
           handle->priv_key =
             *GNUNET_IDENTITY_ego_get_private_key (handle->ego_entry->ego);
-          handle->idp = GNUNET_RECLAIM_connect (cfg);
           handle->attr_idtoken_list =
             GNUNET_new (struct GNUNET_RECLAIM_AttributeList);
           handle->attr_userinfo_list =
             GNUNET_new (struct GNUNET_RECLAIM_AttributeList);
           handle->attr_it =
-            GNUNET_RECLAIM_get_attributes_start (handle->idp,
+            GNUNET_RECLAIM_get_attributes_start (idp,
                                                  &handle->priv_key,
                                                  &oidc_iteration_error,
                                                  handle,
@@ -1339,7 +1359,7 @@ build_redirect (void *cls)
     resp = GNUNET_REST_create_response ("");
     MHD_add_response_header (resp, "Location", redirect_uri);
     handle->proc (handle->proc_cls, resp, MHD_HTTP_FOUND);
-    GNUNET_SCHEDULER_add_now (&cleanup_handle_delayed, handle);
+    cleanup_handle (handle);
     GNUNET_free (redirect_uri);
     return;
   }
@@ -1433,7 +1453,7 @@ client_redirect (void *cls)
 
   /* Lookup client redirect uri to verify request */
   handle->gns_op =
-    GNUNET_GNS_lookup (handle->gns_handle,
+    GNUNET_GNS_lookup (gns_handle,
                        GNUNET_GNS_EMPTY_LABEL_AT,
                        &handle->oidc->client_pkey,
                        GNUNET_GNSRECORD_TYPE_RECLAIM_OIDC_REDIRECT,
@@ -1448,6 +1468,7 @@ get_url_parameter_copy (const struct RequestHandle *handle, const char *key)
 {
   struct GNUNET_HashCode hc;
   char *value;
+  char *res;
 
   GNUNET_CRYPTO_hash (key, strlen (key), &hc);
   if (GNUNET_YES != GNUNET_CONTAINER_multihashmap_contains (handle->rest_handle
@@ -1458,7 +1479,8 @@ get_url_parameter_copy (const struct RequestHandle *handle, const char *key)
     GNUNET_CONTAINER_multihashmap_get (handle->rest_handle->url_param_map, &hc);
   if (NULL == value)
     return NULL;
-  return GNUNET_strdup (value);
+  GNUNET_STRINGS_urldecode (value, strlen (value), &res);
+  return res;
 }
 
 
@@ -1657,14 +1679,14 @@ authorize_endpoint (struct GNUNET_REST_RequestHandle *con_handle,
 
   // If we know this identity, translated the corresponding TLD
   // TODO: We might want to have a reverse lookup functionality for TLDs?
-  for (tmp_ego = handle->ego_head; NULL != tmp_ego; tmp_ego = tmp_ego->next)
+  for (tmp_ego = ego_head; NULL != tmp_ego; tmp_ego = tmp_ego->next)
   {
     priv_key = GNUNET_IDENTITY_ego_get_private_key (tmp_ego->ego);
     GNUNET_CRYPTO_ecdsa_key_get_public (priv_key, &pkey);
     if (0 == GNUNET_memcmp (&pkey, &handle->oidc->client_pkey))
     {
       handle->tld = GNUNET_strdup (tmp_ego->identifier);
-      handle->ego_entry = handle->ego_tail;
+      handle->ego_entry = ego_tail;
     }
   }
   handle->oidc->scope = get_url_parameter_copy (handle, OIDC_SCOPE_KEY);
@@ -1714,7 +1736,7 @@ login_cont (struct GNUNET_REST_RequestHandle *con_handle,
                 term_data);
     handle->proc (handle->proc_cls, resp, MHD_HTTP_BAD_REQUEST);
     json_decref (root);
-    GNUNET_SCHEDULER_add_now (&cleanup_handle_delayed, handle);
+    cleanup_handle (handle);
     return;
   }
   GNUNET_asprintf (&cookie, "Identity=%s", json_string_value (identity));
@@ -1744,21 +1766,21 @@ login_cont (struct GNUNET_REST_RequestHandle *con_handle,
   GNUNET_free (cookie);
   GNUNET_free (header_val);
   json_decref (root);
-  GNUNET_SCHEDULER_add_now (&cleanup_handle_delayed, handle);
+  cleanup_handle (handle);
 }
 
 
 static int
-check_authorization (struct RequestHandle *handle,
-                     struct GNUNET_CRYPTO_EcdsaPublicKey *cid)
+parse_credentials_basic_auth (struct RequestHandle *handle,
+                              char **client_id,
+                              char **client_secret)
 {
   struct GNUNET_HashCode cache_key;
   char *authorization;
   char *credentials;
   char *basic_authorization;
-  char *client_id;
+  char *client_id_tmp;
   char *pass;
-  char *expected_pass;
 
   GNUNET_CRYPTO_hash (OIDC_AUTHORIZATION_HEADER_KEY,
                       strlen (OIDC_AUTHORIZATION_HEADER_KEY),
@@ -1766,12 +1788,7 @@ check_authorization (struct RequestHandle *handle,
   if (GNUNET_NO == GNUNET_CONTAINER_multihashmap_contains (handle->rest_handle
                                                            ->header_param_map,
                                                            &cache_key))
-  {
-    handle->emsg = GNUNET_strdup (OIDC_ERROR_KEY_INVALID_CLIENT);
-    handle->edesc = GNUNET_strdup ("missing authorization");
-    handle->response_code = MHD_HTTP_UNAUTHORIZED;
     return GNUNET_SYSERR;
-  }
   authorization =
     GNUNET_CONTAINER_multihashmap_get (handle->rest_handle->header_param_map,
                                        &cache_key);
@@ -1779,44 +1796,117 @@ check_authorization (struct RequestHandle *handle,
   // split header in "Basic" and [content]
   credentials = strtok (authorization, " ");
   if ((NULL == credentials) || (0 != strcmp ("Basic", credentials)))
-  {
-    handle->emsg = GNUNET_strdup (OIDC_ERROR_KEY_INVALID_CLIENT);
-    handle->response_code = MHD_HTTP_UNAUTHORIZED;
     return GNUNET_SYSERR;
-  }
   credentials = strtok (NULL, " ");
   if (NULL == credentials)
-  {
-    handle->emsg = GNUNET_strdup (OIDC_ERROR_KEY_INVALID_CLIENT);
-    handle->response_code = MHD_HTTP_UNAUTHORIZED;
     return GNUNET_SYSERR;
-  }
   GNUNET_STRINGS_base64_decode (credentials,
                                 strlen (credentials),
                                 (void **) &basic_authorization);
 
   if (NULL == basic_authorization)
-  {
-    handle->emsg = GNUNET_strdup (OIDC_ERROR_KEY_INVALID_CLIENT);
-    handle->response_code = MHD_HTTP_UNAUTHORIZED;
     return GNUNET_SYSERR;
-  }
-  client_id = strtok (basic_authorization, ":");
-  if (NULL == client_id)
+  client_id_tmp = strtok (basic_authorization, ":");
+  if (NULL == client_id_tmp)
   {
     GNUNET_free (basic_authorization);
-    handle->emsg = GNUNET_strdup (OIDC_ERROR_KEY_INVALID_CLIENT);
-    handle->response_code = MHD_HTTP_UNAUTHORIZED;
     return GNUNET_SYSERR;
   }
   pass = strtok (NULL, ":");
   if (NULL == pass)
   {
     GNUNET_free (basic_authorization);
-    handle->emsg = GNUNET_strdup (OIDC_ERROR_KEY_INVALID_CLIENT);
-    handle->response_code = MHD_HTTP_UNAUTHORIZED;
     return GNUNET_SYSERR;
   }
+  *client_id = strdup (client_id_tmp);
+  *client_secret = strdup (pass);
+  GNUNET_free (basic_authorization);
+  return GNUNET_OK;
+}
+
+
+static int
+parse_credentials_post_body (struct RequestHandle *handle,
+                             char **client_id,
+                             char **client_secret)
+{
+  struct GNUNET_HashCode cache_key;
+  char *client_id_tmp;
+  char *pass;
+
+  GNUNET_CRYPTO_hash ("client_id",
+                      strlen ("client_id"),
+                      &cache_key);
+  if (GNUNET_NO == GNUNET_CONTAINER_multihashmap_contains (handle->rest_handle
+                                                           ->url_param_map,
+                                                           &cache_key))
+    return GNUNET_SYSERR;
+  client_id_tmp = GNUNET_CONTAINER_multihashmap_get (
+    handle->rest_handle->url_param_map,
+    &cache_key);
+  if (NULL == client_id_tmp)
+    return GNUNET_SYSERR;
+  *client_id = strdup (client_id_tmp);
+  GNUNET_CRYPTO_hash ("client_secret",
+                      strlen ("client_secret"),
+                      &cache_key);
+  if (GNUNET_NO == GNUNET_CONTAINER_multihashmap_contains (handle->rest_handle
+                                                           ->url_param_map,
+                                                           &cache_key))
+    return GNUNET_SYSERR;
+  pass = GNUNET_CONTAINER_multihashmap_get (handle->rest_handle->url_param_map,
+                                            &cache_key);
+  if (NULL == pass)
+    return GNUNET_SYSERR;
+  *client_secret = strdup (pass);
+  return GNUNET_OK;
+}
+
+
+static int
+check_authorization (struct RequestHandle *handle,
+                     struct GNUNET_CRYPTO_EcdsaPublicKey *cid)
+{
+  char *expected_pass;
+  char *received_cid;
+  char *received_cpw;
+  char *pkce_cv;
+
+  if (GNUNET_OK == parse_credentials_basic_auth (handle,
+                                                 &received_cid,
+                                                 &received_cpw))
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                "Received client credentials in HTTP AuthZ header\n");
+  }
+  else if (GNUNET_OK == parse_credentials_post_body (handle,
+                                                     &received_cid,
+                                                     &received_cpw))
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                "Received client credentials in POST body\n");
+  }
+  else
+  {
+    /** Allow public clients with PKCE **/
+    pkce_cv = get_url_parameter_copy (handle, OIDC_CODE_VERIFIER_KEY);
+    if (NULL == pkce_cv)
+    {
+      handle->emsg = GNUNET_strdup (OIDC_ERROR_KEY_INVALID_CLIENT);
+      handle->response_code = MHD_HTTP_UNAUTHORIZED;
+      return GNUNET_SYSERR;
+    }
+    handle->public_client = GNUNET_YES;
+    GNUNET_free (pkce_cv);
+    received_cid = get_url_parameter_copy (handle, OIDC_CLIENT_ID_KEY);
+    GNUNET_STRINGS_string_to_data (received_cid,
+                                   strlen (received_cid),
+                                   cid,
+                                   sizeof(struct GNUNET_CRYPTO_EcdsaPublicKey));
+    GNUNET_free (received_cid);
+    return GNUNET_OK;
+
+  }
 
   // check client password
   if (GNUNET_OK == GNUNET_CONFIGURATION_get_value_string (cfg,
@@ -1824,9 +1914,8 @@ check_authorization (struct RequestHandle *handle,
                                                           "OIDC_CLIENT_SECRET",
                                                           &expected_pass))
   {
-    if (0 != strcmp (expected_pass, pass))
+    if (0 != strcmp (expected_pass, received_cpw))
     {
-      GNUNET_free (basic_authorization);
       GNUNET_free (expected_pass);
       handle->emsg = GNUNET_strdup (OIDC_ERROR_KEY_INVALID_CLIENT);
       handle->response_code = MHD_HTTP_UNAUTHORIZED;
@@ -1836,33 +1925,33 @@ check_authorization (struct RequestHandle *handle,
   }
   else
   {
-    GNUNET_free (basic_authorization);
     handle->emsg = GNUNET_strdup (OIDC_ERROR_KEY_SERVER_ERROR);
     handle->edesc = GNUNET_strdup ("gnunet configuration failed");
     handle->response_code = MHD_HTTP_INTERNAL_SERVER_ERROR;
     return GNUNET_SYSERR;
   }
-
   // check client_id
-  for (handle->ego_entry = handle->ego_head; NULL != handle->ego_entry;
+  for (handle->ego_entry = ego_head; NULL != handle->ego_entry;
        handle->ego_entry = handle->ego_entry->next)
   {
-    if (0 == strcmp (handle->ego_entry->keystring, client_id))
+    if (0 == strcmp (handle->ego_entry->keystring, received_cid))
       break;
   }
   if (NULL == handle->ego_entry)
   {
-    GNUNET_free (basic_authorization);
+    GNUNET_free (received_cpw);
+    GNUNET_free (received_cid);
     handle->emsg = GNUNET_strdup (OIDC_ERROR_KEY_INVALID_CLIENT);
     handle->response_code = MHD_HTTP_UNAUTHORIZED;
     return GNUNET_SYSERR;
   }
-  GNUNET_STRINGS_string_to_data (client_id,
-                                 strlen (client_id),
+  GNUNET_STRINGS_string_to_data (received_cid,
+                                 strlen (received_cid),
                                  cid,
                                  sizeof(struct GNUNET_CRYPTO_EcdsaPublicKey));
 
-  GNUNET_free (basic_authorization);
+  GNUNET_free (received_cpw);
+  GNUNET_free (received_cid);
   return GNUNET_OK;
 }
 
@@ -1874,7 +1963,7 @@ find_ego (struct RequestHandle *handle,
   struct EgoEntry *ego_entry;
   struct GNUNET_CRYPTO_EcdsaPublicKey pub_key;
 
-  for (ego_entry = handle->ego_head; NULL != ego_entry;
+  for (ego_entry = ego_head; NULL != ego_entry;
        ego_entry = ego_entry->next)
   {
     GNUNET_IDENTITY_ego_get_public_key (ego_entry->ego, &pub_key);
@@ -1885,26 +1974,6 @@ find_ego (struct RequestHandle *handle,
 }
 
 
-static void
-persist_access_token (const struct RequestHandle *handle,
-                      const char *access_token,
-                      const struct GNUNET_RECLAIM_Ticket *ticket)
-{
-  struct GNUNET_HashCode hc;
-  struct GNUNET_RECLAIM_Ticket *ticketbuf;
-
-  GNUNET_CRYPTO_hash (access_token, strlen (access_token), &hc);
-  ticketbuf = GNUNET_new (struct GNUNET_RECLAIM_Ticket);
-  *ticketbuf = *ticket;
-  GNUNET_assert (GNUNET_SYSERR !=
-                 GNUNET_CONTAINER_multihashmap_put (
-                   OIDC_access_token_map,
-                   &hc,
-                   ticketbuf,
-                   GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
-}
-
-
 /**
  * Responds to token url-encoded POST request
  *
@@ -1921,10 +1990,9 @@ token_endpoint (struct GNUNET_REST_RequestHandle *con_handle,
   const struct EgoEntry *ego_entry;
   struct GNUNET_TIME_Relative expiration_time;
   struct GNUNET_RECLAIM_AttributeList *cl = NULL;
-  struct GNUNET_RECLAIM_AttestationList *al = NULL;
+  struct GNUNET_RECLAIM_PresentationList *pl = NULL;
   struct GNUNET_RECLAIM_Ticket ticket;
   struct GNUNET_CRYPTO_EcdsaPublicKey cid;
-  const struct GNUNET_CRYPTO_EcdsaPrivateKey *privkey;
   struct GNUNET_HashCode cache_key;
   struct MHD_Response *resp;
   char *grant_type;
@@ -1996,7 +2064,6 @@ token_endpoint (struct GNUNET_REST_RequestHandle *con_handle,
     GNUNET_SCHEDULER_add_now (&do_error, handle);
     return;
   }
-  privkey = GNUNET_IDENTITY_ego_get_private_key (ego_entry->ego);
 
   // REQUIRED code verifier
   code_verifier = get_url_parameter_copy (handle, OIDC_CODE_VERIFIER_KEY);
@@ -2008,8 +2075,8 @@ token_endpoint (struct GNUNET_REST_RequestHandle *con_handle,
   }
 
   // decode code
-  if (GNUNET_OK != OIDC_parse_authz_code (privkey, code, code_verifier, &ticket,
-                                          &cl, &al, &nonce))
+  if (GNUNET_OK != OIDC_parse_authz_code (&cid, code, code_verifier, &ticket,
+                                          &cl, &pl, &nonce))
   {
     handle->emsg = GNUNET_strdup (OIDC_ERROR_KEY_INVALID_REQUEST);
     handle->edesc = GNUNET_strdup ("invalid code");
@@ -2046,31 +2113,30 @@ token_endpoint (struct GNUNET_REST_RequestHandle *con_handle,
     GNUNET_SCHEDULER_add_now (&do_error, handle);
     return;
   }
-  id_token = OIDC_id_token_new (&ticket.audience,
-                                &ticket.identity,
-                                cl,
-                                al,
-                                &expiration_time,
-                                (NULL != nonce) ? nonce : NULL,
-                                jwt_secret);
-  access_token = OIDC_access_token_new ();
+  id_token = OIDC_generate_id_token (&ticket.audience,
+                                     &ticket.identity,
+                                     cl,
+                                     pl,
+                                     &expiration_time,
+                                     (NULL != nonce) ? nonce : NULL,
+                                     jwt_secret);
+  access_token = OIDC_access_token_new (&ticket);
   OIDC_build_token_response (access_token,
                              id_token,
                              &expiration_time,
                              &json_response);
 
-  persist_access_token (handle, access_token, &ticket);
   resp = GNUNET_REST_create_response (json_response);
   MHD_add_response_header (resp, "Cache-Control", "no-store");
   MHD_add_response_header (resp, "Pragma", "no-cache");
   MHD_add_response_header (resp, "Content-Type", "application/json");
   handle->proc (handle->proc_cls, resp, MHD_HTTP_OK);
   GNUNET_RECLAIM_attribute_list_destroy (cl);
-  GNUNET_RECLAIM_attestation_list_destroy (al);
+  GNUNET_RECLAIM_presentation_list_destroy (pl);
   GNUNET_free (access_token);
   GNUNET_free (json_response);
   GNUNET_free (id_token);
-  GNUNET_SCHEDULER_add_now (&cleanup_handle_delayed, handle);
+  cleanup_handle (handle);
 }
 
 
@@ -2081,86 +2147,60 @@ static void
 consume_ticket (void *cls,
                 const struct GNUNET_CRYPTO_EcdsaPublicKey *identity,
                 const struct GNUNET_RECLAIM_Attribute *attr,
-                const struct GNUNET_RECLAIM_Attestation *attest)
+                const struct GNUNET_RECLAIM_Presentation *pres)
 {
   struct RequestHandle *handle = cls;
+  struct GNUNET_RECLAIM_AttributeListEntry *ale;
+  struct GNUNET_RECLAIM_PresentationListEntry *atle;
+  struct MHD_Response *resp;
+  char *result_str;
   handle->idp_op = NULL;
 
   if (NULL == identity)
   {
-    GNUNET_SCHEDULER_add_now (&return_userinfo_response, handle);
+    result_str = OIDC_generate_userinfo (&handle->ticket.identity,
+                                         handle->attr_userinfo_list,
+                                         handle->presentations);
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Userinfo: %s\n", result_str);
+    resp = GNUNET_REST_create_response (result_str);
+    handle->proc (handle->proc_cls, resp, MHD_HTTP_OK);
+    GNUNET_free (result_str);
+    cleanup_handle (handle);
     return;
   }
-  if (GNUNET_YES == GNUNET_RECLAIM_id_is_zero (&attr->attestation))
-  {
-    char *tmp_value;
-    json_t *value;
-    tmp_value = GNUNET_RECLAIM_attribute_value_to_string (attr->type,
-                                                          attr->data,
-                                                          attr->data_size);
-    value = json_string (tmp_value);
-    json_object_set_new (handle->oidc->response, attr->name, value);
-    GNUNET_free (tmp_value);
+  ale = GNUNET_new (struct GNUNET_RECLAIM_AttributeListEntry);
+  ale->attribute = GNUNET_RECLAIM_attribute_new (attr->name,
+                                                 &attr->credential,
+                                                 attr->type,
+                                                 attr->data,
+                                                 attr->data_size);
+  ale->attribute->id = attr->id;
+  ale->attribute->flag = attr->flag;
+  ale->attribute->credential = attr->credential;
+  GNUNET_CONTAINER_DLL_insert (handle->attr_userinfo_list->list_head,
+                               handle->attr_userinfo_list->list_tail,
+                               ale);
+  if (NULL == pres)
     return;
+  for (atle = handle->presentations->list_head;
+       NULL != atle; atle = atle->next)
+  {
+    if (GNUNET_NO == GNUNET_RECLAIM_id_is_equal (&atle->presentation->credential_id,
+                                                 &pres->credential_id))
+      continue;
+    break; /** already in list **/
+  }
+  if (NULL == atle)
+  {
+    /** Credential matches for attribute, add **/
+    atle = GNUNET_new (struct GNUNET_RECLAIM_PresentationListEntry);
+    atle->presentation = GNUNET_RECLAIM_presentation_new (pres->type,
+                                                         pres->data,
+                                                         pres->data_size);
+    GNUNET_CONTAINER_DLL_insert (handle->presentations->list_head,
+                                 handle->presentations->list_tail,
+                                 atle);
   }
-  json_t *claim_sources;
-  json_t *claim_sources_jwt;
-  json_t *claim_names;
-  char *attest_val_str;
-  claim_sources = json_object_get (handle->oidc->response,"_claim_sources");
-  claim_names = json_object_get (handle->oidc->response,"_claim_names");
-  attest_val_str =
-    GNUNET_RECLAIM_attestation_value_to_string (attest->type,
-                                                attest->data,
-                                                attest->data_size);
-  if ((NULL == claim_sources) && (NULL == claim_names) )
-  {
-    claim_sources = json_object ();
-    claim_names = json_object ();
-  }
-  char *source_name;
-  int i = 0;
-  GNUNET_asprintf (&source_name, "src%d", i);
-  while (NULL != (claim_sources_jwt = json_object_get (claim_sources,
-                                                       source_name)))
-  {
-    if (0 == strcmp (json_string_value (json_object_get (claim_sources_jwt,
-                                                         "JWT")),
-                     attest_val_str))
-    {
-      // Adapt only the claim names
-      json_object_set_new (claim_names, attr->data,
-                           json_string (source_name));
-      json_object_set (handle->oidc->response,
-                       "_claim_names", claim_names);
-      break;
-    }
-    i++;
-    GNUNET_free (source_name);
-    GNUNET_asprintf (&source_name, "src%d", i);
-  }
-
-  // Create new one
-  if (NULL == claim_sources_jwt)
-  {
-    claim_sources_jwt = json_object ();
-    // Set the JWT for names
-    json_object_set_new (claim_names, attr->data,
-                         json_string (source_name));
-    // Set the JWT for the inner source
-    json_object_set_new (claim_sources_jwt, "JWT",
-                         json_string (attest_val_str));
-    // Set the JWT for the source
-    json_object_set_new (claim_sources, source_name, claim_sources_jwt);
-    // Set as claims
-    json_object_set (handle->oidc->response, "_claim_names", claim_names);
-    json_object_set (handle->oidc->response, "_claim_sources",claim_sources);
-  }
-
-  json_decref (claim_sources);
-  json_decref (claim_names);
-  json_decref (claim_sources_jwt);
-  GNUNET_free (attest_val_str);
 }
 
 
@@ -2178,15 +2218,16 @@ userinfo_endpoint (struct GNUNET_REST_RequestHandle *con_handle,
 {
   // TODO expiration time
   struct RequestHandle *handle = cls;
+  struct GNUNET_RECLAIM_Ticket *ticket;
   char delimiter[] = " ";
   struct GNUNET_HashCode cache_key;
   char *authorization;
   char *authorization_type;
   char *authorization_access_token;
-  struct GNUNET_RECLAIM_Ticket *ticket;
-  const struct EgoEntry *ego_entry;
+  const struct EgoEntry *aud_ego;
   const struct GNUNET_CRYPTO_EcdsaPrivateKey *privkey;
 
+  GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Getting userinfo\n");
   GNUNET_CRYPTO_hash (OIDC_AUTHORIZATION_HEADER_KEY,
                       strlen (OIDC_AUTHORIZATION_HEADER_KEY),
                       &cache_key);
@@ -2228,25 +2269,22 @@ userinfo_endpoint (struct GNUNET_REST_RequestHandle *con_handle,
     return;
   }
 
-  GNUNET_CRYPTO_hash (authorization_access_token,
-                      strlen (authorization_access_token),
-                      &cache_key);
-  if (GNUNET_NO ==
-      GNUNET_CONTAINER_multihashmap_contains (OIDC_access_token_map,
-                                              &cache_key))
+  if (GNUNET_OK != OIDC_access_token_parse (authorization_access_token,
+                                            &ticket))
   {
     handle->emsg = GNUNET_strdup (OIDC_ERROR_KEY_INVALID_TOKEN);
-    handle->edesc = GNUNET_strdup ("The access token expired");
+    handle->edesc = GNUNET_strdup ("The access token is invalid");
     handle->response_code = MHD_HTTP_UNAUTHORIZED;
     GNUNET_SCHEDULER_add_now (&do_userinfo_error, handle);
     GNUNET_free (authorization);
     return;
+
   }
-  ticket =
-    GNUNET_CONTAINER_multihashmap_get (OIDC_access_token_map, &cache_key);
   GNUNET_assert (NULL != ticket);
-  ego_entry = find_ego (handle, &ticket->audience);
-  if (NULL == ego_entry)
+  handle->ticket = *ticket;
+  GNUNET_free (ticket);
+  aud_ego = find_ego (handle, &handle->ticket.audience);
+  if (NULL == aud_ego)
   {
     handle->emsg = GNUNET_strdup (OIDC_ERROR_KEY_INVALID_TOKEN);
     handle->edesc = GNUNET_strdup ("The access token expired");
@@ -2255,52 +2293,22 @@ userinfo_endpoint (struct GNUNET_REST_RequestHandle *con_handle,
     GNUNET_free (authorization);
     return;
   }
+  GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Consuming ticket\n");
+  privkey = GNUNET_IDENTITY_ego_get_private_key (aud_ego->ego);
+  handle->attr_userinfo_list =
+    GNUNET_new (struct GNUNET_RECLAIM_AttributeList);
+  handle->presentations =
+    GNUNET_new (struct GNUNET_RECLAIM_PresentationList);
 
-  handle->idp = GNUNET_RECLAIM_connect (cfg);
-  handle->oidc->response = json_object ();
-  json_object_set_new (handle->oidc->response,
-                       "sub",
-                       json_string (ego_entry->keystring));
-  privkey = GNUNET_IDENTITY_ego_get_private_key (ego_entry->ego);
-  handle->idp_op = GNUNET_RECLAIM_ticket_consume (handle->idp,
+  handle->idp_op = GNUNET_RECLAIM_ticket_consume (idp,
                                                   privkey,
-                                                  ticket,
-                                                  consume_ticket,
+                                                  &handle->ticket,
+                                                  &consume_ticket,
                                                   handle);
   GNUNET_free (authorization);
 }
 
 
-/**
- * Handle rest request
- *
- * @param handle the request handle
- */
-static void
-init_cont (struct RequestHandle *handle)
-{
-  struct GNUNET_REST_RequestHandlerError err;
-  static const struct GNUNET_REST_RequestHandler handlers[] =
-  { { MHD_HTTP_METHOD_GET, GNUNET_REST_API_NS_AUTHORIZE, &authorize_endpoint },
-    { MHD_HTTP_METHOD_POST,
-      GNUNET_REST_API_NS_AUTHORIZE,
-      &authorize_endpoint },   // url-encoded
-    { MHD_HTTP_METHOD_POST, GNUNET_REST_API_NS_LOGIN, &login_cont },
-    { MHD_HTTP_METHOD_POST, GNUNET_REST_API_NS_TOKEN, &token_endpoint },
-    { MHD_HTTP_METHOD_GET, GNUNET_REST_API_NS_USERINFO, &userinfo_endpoint },
-    { MHD_HTTP_METHOD_POST, GNUNET_REST_API_NS_USERINFO, &userinfo_endpoint },
-    { MHD_HTTP_METHOD_OPTIONS, GNUNET_REST_API_NS_OIDC, &options_cont },
-    GNUNET_REST_HANDLER_END };
-
-  if (GNUNET_NO ==
-      GNUNET_REST_handle_request (handle->rest_handle, handlers, &err, handle))
-  {
-    handle->response_code = err.error_code;
-    GNUNET_SCHEDULER_add_now (&do_error, handle);
-  }
-}
-
-
 /**
  * If listing is enabled, prints information about the egos.
  *
@@ -2340,18 +2348,16 @@ list_ego (void *cls,
           void **ctx,
           const char *identifier)
 {
-  struct RequestHandle *handle = cls;
   struct EgoEntry *ego_entry;
   struct GNUNET_CRYPTO_EcdsaPublicKey pk;
 
-  if ((NULL == ego) && (ID_REST_STATE_INIT == handle->state))
+  if ((NULL == ego) && (ID_REST_STATE_INIT == state))
   {
-    handle->state = ID_REST_STATE_POST_INIT;
-    init_cont (handle);
+    state = ID_REST_STATE_POST_INIT;
     return;
   }
   GNUNET_assert (NULL != ego);
-  if (ID_REST_STATE_INIT == handle->state)
+  if (ID_REST_STATE_INIT == state)
 
   {
     ego_entry = GNUNET_new (struct EgoEntry);
@@ -2359,15 +2365,15 @@ list_ego (void *cls,
     ego_entry->keystring = GNUNET_CRYPTO_ecdsa_public_key_to_string (&pk);
     ego_entry->ego = ego;
     ego_entry->identifier = GNUNET_strdup (identifier);
-    GNUNET_CONTAINER_DLL_insert_tail (handle->ego_head,
-                                      handle->ego_tail,
+    GNUNET_CONTAINER_DLL_insert_tail (ego_head,
+                                      ego_tail,
                                       ego_entry);
     return;
   }
   /* Ego renamed or added */
   if (identifier != NULL)
   {
-    for (ego_entry = handle->ego_head; NULL != ego_entry;
+    for (ego_entry = ego_head; NULL != ego_entry;
          ego_entry = ego_entry->next)
     {
       if (ego_entry->ego == ego)
@@ -2386,15 +2392,15 @@ list_ego (void *cls,
       ego_entry->keystring = GNUNET_CRYPTO_ecdsa_public_key_to_string (&pk);
       ego_entry->ego = ego;
       ego_entry->identifier = GNUNET_strdup (identifier);
-      GNUNET_CONTAINER_DLL_insert_tail (handle->ego_head,
-                                        handle->ego_tail,
+      GNUNET_CONTAINER_DLL_insert_tail (ego_head,
+                                        ego_tail,
                                         ego_entry);
     }
   }
   else
   {
     /* Delete */
-    for (ego_entry = handle->ego_head; NULL != ego_entry;
+    for (ego_entry = ego_head; NULL != ego_entry;
          ego_entry = ego_entry->next)
     {
       if (ego_entry->ego == ego)
@@ -2403,8 +2409,8 @@ list_ego (void *cls,
     if (NULL == ego_entry)
       return; /* Not found */
 
-    GNUNET_CONTAINER_DLL_remove (handle->ego_head,
-                                 handle->ego_tail,
+    GNUNET_CONTAINER_DLL_remove (ego_head,
+                                 ego_tail,
                                  ego_entry);
     GNUNET_free (ego_entry->identifier);
     GNUNET_free (ego_entry->keystring);
@@ -2415,36 +2421,162 @@ list_ego (void *cls,
 
 
 static void
+oidc_config_endpoint (struct GNUNET_REST_RequestHandle *con_handle,
+                      const char *url,
+                      void *cls)
+{
+  json_t *oidc_config;
+  json_t *auth_methods;
+  json_t *sig_algs;
+  json_t *scopes;
+  json_t *response_types;
+  json_t *sub_types;
+  json_t *claim_types;
+  char *oidc_config_str;
+  struct MHD_Response *resp;
+  struct RequestHandle *handle = cls;
+
+  oidc_config = json_object ();
+  // FIXME get from config?
+  json_object_set_new (oidc_config,
+                       "issuer", json_string ("http://localhost:7776"));
+  json_object_set_new (oidc_config,
+                       "authorization_endpoint",
+                       json_string ("https://api.reclaim/openid/authorize"));
+  json_object_set_new (oidc_config,
+                       "token_endpoint",
+                       json_string ("http://localhost:7776/openid/token"));
+  auth_methods = json_array ();
+  json_array_append_new (auth_methods,
+                         json_string ("client_secret_basic"));
+  json_array_append_new (auth_methods,
+                         json_string ("client_secret_post"));
+  json_object_set_new (oidc_config,
+                       "token_endpoint_auth_methods_supported",
+                       auth_methods);
+  sig_algs = json_array ();
+  json_array_append_new (sig_algs,
+                         json_string ("HS512"));
+  json_object_set_new (oidc_config,
+                       "id_token_signing_alg_values_supported",
+                       sig_algs);
+  json_object_set_new (oidc_config,
+                       "userinfo_endpoint",
+                       json_string ("http://localhost:7776/openid/userinfo"));
+  scopes = json_array ();
+  json_array_append_new (scopes,
+                         json_string ("openid"));
+  json_array_append_new (scopes,
+                         json_string ("profile"));
+  json_array_append_new (scopes,
+                         json_string ("email"));
+  json_array_append_new (scopes,
+                         json_string ("address"));
+  json_array_append_new (scopes,
+                         json_string ("phone"));
+  json_object_set_new (oidc_config,
+                       "scopes_supported",
+                       scopes);
+  response_types = json_array ();
+  json_array_append_new (response_types,
+                         json_string ("code"));
+  json_object_set_new (oidc_config,
+                       "response_types_supported",
+                       response_types);
+  sub_types = json_array ();
+  json_array_append_new (sub_types,
+                         json_string ("public"));  /* no pairwise suppport */
+  json_object_set_new (oidc_config,
+                       "subject_types_supported",
+                       sub_types);
+  claim_types = json_array ();
+  json_array_append_new (claim_types,
+                         json_string ("normal"));
+  json_array_append_new (claim_types,
+                         json_string ("aggregated"));
+  json_object_set_new (oidc_config,
+                       "claim_types_supported",
+                       claim_types);
+  json_object_set_new (oidc_config,
+                       "claims_parameter_supported",
+                       json_boolean (1));
+  oidc_config_str = json_dumps (oidc_config, JSON_INDENT (1));
+  resp = GNUNET_REST_create_response (oidc_config_str);
+  handle->proc (handle->proc_cls, resp, MHD_HTTP_OK);
+  GNUNET_free (oidc_config_str);
+  cleanup_handle (handle);
+}
+
+
+/**
+ * Respond to OPTIONS request
+ *
+ * @param con_handle the connection handle
+ * @param url the url
+ * @param cls the RequestHandle
+ */
+static void
+oidc_config_cors (struct GNUNET_REST_RequestHandle *con_handle,
+                  const char *url,
+                  void *cls)
+{
+  struct MHD_Response *resp;
+  struct RequestHandle *handle = cls;
+
+  // For now, independent of path return all options
+  resp = GNUNET_REST_create_response (NULL);
+  MHD_add_response_header (resp, "Access-Control-Allow-Methods", allow_methods);
+  MHD_add_response_header (resp, "Access-Control-Allow-Origin", "*");
+  handle->proc (handle->proc_cls, resp, MHD_HTTP_OK);
+  cleanup_handle (handle);
+  return;
+}
+
+
+static enum GNUNET_GenericReturnValue
 rest_identity_process_request (struct GNUNET_REST_RequestHandle *rest_handle,
                                GNUNET_REST_ResultProcessor proc,
                                void *proc_cls)
 {
   struct RequestHandle *handle = GNUNET_new (struct RequestHandle);
+  struct GNUNET_REST_RequestHandlerError err;
+  static const struct GNUNET_REST_RequestHandler handlers[] =
+  { { MHD_HTTP_METHOD_GET, GNUNET_REST_API_NS_AUTHORIZE, &authorize_endpoint },
+    { MHD_HTTP_METHOD_POST,
+      GNUNET_REST_API_NS_AUTHORIZE, &authorize_endpoint },   // url-encoded
+    { MHD_HTTP_METHOD_POST, GNUNET_REST_API_NS_LOGIN, &login_cont },
+    { MHD_HTTP_METHOD_POST, GNUNET_REST_API_NS_TOKEN, &token_endpoint },
+    { MHD_HTTP_METHOD_GET, GNUNET_REST_API_NS_USERINFO, &userinfo_endpoint },
+    { MHD_HTTP_METHOD_POST, GNUNET_REST_API_NS_USERINFO, &userinfo_endpoint },
+    { MHD_HTTP_METHOD_GET, GNUNET_REST_API_NS_OIDC_CONFIG,
+      &oidc_config_endpoint },
+    { MHD_HTTP_METHOD_OPTIONS, GNUNET_REST_API_NS_OIDC_CONFIG,
+      &oidc_config_cors },
+    { MHD_HTTP_METHOD_OPTIONS, GNUNET_REST_API_NS_OIDC, &options_cont },
+    GNUNET_REST_HANDLER_END };
 
   handle->oidc = GNUNET_new (struct OIDC_Variables);
   if (NULL == OIDC_cookie_jar_map)
     OIDC_cookie_jar_map = GNUNET_CONTAINER_multihashmap_create (10,
                                                                 GNUNET_NO);
-  if (NULL == OIDC_access_token_map)
-    OIDC_access_token_map =
-      GNUNET_CONTAINER_multihashmap_create (10, GNUNET_NO);
   handle->response_code = 0;
   handle->timeout = GNUNET_TIME_UNIT_FOREVER_REL;
   handle->proc_cls = proc_cls;
   handle->proc = proc;
-  handle->state = ID_REST_STATE_INIT;
   handle->rest_handle = rest_handle;
-
   handle->url = GNUNET_strdup (rest_handle->url);
-  if (handle->url[strlen (handle->url) - 1] == '/')
-    handle->url[strlen (handle->url) - 1] = '\0';
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Connecting...\n");
-  handle->identity_handle = GNUNET_IDENTITY_connect (cfg, &list_ego, handle);
-  handle->gns_handle = GNUNET_GNS_connect (cfg);
-  handle->namestore_handle = GNUNET_NAMESTORE_connect (cfg);
   handle->timeout_task =
     GNUNET_SCHEDULER_add_delayed (handle->timeout, &do_timeout, handle);
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Connected\n");
+  GNUNET_CONTAINER_DLL_insert (requests_head,
+                               requests_tail,
+                               handle);
+  if (handle->url[strlen (handle->url) - 1] == '/')
+    handle->url[strlen (handle->url) - 1] = '\0';
+  if (GNUNET_NO ==
+      GNUNET_REST_handle_request (handle->rest_handle, handlers, &err, handle))
+    return GNUNET_NO;
+
+  return GNUNET_YES;
 }
 
 
@@ -2469,6 +2601,11 @@ libgnunet_plugin_rest_openid_connect_init (void *cls)
   api->cls = &plugin;
   api->name = GNUNET_REST_API_NS_OIDC;
   api->process_request = &rest_identity_process_request;
+  identity_handle = GNUNET_IDENTITY_connect (cfg, &list_ego, NULL);
+  gns_handle = GNUNET_GNS_connect (cfg);
+  idp = GNUNET_RECLAIM_connect (cfg);
+
+  state = ID_REST_STATE_INIT;
   GNUNET_asprintf (&allow_methods,
                    "%s, %s, %s, %s, %s",
                    MHD_HTTP_METHOD_GET,
@@ -2483,6 +2620,14 @@ libgnunet_plugin_rest_openid_connect_init (void *cls)
 }
 
 
+static int
+cleanup_hashmap (void *cls, const struct GNUNET_HashCode *key, void *value)
+{
+  GNUNET_free (value);
+  return GNUNET_YES;
+}
+
+
 /**
    * Exit point from the plugin.
    *
@@ -2494,29 +2639,34 @@ libgnunet_plugin_rest_openid_connect_done (void *cls)
 {
   struct GNUNET_REST_Plugin *api = cls;
   struct Plugin *plugin = api->cls;
+  struct EgoEntry *ego_entry;
 
   plugin->cfg = NULL;
-
-  struct GNUNET_CONTAINER_MultiHashMapIterator *hashmap_it;
-  void *value = NULL;
-  hashmap_it =
-    GNUNET_CONTAINER_multihashmap_iterator_create (OIDC_cookie_jar_map);
-  while (GNUNET_YES ==
-         GNUNET_CONTAINER_multihashmap_iterator_next (hashmap_it, NULL,
-                                                      value))
-    GNUNET_free (value);
-  GNUNET_CONTAINER_multihashmap_iterator_destroy (hashmap_it);
-  GNUNET_CONTAINER_multihashmap_destroy (OIDC_cookie_jar_map);
-
-  hashmap_it =
-    GNUNET_CONTAINER_multihashmap_iterator_create (OIDC_access_token_map);
-  while (GNUNET_YES ==
-         GNUNET_CONTAINER_multihashmap_iterator_next (hashmap_it, NULL,
-                                                      value))
-    GNUNET_free (value);
-  GNUNET_CONTAINER_multihashmap_destroy (OIDC_access_token_map);
-  GNUNET_CONTAINER_multihashmap_iterator_destroy (hashmap_it);
+  while (NULL != requests_head)
+    cleanup_handle (requests_head);
+  if (NULL != OIDC_cookie_jar_map)
+  {
+    GNUNET_CONTAINER_multihashmap_iterate (OIDC_cookie_jar_map,
+                                           &cleanup_hashmap,
+                                           NULL);
+    GNUNET_CONTAINER_multihashmap_destroy (OIDC_cookie_jar_map);
+  }
   GNUNET_free (allow_methods);
+  if (NULL != gns_handle)
+    GNUNET_GNS_disconnect (gns_handle);
+  if (NULL != identity_handle)
+    GNUNET_IDENTITY_disconnect (identity_handle);
+  if (NULL != idp)
+    GNUNET_RECLAIM_disconnect (idp);
+  while (NULL != (ego_entry = ego_head))
+  {
+    GNUNET_CONTAINER_DLL_remove (ego_head,
+                                 ego_tail,
+                                 ego_entry);
+    GNUNET_free (ego_entry->identifier);
+    GNUNET_free (ego_entry->keystring);
+    GNUNET_free (ego_entry);
+  }
   GNUNET_free (api);
   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
               "OpenID Connect REST plugin is finished\n");
diff --git a/src/reclaim/plugin_rest_reclaim.c b/src/reclaim/plugin_rest_reclaim.c
index 654df175ebb09b1e758e25923eb7ca66d141ea55..ff11d2a562bde47df93ed36de2b4e6baafe7feaf 100644
--- a/src/reclaim/plugin_rest_reclaim.c
+++ b/src/reclaim/plugin_rest_reclaim.c
@@ -48,9 +48,9 @@
 #define GNUNET_REST_API_NS_RECLAIM_ATTRIBUTES "/reclaim/attributes"
 
 /**
- * Attestation namespace
+ * Credential namespace
  */
-#define GNUNET_REST_API_NS_RECLAIM_ATTESTATION "/reclaim/attestation"
+#define GNUNET_REST_API_NS_RECLAIM_CREDENTIAL "/reclaim/credential"
 
 /**
  * Ticket namespace
@@ -87,6 +87,31 @@ const struct GNUNET_CONFIGURATION_Handle *cfg;
  */
 static char *allow_methods;
 
+/**
+ * Ego list
+ */
+static struct EgoEntry *ego_head;
+
+/**
+ * Ego list
+ */
+static struct EgoEntry *ego_tail;
+
+/**
+ * The processing state
+ */
+static int state;
+
+/**
+ * Handle to Identity service.
+ */
+static struct GNUNET_IDENTITY_Handle *identity_handle;
+
+/**
+ * Identity Provider
+ */
+static struct GNUNET_RECLAIM_Handle *idp;
+
 /**
  * @brief struct returned by the initialization function of the plugin
  */
@@ -130,14 +155,14 @@ struct EgoEntry
 struct RequestHandle
 {
   /**
-   * Ego list
+   * DLL
    */
-  struct EgoEntry *ego_head;
+  struct RequestHandle *next;
 
   /**
-   * Ego list
+   * DLL
    */
-  struct EgoEntry *ego_tail;
+  struct RequestHandle *prev;
 
   /**
    * Selected ego
@@ -149,16 +174,6 @@ struct RequestHandle
    */
   struct GNUNET_CRYPTO_EcdsaPrivateKey priv_key;
 
-  /**
-   * The processing state
-   */
-  int state;
-
-  /**
-   * Handle to Identity service.
-   */
-  struct GNUNET_IDENTITY_Handle *identity_handle;
-
   /**
    * Rest connection
    */
@@ -174,11 +189,6 @@ struct RequestHandle
    */
   struct GNUNET_IDENTITY_Operation *op;
 
-  /**
-   * Identity Provider
-   */
-  struct GNUNET_RECLAIM_Handle *idp;
-
   /**
    * Idp Operation
    */
@@ -192,8 +202,7 @@ struct RequestHandle
   /**
    * Attribute iterator
    */
-  struct GNUNET_RECLAIM_AttestationIterator *attest_it;
-
+  struct GNUNET_RECLAIM_CredentialIterator *cred_it;
 
   /**
    * Ticket iterator
@@ -246,56 +255,50 @@ struct RequestHandle
   json_t *resp_object;
 };
 
+/**
+ * DLL
+ */
+static struct RequestHandle *requests_head;
+
+/**
+ * DLL
+ */
+static struct RequestHandle *requests_tail;
+
+
 /**
  * Cleanup lookup handle
  * @param handle Handle to clean up
  */
 static void
-cleanup_handle (struct RequestHandle *handle)
+cleanup_handle (void *cls)
 {
-  struct EgoEntry *ego_entry;
-  struct EgoEntry *ego_tmp;
+  struct RequestHandle *handle = cls;
 
   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Cleaning up\n");
   if (NULL != handle->resp_object)
     json_decref (handle->resp_object);
   if (NULL != handle->timeout_task)
     GNUNET_SCHEDULER_cancel (handle->timeout_task);
-  if (NULL != handle->identity_handle)
-    GNUNET_IDENTITY_disconnect (handle->identity_handle);
   if (NULL != handle->attr_it)
     GNUNET_RECLAIM_get_attributes_stop (handle->attr_it);
-  if (NULL != handle->attest_it)
-    GNUNET_RECLAIM_get_attestations_stop (handle->attest_it);
+  if (NULL != handle->cred_it)
+    GNUNET_RECLAIM_get_credentials_stop (handle->cred_it);
   if (NULL != handle->ticket_it)
     GNUNET_RECLAIM_ticket_iteration_stop (handle->ticket_it);
-  if (NULL != handle->idp)
-    GNUNET_RECLAIM_disconnect (handle->idp);
   if (NULL != handle->url)
     GNUNET_free (handle->url);
   if (NULL != handle->emsg)
     GNUNET_free (handle->emsg);
   if (NULL != handle->attr_list)
     GNUNET_RECLAIM_attribute_list_destroy (handle->attr_list);
-  for (ego_entry = handle->ego_head; NULL != ego_entry;)
-  {
-    ego_tmp = ego_entry;
-    ego_entry = ego_entry->next;
-    GNUNET_free (ego_tmp->identifier);
-    GNUNET_free (ego_tmp->keystring);
-    GNUNET_free (ego_tmp);
-  }
+  GNUNET_CONTAINER_DLL_remove (requests_head,
+                               requests_tail,
+                               handle);
   GNUNET_free (handle);
 }
 
 
-static void
-cleanup_handle_delayed (void *cls)
-{
-  cleanup_handle (cls);
-}
-
-
 /**
  * Task run on error, sends error message.  Cleans up everything.
  *
@@ -316,7 +319,7 @@ do_error (void *cls)
   resp = GNUNET_REST_create_response (json_error);
   MHD_add_response_header (resp, "Content-Type", "application/json");
   handle->proc (handle->proc_cls, resp, handle->response_code);
-  GNUNET_SCHEDULER_add_now (&cleanup_handle_delayed, handle);
+  cleanup_handle (handle);
   GNUNET_free (json_error);
 }
 
@@ -339,9 +342,7 @@ do_timeout (void *cls)
 static void
 collect_error_cb (void *cls)
 {
-  struct RequestHandle *handle = cls;
-
-  do_error (handle);
+  GNUNET_SCHEDULER_add_now (&do_error, cls);
 }
 
 
@@ -351,15 +352,17 @@ finished_cont (void *cls, int32_t success, const char *emsg)
   struct RequestHandle *handle = cls;
   struct MHD_Response *resp;
 
+  handle->idp_op = NULL;
   resp = GNUNET_REST_create_response (emsg);
   MHD_add_response_header (resp, "Content-Type", "application/json");
+  MHD_add_response_header (resp, "Access-Control-Allow-Methods", allow_methods);
   if (GNUNET_OK != success)
   {
     GNUNET_SCHEDULER_add_now (&do_error, handle);
     return;
   }
   handle->proc (handle->proc_cls, resp, MHD_HTTP_OK);
-  GNUNET_SCHEDULER_add_now (&cleanup_handle_delayed, handle);
+  GNUNET_SCHEDULER_add_now (&cleanup_handle, handle);
 }
 
 
@@ -370,13 +373,14 @@ delete_finished_cb (void *cls, int32_t success, const char *emsg)
   struct MHD_Response *resp;
 
   resp = GNUNET_REST_create_response (emsg);
+  MHD_add_response_header (resp, "Access-Control-Allow-Methods", allow_methods);
   if (GNUNET_OK != success)
   {
     GNUNET_SCHEDULER_add_now (&do_error, handle);
     return;
   }
   handle->proc (handle->proc_cls, resp, MHD_HTTP_OK);
-  GNUNET_SCHEDULER_add_now (&cleanup_handle_delayed, handle);
+  GNUNET_SCHEDULER_add_now (&cleanup_handle, handle);
 }
 
 
@@ -395,6 +399,7 @@ return_response (void *cls)
   result_str = json_dumps (handle->resp_object, 0);
   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Result %s\n", result_str);
   resp = GNUNET_REST_create_response (result_str);
+  MHD_add_response_header (resp, "Access-Control-Allow-Methods", allow_methods);
   handle->proc (handle->proc_cls, resp, MHD_HTTP_OK);
   GNUNET_free (result_str);
   cleanup_handle (handle);
@@ -408,7 +413,7 @@ collect_finished_cb (void *cls)
 
   // Done
   handle->attr_it = NULL;
-  handle->attest_it = NULL;
+  handle->cred_it = NULL;
   handle->ticket_it = NULL;
   GNUNET_SCHEDULER_add_now (&return_response, handle);
 }
@@ -455,7 +460,7 @@ ticket_collect (void *cls, const struct GNUNET_RECLAIM_Ticket *ticket)
 
 
 static void
-add_attestation_cont (struct GNUNET_REST_RequestHandle *con_handle,
+add_credential_cont (struct GNUNET_REST_RequestHandle *con_handle,
                       const char *url,
                       void *cls)
 {
@@ -463,19 +468,19 @@ add_attestation_cont (struct GNUNET_REST_RequestHandle *con_handle,
   const struct GNUNET_CRYPTO_EcdsaPrivateKey *identity_priv;
   const char *identity;
   struct EgoEntry *ego_entry;
-  struct GNUNET_RECLAIM_Attestation *attribute;
+  struct GNUNET_RECLAIM_Credential *attribute;
   struct GNUNET_TIME_Relative exp;
   char term_data[handle->rest_handle->data_size + 1];
   json_t *data_json;
   json_error_t err;
   struct GNUNET_JSON_Specification attrspec[] =
-  { GNUNET_RECLAIM_JSON_spec_claim_attest (&attribute),
+  { GNUNET_RECLAIM_JSON_spec_credential (&attribute),
     GNUNET_JSON_spec_end () };
 
   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              "Adding an attestation for %s.\n",
+              "Adding an credential for %s.\n",
               handle->url);
-  if (strlen (GNUNET_REST_API_NS_RECLAIM_ATTESTATION) >= strlen (
+  if (strlen (GNUNET_REST_API_NS_RECLAIM_CREDENTIAL) >= strlen (
         handle->url))
   {
     GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "No identity given.\n");
@@ -483,9 +488,9 @@ add_attestation_cont (struct GNUNET_REST_RequestHandle *con_handle,
     return;
   }
   identity = handle->url + strlen (
-    GNUNET_REST_API_NS_RECLAIM_ATTESTATION) + 1;
+    GNUNET_REST_API_NS_RECLAIM_CREDENTIAL) + 1;
 
-  for (ego_entry = handle->ego_head; NULL != ego_entry;
+  for (ego_entry = ego_head; NULL != ego_entry;
        ego_entry = ego_entry->next)
     if (0 == strcmp (identity, ego_entry->identifier))
       break;
@@ -513,7 +518,7 @@ add_attestation_cont (struct GNUNET_REST_RequestHandle *con_handle,
   if (NULL == attribute)
   {
     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                "Unable to parse attestation from %s\n",
+                "Unable to parse credential from %s\n",
                 term_data);
     GNUNET_SCHEDULER_add_now (&do_error, handle);
     return;
@@ -523,9 +528,8 @@ add_attestation_cont (struct GNUNET_REST_RequestHandle *con_handle,
    */
   if (GNUNET_YES == GNUNET_RECLAIM_id_is_zero (&attribute->id))
     GNUNET_RECLAIM_id_generate (&attribute->id);
-  handle->idp = GNUNET_RECLAIM_connect (cfg);
   exp = GNUNET_TIME_UNIT_HOURS;
-  handle->idp_op = GNUNET_RECLAIM_attestation_store (handle->idp,
+  handle->idp_op = GNUNET_RECLAIM_credential_store (idp,
                                                      identity_priv,
                                                      attribute,
                                                      &exp,
@@ -536,51 +540,52 @@ add_attestation_cont (struct GNUNET_REST_RequestHandle *con_handle,
 
 
 /**
- * Collect all attestations for an ego
+ * Collect all credentials for an ego
  *
  */
 static void
-attest_collect (void *cls,
+cred_collect (void *cls,
                 const struct GNUNET_CRYPTO_EcdsaPublicKey *identity,
-                const struct GNUNET_RECLAIM_Attestation *attest)
+                const struct GNUNET_RECLAIM_Credential *cred)
 {
   struct RequestHandle *handle = cls;
   struct GNUNET_RECLAIM_AttributeList *attrs;
   struct GNUNET_RECLAIM_AttributeListEntry *ale;
   struct GNUNET_TIME_Absolute exp;
   json_t *attr_obj;
-  json_t *attest_obj;
+  json_t *cred_obj;
   const char *type;
   char *tmp_value;
   char *id_str;
   char *issuer;
 
 
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Adding attestation: %s\n",
-              attest->name);
-  attrs = GNUNET_RECLAIM_attestation_get_attributes (attest);
-  issuer = GNUNET_RECLAIM_attestation_get_issuer (attest);
-  tmp_value = GNUNET_RECLAIM_attestation_value_to_string (attest->type,
-                                                          attest->data,
-                                                          attest->data_size);
-  attest_obj = json_object ();
-  json_object_set_new (attest_obj, "value", json_string (tmp_value));
-  json_object_set_new (attest_obj, "name", json_string (attest->name));
-  type = GNUNET_RECLAIM_attestation_number_to_typename (attest->type);
-  json_object_set_new (attest_obj, "type", json_string (type));
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Adding credential: %s\n",
+              cred->name);
+  attrs = GNUNET_RECLAIM_credential_get_attributes (cred);
+  issuer = GNUNET_RECLAIM_credential_get_issuer (cred);
+  tmp_value = GNUNET_RECLAIM_credential_value_to_string (cred->type,
+                                                          cred->data,
+                                                          cred->data_size);
+  cred_obj = json_object ();
+  json_object_set_new (cred_obj, "value", json_string (tmp_value));
+  json_object_set_new (cred_obj, "name", json_string (cred->name));
+  type = GNUNET_RECLAIM_credential_number_to_typename (cred->type);
+  json_object_set_new (cred_obj, "type", json_string (type));
   if (NULL != issuer)
   {
-    json_object_set_new (attest_obj, "issuer", json_string (issuer));
+    json_object_set_new (cred_obj, "issuer", json_string (issuer));
     GNUNET_free (issuer);
   }
-  if (GNUNET_OK == GNUNET_RECLAIM_attestation_get_expiration (attest,
+  if (GNUNET_OK == GNUNET_RECLAIM_credential_get_expiration (cred,
                                                               &exp))
   {
-    json_object_set_new (attest_obj, "expiration", json_integer (exp.abs_value_us));
+    json_object_set_new (cred_obj, "expiration", json_integer (
+                           exp.abs_value_us));
   }
-  id_str = GNUNET_STRINGS_data_to_string_alloc (&attest->id,
-                                                sizeof(attest->id));
-  json_object_set_new (attest_obj, "id", json_string (id_str));
+  id_str = GNUNET_STRINGS_data_to_string_alloc (&cred->id,
+                                                sizeof(cred->id));
+  json_object_set_new (cred_obj, "id", json_string (id_str));
   GNUNET_free (tmp_value);
   GNUNET_free (id_str);
   if (NULL != attrs)
@@ -597,31 +602,31 @@ attest_collect (void *cls,
       json_object_set_new (attr_obj, "name", json_string (
                              ale->attribute->name));
 
-      json_object_set_new (attr_obj, "flag", json_string ("1")); //FIXME
+      json_object_set_new (attr_obj, "flag", json_string ("1")); // FIXME
       type = GNUNET_RECLAIM_attribute_number_to_typename (ale->attribute->type);
       json_object_set_new (attr_obj, "type", json_string (type));
       json_object_set_new (attr_obj, "id", json_string (""));
-      json_object_set_new (attr_obj, "attestation", json_string (""));
+      json_object_set_new (attr_obj, "credential", json_string (""));
       json_array_append_new (attr_arr, attr_obj);
       GNUNET_free (tmp_value);
     }
-    json_object_set_new (attest_obj, "attributes", attr_arr);
+    json_object_set_new (cred_obj, "attributes", attr_arr);
   }
-  json_array_append_new (handle->resp_object, attest_obj);
+  json_array_append_new (handle->resp_object, cred_obj);
   GNUNET_RECLAIM_attribute_list_destroy (attrs);
-  GNUNET_RECLAIM_get_attestations_next (handle->attest_it);
+  GNUNET_RECLAIM_get_credentials_next (handle->cred_it);
 }
 
 
 /**
- * Lists attestation for identity request
+ * Lists credential for identity request
  *
  * @param con_handle the connection handle
  * @param url the url
  * @param cls the RequestHandle
  */
 static void
-list_attestation_cont (struct GNUNET_REST_RequestHandle *con_handle,
+list_credential_cont (struct GNUNET_REST_RequestHandle *con_handle,
                        const char *url,
                        void *cls)
 {
@@ -631,9 +636,9 @@ list_attestation_cont (struct GNUNET_REST_RequestHandle *con_handle,
   char *identity;
 
   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              "Getting attestations for %s.\n",
+              "Getting credentials for %s.\n",
               handle->url);
-  if (strlen (GNUNET_REST_API_NS_RECLAIM_ATTESTATION) >= strlen (
+  if (strlen (GNUNET_REST_API_NS_RECLAIM_CREDENTIAL) >= strlen (
         handle->url))
   {
     GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "No identity given.\n");
@@ -641,9 +646,9 @@ list_attestation_cont (struct GNUNET_REST_RequestHandle *con_handle,
     return;
   }
   identity = handle->url + strlen (
-    GNUNET_REST_API_NS_RECLAIM_ATTESTATION) + 1;
+    GNUNET_REST_API_NS_RECLAIM_CREDENTIAL) + 1;
 
-  for (ego_entry = handle->ego_head; NULL != ego_entry;
+  for (ego_entry = ego_head; NULL != ego_entry;
        ego_entry = ego_entry->next)
     if (0 == strcmp (identity, ego_entry->identifier))
       break;
@@ -658,12 +663,11 @@ list_attestation_cont (struct GNUNET_REST_RequestHandle *con_handle,
     return;
   }
   priv_key = GNUNET_IDENTITY_ego_get_private_key (ego_entry->ego);
-  handle->idp = GNUNET_RECLAIM_connect (cfg);
-  handle->attest_it = GNUNET_RECLAIM_get_attestations_start (handle->idp,
+  handle->cred_it = GNUNET_RECLAIM_get_credentials_start (idp,
                                                              priv_key,
                                                              &collect_error_cb,
                                                              handle,
-                                                             &attest_collect,
+                                                             &cred_collect,
                                                              handle,
                                                              &
                                                              collect_finished_cb,
@@ -672,27 +676,27 @@ list_attestation_cont (struct GNUNET_REST_RequestHandle *con_handle,
 
 
 /**
- * Deletes attestation from an identity
+ * Deletes credential from an identity
  *
  * @param con_handle the connection handle
  * @param url the url
  * @param cls the RequestHandle
  */
 static void
-delete_attestation_cont (struct GNUNET_REST_RequestHandle *con_handle,
+delete_credential_cont (struct GNUNET_REST_RequestHandle *con_handle,
                          const char *url,
                          void *cls)
 {
   struct RequestHandle *handle = cls;
   const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv_key;
-  struct GNUNET_RECLAIM_Attestation attr;
+  struct GNUNET_RECLAIM_Credential attr;
   struct EgoEntry *ego_entry;
   char *identity_id_str;
   char *identity;
   char *id;
 
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Deleting attestation.\n");
-  if (strlen (GNUNET_REST_API_NS_RECLAIM_ATTESTATION) >= strlen (
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Deleting credential.\n");
+  if (strlen (GNUNET_REST_API_NS_RECLAIM_CREDENTIAL) >= strlen (
         handle->url))
   {
     GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "No identity given.\n");
@@ -701,7 +705,7 @@ delete_attestation_cont (struct GNUNET_REST_RequestHandle *con_handle,
   }
   identity_id_str =
     strdup (handle->url + strlen (
-              GNUNET_REST_API_NS_RECLAIM_ATTESTATION) + 1);
+              GNUNET_REST_API_NS_RECLAIM_CREDENTIAL) + 1);
   identity = strtok (identity_id_str, "/");
   id = strtok (NULL, "/");
   if ((NULL == identity) || (NULL == id))
@@ -712,7 +716,7 @@ delete_attestation_cont (struct GNUNET_REST_RequestHandle *con_handle,
     return;
   }
 
-  for (ego_entry = handle->ego_head; NULL != ego_entry;
+  for (ego_entry = ego_head; NULL != ego_entry;
        ego_entry = ego_entry->next)
     if (0 == strcmp (identity, ego_entry->identifier))
       break;
@@ -726,11 +730,10 @@ delete_attestation_cont (struct GNUNET_REST_RequestHandle *con_handle,
     return;
   }
   priv_key = GNUNET_IDENTITY_ego_get_private_key (ego_entry->ego);
-  handle->idp = GNUNET_RECLAIM_connect (cfg);
-  memset (&attr, 0, sizeof(struct GNUNET_RECLAIM_Attestation));
+  memset (&attr, 0, sizeof(struct GNUNET_RECLAIM_Credential));
   GNUNET_STRINGS_string_to_data (id, strlen (id), &attr.id, sizeof(attr.id));
   attr.name = "";
-  handle->idp_op = GNUNET_RECLAIM_attestation_delete (handle->idp,
+  handle->idp_op = GNUNET_RECLAIM_credential_delete (idp,
                                                       priv_key,
                                                       &attr,
                                                       &delete_finished_cb,
@@ -767,7 +770,7 @@ list_tickets_cont (struct GNUNET_REST_RequestHandle *con_handle,
   }
   identity = handle->url + strlen (GNUNET_REST_API_NS_IDENTITY_TICKETS) + 1;
 
-  for (ego_entry = handle->ego_head; NULL != ego_entry;
+  for (ego_entry = ego_head; NULL != ego_entry;
        ego_entry = ego_entry->next)
     if (0 == strcmp (identity, ego_entry->identifier))
       break;
@@ -781,9 +784,8 @@ list_tickets_cont (struct GNUNET_REST_RequestHandle *con_handle,
     return;
   }
   priv_key = GNUNET_IDENTITY_ego_get_private_key (ego_entry->ego);
-  handle->idp = GNUNET_RECLAIM_connect (cfg);
   handle->ticket_it =
-    GNUNET_RECLAIM_ticket_iteration_start (handle->idp,
+    GNUNET_RECLAIM_ticket_iteration_start (idp,
                                            priv_key,
                                            &collect_error_cb,
                                            handle,
@@ -809,7 +811,7 @@ add_attribute_cont (struct GNUNET_REST_RequestHandle *con_handle,
   json_t *data_json;
   json_error_t err;
   struct GNUNET_JSON_Specification attrspec[] =
-  { GNUNET_RECLAIM_JSON_spec_claim (&attribute), GNUNET_JSON_spec_end () };
+  { GNUNET_RECLAIM_JSON_spec_attribute (&attribute), GNUNET_JSON_spec_end () };
 
   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
               "Adding an attribute for %s.\n",
@@ -822,7 +824,7 @@ add_attribute_cont (struct GNUNET_REST_RequestHandle *con_handle,
   }
   identity = handle->url + strlen (GNUNET_REST_API_NS_RECLAIM_ATTRIBUTES) + 1;
 
-  for (ego_entry = handle->ego_head; NULL != ego_entry;
+  for (ego_entry = ego_head; NULL != ego_entry;
        ego_entry = ego_entry->next)
     if (0 == strcmp (identity, ego_entry->identifier))
       break;
@@ -861,9 +863,8 @@ add_attribute_cont (struct GNUNET_REST_RequestHandle *con_handle,
    */
   if (GNUNET_YES == GNUNET_RECLAIM_id_is_zero (&attribute->id))
     GNUNET_RECLAIM_id_generate (&attribute->id);
-  handle->idp = GNUNET_RECLAIM_connect (cfg);
   exp = GNUNET_TIME_UNIT_HOURS;
-  handle->idp_op = GNUNET_RECLAIM_attribute_store (handle->idp,
+  handle->idp_op = GNUNET_RECLAIM_attribute_store (idp,
                                                    identity_priv,
                                                    attribute,
                                                    &exp,
@@ -876,13 +877,13 @@ add_attribute_cont (struct GNUNET_REST_RequestHandle *con_handle,
 /**
  * Parse a JWT and return the respective claim value as Attribute
  *
- * @param attest the jwt attestation
+ * @param cred the jwt credential
  * @param claim the name of the claim in the JWT
  *
  * @return a GNUNET_RECLAIM_Attribute, containing the new value
  */
 struct GNUNET_RECLAIM_Attribute *
-parse_jwt (const struct GNUNET_RECLAIM_Attestation *attest,
+parse_jwt (const struct GNUNET_RECLAIM_Credential *cred,
            const char *claim)
 {
   char *jwt_string;
@@ -898,9 +899,9 @@ parse_jwt (const struct GNUNET_RECLAIM_Attestation *attest,
   json_t *json_val;
   json_error_t *json_err = NULL;
 
-  jwt_string = GNUNET_RECLAIM_attestation_value_to_string (attest->type,
-                                                           attest->data,
-                                                           attest->data_size);
+  jwt_string = GNUNET_RECLAIM_credential_value_to_string (cred->type,
+                                                           cred->data,
+                                                           cred->data_size);
   char *jwt_body = strtok (jwt_string, delim);
   jwt_body = strtok (NULL, delim);
   GNUNET_STRINGS_base64_decode (jwt_body, strlen (jwt_body),
@@ -926,16 +927,16 @@ parse_jwt (const struct GNUNET_RECLAIM_Attestation *attest,
                                               "Error: Referenced Claim Name not Found",
                                               (void **) &data,
                                               &data_size);
-    attr = GNUNET_RECLAIM_attribute_new (claim, &attest->id,
+    attr = GNUNET_RECLAIM_attribute_new (claim, &cred->id,
                                          type, data, data_size);
-    attr->id = attest->id;
+    attr->id = cred->id;
     attr->flag = 1;
   }
   else
   {
-    attr = GNUNET_RECLAIM_attribute_new (claim, &attest->id,
+    attr = GNUNET_RECLAIM_attribute_new (claim, &cred->id,
                                          type, data, data_size);
-    attr->id = attest->id;
+    attr->id = cred->id;
     attr->flag = 1;
   }
   return attr;
@@ -964,7 +965,7 @@ attr_collect (void *cls,
   json_object_set_new (attr_obj, "value", json_string (tmp_value));
   json_object_set_new (attr_obj, "name", json_string (attr->name));
 
-  if (GNUNET_RECLAIM_id_is_zero (&attr->attestation))
+  if (GNUNET_RECLAIM_id_is_zero (&attr->credential))
     json_object_set_new (attr_obj, "flag", json_string ("0"));
   else
     json_object_set_new (attr_obj, "flag", json_string ("1"));
@@ -973,9 +974,9 @@ attr_collect (void *cls,
   id_str = GNUNET_STRINGS_data_to_string_alloc (&attr->id,
                                                 sizeof(attr->id));
   json_object_set_new (attr_obj, "id", json_string (id_str));
-  id_str = GNUNET_STRINGS_data_to_string_alloc (&attr->attestation,
-                                                sizeof(attr->attestation));
-  json_object_set_new (attr_obj, "attestation", json_string (id_str));
+  id_str = GNUNET_STRINGS_data_to_string_alloc (&attr->credential,
+                                                sizeof(attr->credential));
+  json_object_set_new (attr_obj, "credential", json_string (id_str));
   json_array_append (handle->resp_object, attr_obj);
   json_decref (attr_obj);
   GNUNET_free (tmp_value);
@@ -1011,7 +1012,7 @@ list_attribute_cont (struct GNUNET_REST_RequestHandle *con_handle,
   }
   identity = handle->url + strlen (GNUNET_REST_API_NS_RECLAIM_ATTRIBUTES) + 1;
 
-  for (ego_entry = handle->ego_head; NULL != ego_entry;
+  for (ego_entry = ego_head; NULL != ego_entry;
        ego_entry = ego_entry->next)
     if (0 == strcmp (identity, ego_entry->identifier))
       break;
@@ -1026,8 +1027,7 @@ list_attribute_cont (struct GNUNET_REST_RequestHandle *con_handle,
     return;
   }
   priv_key = GNUNET_IDENTITY_ego_get_private_key (ego_entry->ego);
-  handle->idp = GNUNET_RECLAIM_connect (cfg);
-  handle->attr_it = GNUNET_RECLAIM_get_attributes_start (handle->idp,
+  handle->attr_it = GNUNET_RECLAIM_get_attributes_start (idp,
                                                          priv_key,
                                                          &collect_error_cb,
                                                          handle,
@@ -1077,7 +1077,7 @@ delete_attribute_cont (struct GNUNET_REST_RequestHandle *con_handle,
     return;
   }
 
-  for (ego_entry = handle->ego_head; NULL != ego_entry;
+  for (ego_entry = ego_head; NULL != ego_entry;
        ego_entry = ego_entry->next)
     if (0 == strcmp (identity, ego_entry->identifier))
       break;
@@ -1091,11 +1091,10 @@ delete_attribute_cont (struct GNUNET_REST_RequestHandle *con_handle,
     return;
   }
   priv_key = GNUNET_IDENTITY_ego_get_private_key (ego_entry->ego);
-  handle->idp = GNUNET_RECLAIM_connect (cfg);
   memset (&attr, 0, sizeof(struct GNUNET_RECLAIM_Attribute));
   GNUNET_STRINGS_string_to_data (id, strlen (id), &attr.id, sizeof(attr.id));
   attr.name = "";
-  handle->idp_op = GNUNET_RECLAIM_attribute_delete (handle->idp,
+  handle->idp_op = GNUNET_RECLAIM_attribute_delete (idp,
                                                     priv_key,
                                                     &attr,
                                                     &delete_finished_cb,
@@ -1151,7 +1150,7 @@ revoke_ticket_cont (struct GNUNET_REST_RequestHandle *con_handle,
     return;
   }
 
-  for (ego_entry = handle->ego_head; NULL != ego_entry;
+  for (ego_entry = ego_head; NULL != ego_entry;
        ego_entry = ego_entry->next)
   {
     GNUNET_IDENTITY_ego_get_public_key (ego_entry->ego, &tmp_pk);
@@ -1168,8 +1167,7 @@ revoke_ticket_cont (struct GNUNET_REST_RequestHandle *con_handle,
   }
   identity_priv = GNUNET_IDENTITY_ego_get_private_key (ego_entry->ego);
 
-  handle->idp = GNUNET_RECLAIM_connect (cfg);
-  handle->idp_op = GNUNET_RECLAIM_ticket_revoke (handle->idp,
+  handle->idp_op = GNUNET_RECLAIM_ticket_revoke (idp,
                                                  identity_priv,
                                                  ticket,
                                                  &finished_cont,
@@ -1182,7 +1180,7 @@ static void
 consume_cont (void *cls,
               const struct GNUNET_CRYPTO_EcdsaPublicKey *identity,
               const struct GNUNET_RECLAIM_Attribute *attr,
-              const struct GNUNET_RECLAIM_Attestation *attest)
+              const struct GNUNET_RECLAIM_Presentation *pres)
 {
   struct RequestHandle *handle = cls;
   char *val_str;
@@ -1255,7 +1253,7 @@ consume_ticket_cont (struct GNUNET_REST_RequestHandle *con_handle,
     json_decref (data_json);
     return;
   }
-  for (ego_entry = handle->ego_head; NULL != ego_entry;
+  for (ego_entry = ego_head; NULL != ego_entry;
        ego_entry = ego_entry->next)
   {
     GNUNET_IDENTITY_ego_get_public_key (ego_entry->ego, &tmp_pk);
@@ -1272,8 +1270,7 @@ consume_ticket_cont (struct GNUNET_REST_RequestHandle *con_handle,
   }
   identity_priv = GNUNET_IDENTITY_ego_get_private_key (ego_entry->ego);
   handle->resp_object = json_object ();
-  handle->idp = GNUNET_RECLAIM_connect (cfg);
-  handle->idp_op = GNUNET_RECLAIM_ticket_consume (handle->idp,
+  handle->idp_op = GNUNET_RECLAIM_ticket_consume (idp,
                                                   identity_priv,
                                                   ticket,
                                                   &consume_cont,
@@ -1306,55 +1303,6 @@ options_cont (struct GNUNET_REST_RequestHandle *con_handle,
 }
 
 
-/**
- * Handle rest request
- *
- * @param handle the request handle
- */
-static void
-init_cont (struct RequestHandle *handle)
-{
-  struct GNUNET_REST_RequestHandlerError err;
-  static const struct GNUNET_REST_RequestHandler handlers[] =
-  { { MHD_HTTP_METHOD_GET,
-      GNUNET_REST_API_NS_RECLAIM_ATTRIBUTES,
-      &list_attribute_cont },
-    { MHD_HTTP_METHOD_POST,
-      GNUNET_REST_API_NS_RECLAIM_ATTRIBUTES,
-      &add_attribute_cont },
-    { MHD_HTTP_METHOD_DELETE,
-      GNUNET_REST_API_NS_RECLAIM_ATTRIBUTES,
-      &delete_attribute_cont },
-    { MHD_HTTP_METHOD_GET,
-      GNUNET_REST_API_NS_RECLAIM_ATTESTATION,
-      &list_attestation_cont },
-    { MHD_HTTP_METHOD_POST,
-      GNUNET_REST_API_NS_RECLAIM_ATTESTATION,
-      &add_attestation_cont },
-    { MHD_HTTP_METHOD_DELETE,
-      GNUNET_REST_API_NS_RECLAIM_ATTESTATION,
-      &delete_attestation_cont },
-    { MHD_HTTP_METHOD_GET,
-      GNUNET_REST_API_NS_IDENTITY_TICKETS,
-      &list_tickets_cont },
-    { MHD_HTTP_METHOD_POST,
-      GNUNET_REST_API_NS_IDENTITY_REVOKE,
-      &revoke_ticket_cont },
-    { MHD_HTTP_METHOD_POST,
-      GNUNET_REST_API_NS_IDENTITY_CONSUME,
-      &consume_ticket_cont },
-    { MHD_HTTP_METHOD_OPTIONS, GNUNET_REST_API_NS_RECLAIM, &options_cont },
-    GNUNET_REST_HANDLER_END };
-
-  if (GNUNET_NO ==
-      GNUNET_REST_handle_request (handle->rest_handle, handlers, &err, handle))
-  {
-    handle->response_code = err.error_code;
-    GNUNET_SCHEDULER_add_now (&do_error, handle);
-  }
-}
-
-
 /**
  * If listing is enabled, prints information about the egos.
  *
@@ -1394,52 +1342,128 @@ list_ego (void *cls,
           void **ctx,
           const char *identifier)
 {
-  struct RequestHandle *handle = cls;
   struct EgoEntry *ego_entry;
   struct GNUNET_CRYPTO_EcdsaPublicKey pk;
 
-  if ((NULL == ego) && (ID_REST_STATE_INIT == handle->state))
+  if ((NULL == ego) && (ID_REST_STATE_INIT == state))
   {
-    handle->state = ID_REST_STATE_POST_INIT;
-    init_cont (handle);
+    state = ID_REST_STATE_POST_INIT;
     return;
   }
-  if (ID_REST_STATE_INIT == handle->state)
+  if (ID_REST_STATE_INIT == state)
   {
     ego_entry = GNUNET_new (struct EgoEntry);
     GNUNET_IDENTITY_ego_get_public_key (ego, &pk);
     ego_entry->keystring = GNUNET_CRYPTO_ecdsa_public_key_to_string (&pk);
     ego_entry->ego = ego;
     ego_entry->identifier = GNUNET_strdup (identifier);
-    GNUNET_CONTAINER_DLL_insert_tail (handle->ego_head,
-                                      handle->ego_tail,
+    GNUNET_CONTAINER_DLL_insert_tail (ego_head,
+                                      ego_tail,
                                       ego_entry);
   }
+  /* Ego renamed or added */
+  if (identifier != NULL)
+  {
+    for (ego_entry = ego_head; NULL != ego_entry;
+         ego_entry = ego_entry->next)
+    {
+      if (ego_entry->ego == ego)
+      {
+        /* Rename */
+        GNUNET_free (ego_entry->identifier);
+        ego_entry->identifier = GNUNET_strdup (identifier);
+        break;
+      }
+    }
+    if (NULL == ego_entry)
+    {
+      /* Add */
+      ego_entry = GNUNET_new (struct EgoEntry);
+      GNUNET_IDENTITY_ego_get_public_key (ego, &pk);
+      ego_entry->keystring = GNUNET_CRYPTO_ecdsa_public_key_to_string (&pk);
+      ego_entry->ego = ego;
+      ego_entry->identifier = GNUNET_strdup (identifier);
+      GNUNET_CONTAINER_DLL_insert_tail (ego_head,
+                                        ego_tail,
+                                        ego_entry);
+    }
+  }
+  else
+  {
+    /* Delete */
+    for (ego_entry = ego_head; NULL != ego_entry;
+         ego_entry = ego_entry->next)
+    {
+      if (ego_entry->ego == ego)
+        break;
+    }
+    if (NULL == ego_entry)
+      return; /* Not found */
+
+    GNUNET_CONTAINER_DLL_remove (ego_head,
+                                 ego_tail,
+                                 ego_entry);
+    GNUNET_free (ego_entry->identifier);
+    GNUNET_free (ego_entry->keystring);
+    GNUNET_free (ego_entry);
+    return;
+  }
+
 }
 
 
-static void
+static enum GNUNET_GenericReturnValue
 rest_identity_process_request (struct GNUNET_REST_RequestHandle *rest_handle,
                                GNUNET_REST_ResultProcessor proc,
                                void *proc_cls)
 {
   struct RequestHandle *handle = GNUNET_new (struct RequestHandle);
+  struct GNUNET_REST_RequestHandlerError err;
+  static const struct GNUNET_REST_RequestHandler handlers[] =
+  { { MHD_HTTP_METHOD_GET,
+      GNUNET_REST_API_NS_RECLAIM_ATTRIBUTES, &list_attribute_cont },
+  { MHD_HTTP_METHOD_POST,
+    GNUNET_REST_API_NS_RECLAIM_ATTRIBUTES, &add_attribute_cont },
+  { MHD_HTTP_METHOD_DELETE,
+    GNUNET_REST_API_NS_RECLAIM_ATTRIBUTES, &delete_attribute_cont },
+  { MHD_HTTP_METHOD_GET,
+    GNUNET_REST_API_NS_RECLAIM_CREDENTIAL, &list_credential_cont },
+  { MHD_HTTP_METHOD_POST,
+    GNUNET_REST_API_NS_RECLAIM_CREDENTIAL, &add_credential_cont },
+  { MHD_HTTP_METHOD_DELETE,
+    GNUNET_REST_API_NS_RECLAIM_CREDENTIAL, &delete_credential_cont },
+  { MHD_HTTP_METHOD_GET,
+    GNUNET_REST_API_NS_IDENTITY_TICKETS, &list_tickets_cont },
+  { MHD_HTTP_METHOD_POST,
+    GNUNET_REST_API_NS_IDENTITY_REVOKE, &revoke_ticket_cont },
+  { MHD_HTTP_METHOD_POST,
+    GNUNET_REST_API_NS_IDENTITY_CONSUME, &consume_ticket_cont },
+  { MHD_HTTP_METHOD_OPTIONS, GNUNET_REST_API_NS_RECLAIM, &options_cont },
+  GNUNET_REST_HANDLER_END
+  };
 
   handle->response_code = 0;
   handle->timeout = GNUNET_TIME_UNIT_FOREVER_REL;
   handle->proc_cls = proc_cls;
   handle->proc = proc;
-  handle->state = ID_REST_STATE_INIT;
   handle->rest_handle = rest_handle;
 
   handle->url = GNUNET_strdup (rest_handle->url);
   if (handle->url[strlen (handle->url) - 1] == '/')
     handle->url[strlen (handle->url) - 1] = '\0';
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Connecting...\n");
-  handle->identity_handle = GNUNET_IDENTITY_connect (cfg, &list_ego, handle);
   handle->timeout_task =
     GNUNET_SCHEDULER_add_delayed (handle->timeout, &do_timeout, handle);
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Connected\n");
+  GNUNET_CONTAINER_DLL_insert (requests_head,
+                               requests_tail,
+                               handle);
+  if (GNUNET_NO ==
+      GNUNET_REST_handle_request (handle->rest_handle, handlers, &err, handle))
+  {
+    cleanup_handle (handle);
+    return GNUNET_NO;
+  }
+
+  return GNUNET_YES;
 }
 
 
@@ -1471,7 +1495,9 @@ libgnunet_plugin_rest_reclaim_init (void *cls)
                    MHD_HTTP_METHOD_PUT,
                    MHD_HTTP_METHOD_DELETE,
                    MHD_HTTP_METHOD_OPTIONS);
-
+  identity_handle = GNUNET_IDENTITY_connect (cfg, &list_ego, NULL);
+  state = ID_REST_STATE_INIT;
+  idp = GNUNET_RECLAIM_connect (cfg);
   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
               _ ("Identity Provider REST API initialized\n"));
   return api;
@@ -1489,8 +1515,25 @@ libgnunet_plugin_rest_reclaim_done (void *cls)
 {
   struct GNUNET_REST_Plugin *api = cls;
   struct Plugin *plugin = api->cls;
+  struct RequestHandle *request;
+  struct EgoEntry *ego_entry;
+  struct EgoEntry *ego_tmp;
 
   plugin->cfg = NULL;
+  while (NULL != (request = requests_head))
+    do_error (request);
+  if (NULL != idp)
+    GNUNET_RECLAIM_disconnect (idp);
+  if (NULL != identity_handle)
+    GNUNET_IDENTITY_disconnect (identity_handle);
+  for (ego_entry = ego_head; NULL != ego_entry;)
+  {
+    ego_tmp = ego_entry;
+    ego_entry = ego_entry->next;
+    GNUNET_free (ego_tmp->identifier);
+    GNUNET_free (ego_tmp->keystring);
+    GNUNET_free (ego_tmp);
+  }
 
   GNUNET_free (allow_methods);
   GNUNET_free (api);
diff --git a/src/reclaim/reclaim.h b/src/reclaim/reclaim.h
index 7b5d7ab194a211e41ccf7eefa2a3cf7bb0547296..bc7f343658f491d181a52857234d3305017c1ff2 100644
--- a/src/reclaim/reclaim.h
+++ b/src/reclaim/reclaim.h
@@ -139,9 +139,9 @@ struct AttributeResultMessage
   uint16_t attr_len GNUNET_PACKED;
 
   /**
-   * Length of serialized attestation data
+   * Length of serialized credential data
    */
-  uint16_t attestation_len GNUNET_PACKED;
+  uint16_t credential_len GNUNET_PACKED;
 
   /**
    * always zero (for alignment)
@@ -159,9 +159,9 @@ struct AttributeResultMessage
 };
 
 /**
- * Attestation is returned from the idp.
+ * Credential is returned from the idp.
  */
-struct AttestationResultMessage
+struct CredentialResultMessage
 {
   /**
    * Message header
@@ -176,7 +176,7 @@ struct AttestationResultMessage
   /**
    * Length of serialized attribute data
    */
-  uint16_t attestation_len GNUNET_PACKED;
+  uint16_t credential_len GNUNET_PACKED;
 
   /**
    * always zero (for alignment)
@@ -189,7 +189,7 @@ struct AttestationResultMessage
   struct GNUNET_CRYPTO_EcdsaPublicKey identity;
 
   /* followed by:
-   * serialized attestation data
+   * serialized credential data
    */
 };
 
@@ -234,9 +234,9 @@ struct AttributeIterationNextMessage
 
 
 /**
- * Start a attestation iteration for the given identity
+ * Start a credential iteration for the given identity
  */
-struct AttestationIterationStartMessage
+struct CredentialIterationStartMessage
 {
   /**
    * Message
@@ -256,9 +256,9 @@ struct AttestationIterationStartMessage
 
 
 /**
- * Ask for next result of attestation iteration for the given operation
+ * Ask for next result of credential iteration for the given operation
  */
-struct AttestationIterationNextMessage
+struct CredentialIterationNextMessage
 {
   /**
    * Type will be #GNUNET_MESSAGE_TYPE_RECLAIM_ATTRIBUTE_ITERATION_NEXT
@@ -273,9 +273,9 @@ struct AttestationIterationNextMessage
 
 
 /**
- * Stop attestation iteration for the given operation
+ * Stop credential iteration for the given operation
  */
-struct AttestationIterationStopMessage
+struct CredentialIterationStopMessage
 {
   /**
    * Type will be #GNUNET_MESSAGE_TYPE_RECLAIM_ATTRIBUTE_ITERATION_STOP
@@ -462,10 +462,17 @@ struct TicketResultMessage
    */
   uint32_t id GNUNET_PACKED;
 
+  /**
+   * Length of new presentations created
+   */
+  uint32_t presentations_len GNUNET_PACKED;
+
   /**
    * The new ticket
    */
   struct GNUNET_RECLAIM_Ticket ticket;
+
+  /* Followed by the serialized GNUNET_RECLAIM_PresentationList */
 };
 
 /**
@@ -520,9 +527,9 @@ struct ConsumeTicketResultMessage
   uint16_t attrs_len GNUNET_PACKED;
 
   /**
-   * Length of attestation data
+   * Length of presentation data
    */
-  uint16_t attestations_len;
+  uint16_t presentations_len;
 
   /**
    * always zero (for alignment)
diff --git a/src/reclaim/reclaim_api.c b/src/reclaim/reclaim_api.c
index ff549fa7119879e2e543e7315ef96c6007df28a3..1e02515190da530dbbfd0cc3378dbd3dd8b9a3f7 100644
--- a/src/reclaim/reclaim_api.c
+++ b/src/reclaim/reclaim_api.c
@@ -77,9 +77,9 @@ struct GNUNET_RECLAIM_Operation
   GNUNET_RECLAIM_AttributeTicketResult atr_cb;
 
   /**
-   * Attestation result callback
+   * Credential result callback
    */
-  GNUNET_RECLAIM_AttestationResult at_cb;
+  GNUNET_RECLAIM_CredentialResult at_cb;
 
   /**
    * Revocation result callback
@@ -91,6 +91,11 @@ struct GNUNET_RECLAIM_Operation
    */
   GNUNET_RECLAIM_TicketCallback tr_cb;
 
+  /**
+   * Ticket issue result callback
+   */
+  GNUNET_RECLAIM_IssueTicketCallback ti_cb;
+
   /**
    * Envelope with the message for this queue entry.
    */
@@ -239,19 +244,19 @@ struct GNUNET_RECLAIM_AttributeIterator
 };
 
 /**
- * Handle for a attestation iterator operation
+ * Handle for a credential iterator operation
  */
-struct GNUNET_RECLAIM_AttestationIterator
+struct GNUNET_RECLAIM_CredentialIterator
 {
   /**
    * Kept in a DLL.
    */
-  struct GNUNET_RECLAIM_AttestationIterator *next;
+  struct GNUNET_RECLAIM_CredentialIterator *next;
 
   /**
    * Kept in a DLL.
    */
-  struct GNUNET_RECLAIM_AttestationIterator *prev;
+  struct GNUNET_RECLAIM_CredentialIterator *prev;
 
   /**
    * Main handle to access the service.
@@ -271,7 +276,7 @@ struct GNUNET_RECLAIM_AttestationIterator
   /**
    * The continuation to call with the results
    */
-  GNUNET_RECLAIM_AttestationResult proc;
+  GNUNET_RECLAIM_CredentialResult proc;
 
   /**
    * Closure for @e proc.
@@ -349,12 +354,12 @@ struct GNUNET_RECLAIM_Handle
   /**
    * Head of active iterations
    */
-  struct GNUNET_RECLAIM_AttestationIterator *ait_head;
+  struct GNUNET_RECLAIM_CredentialIterator *ait_head;
 
   /**
    * Tail of active iterations
    */
-  struct GNUNET_RECLAIM_AttestationIterator *ait_tail;
+  struct GNUNET_RECLAIM_CredentialIterator *ait_tail;
 
   /**
    * Head of active iterations
@@ -464,7 +469,7 @@ free_it (struct GNUNET_RECLAIM_AttributeIterator *it)
  * @param ait entry to free
  */
 static void
-free_ait (struct GNUNET_RECLAIM_AttestationIterator *ait)
+free_ait (struct GNUNET_RECLAIM_CredentialIterator *ait)
 {
   struct GNUNET_RECLAIM_Handle *h = ait->h;
 
@@ -561,13 +566,13 @@ check_consume_ticket_result (void *cls,
 {
   size_t msg_len;
   size_t attrs_len;
-  size_t attests_len;
+  size_t pl_len;
 
   msg_len = ntohs (msg->header.size);
   attrs_len = ntohs (msg->attrs_len);
-  attests_len = ntohs (msg->attestations_len);
+  pl_len = ntohs (msg->presentations_len);
   if (msg_len !=
-      sizeof(struct ConsumeTicketResultMessage) + attrs_len + attests_len)
+      sizeof(struct ConsumeTicketResultMessage) + attrs_len + pl_len)
   {
     GNUNET_break (0);
     return GNUNET_SYSERR;
@@ -590,12 +595,12 @@ handle_consume_ticket_result (void *cls,
   struct GNUNET_RECLAIM_Handle *h = cls;
   struct GNUNET_RECLAIM_Operation *op;
   size_t attrs_len;
-  size_t attests_len;
+  size_t pl_len;
   uint32_t r_id = ntohl (msg->id);
   char *read_ptr;
 
   attrs_len = ntohs (msg->attrs_len);
-  attests_len = ntohs (msg->attestations_len);
+  pl_len = ntohs (msg->presentations_len);
   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Processing ticket result.\n");
 
 
@@ -608,13 +613,12 @@ handle_consume_ticket_result (void *cls,
   {
     struct GNUNET_RECLAIM_AttributeList *attrs;
     struct GNUNET_RECLAIM_AttributeListEntry *le;
-    struct GNUNET_RECLAIM_AttestationList *attests;
-    struct GNUNET_RECLAIM_AttestationListEntry *ale;
+    struct GNUNET_RECLAIM_PresentationList *pl;
+    struct GNUNET_RECLAIM_PresentationListEntry *ple;
     attrs =
       GNUNET_RECLAIM_attribute_list_deserialize ((char *) &msg[1], attrs_len);
     read_ptr = ((char *) &msg[1]) + attrs_len;
-    attests =
-      GNUNET_RECLAIM_attestation_list_deserialize (read_ptr, attests_len);
+    pl = GNUNET_RECLAIM_presentation_list_deserialize (read_ptr, pl_len);
     if (NULL != op->atr_cb)
     {
       if (NULL == attrs)
@@ -626,22 +630,22 @@ handle_consume_ticket_result (void *cls,
         for (le = attrs->list_head; NULL != le; le = le->next)
         {
           if (GNUNET_NO ==
-              GNUNET_RECLAIM_id_is_zero (&le->attribute->attestation))
+              GNUNET_RECLAIM_id_is_zero (&le->attribute->credential))
           {
-            for (ale = attests->list_head; NULL != ale; ale = ale->next)
+            for (ple = pl->list_head; NULL != ple; ple = ple->next)
             {
               if (GNUNET_YES ==
-                  GNUNET_RECLAIM_id_is_equal (&le->attribute->attestation,
-                                              &ale->attestation->id))
+                  GNUNET_RECLAIM_id_is_equal (&le->attribute->credential,
+                                              &ple->presentation->credential_id))
               {
                 op->atr_cb (op->cls, &msg->identity,
-                            le->attribute, ale->attestation);
+                            le->attribute, ple->presentation);
                 break;
               }
 
             }
           }
-          else     // No attestations
+          else     // No credentials
           {
             op->atr_cb (op->cls, &msg->identity,
                         le->attribute, NULL);
@@ -649,10 +653,10 @@ handle_consume_ticket_result (void *cls,
         }
         if (NULL != attrs)
           GNUNET_RECLAIM_attribute_list_destroy (attrs);
-        if (NULL != attests)
-          GNUNET_RECLAIM_attestation_list_destroy (attests);
+        if (NULL != pl)
+          GNUNET_RECLAIM_presentation_list_destroy (pl);
         attrs = NULL;
-        attests = NULL;
+        pl = NULL;
       }
       op->atr_cb (op->cls, NULL, NULL, NULL);
     }
@@ -747,7 +751,8 @@ handle_attribute_result (void *cls, const struct AttributeResultMessage *msg)
 
   {
     struct GNUNET_RECLAIM_Attribute *attr;
-    attr = GNUNET_RECLAIM_attribute_deserialize ((char *) &msg[1], attr_len);
+    GNUNET_RECLAIM_attribute_deserialize ((char *) &msg[1], attr_len,
+                                          &attr);
     if (NULL != it)
     {
       if (NULL != it->proc)
@@ -767,21 +772,21 @@ handle_attribute_result (void *cls, const struct AttributeResultMessage *msg)
 
 /**
    * Handle an incoming message of type
-   * #GNUNET_MESSAGE_TYPE_RECLAIM_attestation_RESULT
+   * #GNUNET_MESSAGE_TYPE_RECLAIM_credential_RESULT
    *
    * @param cls
    * @param msg the message we received
    * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
    */
 static int
-check_attestation_result (void *cls, const struct AttestationResultMessage *msg)
+check_credential_result (void *cls, const struct CredentialResultMessage *msg)
 {
   size_t msg_len;
-  size_t attest_len;
+  size_t cred_len;
 
   msg_len = ntohs (msg->header.size);
-  attest_len = ntohs (msg->attestation_len);
-  if (msg_len != sizeof(struct AttestationResultMessage) + attest_len)
+  cred_len = ntohs (msg->credential_len);
+  if (msg_len != sizeof(struct CredentialResultMessage) + cred_len)
   {
     GNUNET_break (0);
     return GNUNET_SYSERR;
@@ -792,24 +797,24 @@ check_attestation_result (void *cls, const struct AttestationResultMessage *msg)
 
 /**
  * Handle an incoming message of type
- * #GNUNET_MESSAGE_TYPE_RECLAIM_attestation_RESULT
+ * #GNUNET_MESSAGE_TYPE_RECLAIM_credential_RESULT
  *
  * @param cls
  * @param msg the message we received
  */
 static void
-handle_attestation_result (void *cls, const struct
-                           AttestationResultMessage *msg)
+handle_credential_result (void *cls, const struct
+                           CredentialResultMessage *msg)
 {
   static struct GNUNET_CRYPTO_EcdsaPrivateKey identity_dummy;
   struct GNUNET_RECLAIM_Handle *h = cls;
-  struct GNUNET_RECLAIM_AttestationIterator *it;
+  struct GNUNET_RECLAIM_CredentialIterator *it;
   struct GNUNET_RECLAIM_Operation *op;
   size_t att_len;
   uint32_t r_id = ntohl (msg->id);
 
-  att_len = ntohs (msg->attestation_len);
-  LOG (GNUNET_ERROR_TYPE_DEBUG, "Processing attestation result.\n");
+  att_len = ntohs (msg->credential_len);
+  LOG (GNUNET_ERROR_TYPE_DEBUG, "Processing credential result.\n");
 
 
   for (it = h->ait_head; NULL != it; it = it->next)
@@ -847,8 +852,8 @@ handle_attestation_result (void *cls, const struct
   }
 
   {
-    struct GNUNET_RECLAIM_Attestation *att;
-    att = GNUNET_RECLAIM_attestation_deserialize ((char *) &msg[1], att_len);
+    struct GNUNET_RECLAIM_Credential *att;
+    att = GNUNET_RECLAIM_credential_deserialize ((char *) &msg[1], att_len);
 
     if (NULL != it)
     {
@@ -866,6 +871,30 @@ handle_attestation_result (void *cls, const struct
   GNUNET_assert (0);
 }
 
+/**
+   * Handle an incoming message of type
+   * #GNUNET_MESSAGE_TYPE_RECLAIM_TICKET_RESULT
+   *
+   * @param cls
+   * @param msg the message we received
+   * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
+   */
+static int
+check_ticket_result (void *cls, const struct TicketResultMessage *msg)
+{
+  size_t msg_len;
+  size_t pres_len;
+
+  msg_len = ntohs (msg->header.size);
+  pres_len = ntohs (msg->presentations_len);
+  if (msg_len != sizeof(struct TicketResultMessage) + pres_len)
+  {
+    GNUNET_break (0);
+    return GNUNET_SYSERR;
+  }
+  return GNUNET_OK;
+}
+
 
 /**
  * Handle an incoming message of type
@@ -880,8 +909,10 @@ handle_ticket_result (void *cls, const struct TicketResultMessage *msg)
   struct GNUNET_RECLAIM_Handle *handle = cls;
   struct GNUNET_RECLAIM_Operation *op;
   struct GNUNET_RECLAIM_TicketIterator *it;
+  struct GNUNET_RECLAIM_PresentationList *pres;
   uint32_t r_id = ntohl (msg->id);
   static const struct GNUNET_RECLAIM_Ticket ticket;
+  uint32_t pres_len = ntohs (msg->presentations_len);
 
   for (op = handle->op_head; NULL != op; op = op->next)
     if (op->r_id == r_id)
@@ -893,18 +924,25 @@ handle_ticket_result (void *cls, const struct TicketResultMessage *msg)
     return;
   if (NULL != op)
   {
+    if (0 < pres_len)
+      pres = GNUNET_RECLAIM_presentation_list_deserialize ((char*)&msg[1],
+                                                           pres_len);
     GNUNET_CONTAINER_DLL_remove (handle->op_head, handle->op_tail, op);
     if (0 ==
         memcmp (&msg->ticket, &ticket, sizeof(struct GNUNET_RECLAIM_Ticket)))
     {
-      if (NULL != op->tr_cb)
-        op->tr_cb (op->cls, NULL);
+      if (NULL != op->ti_cb)
+        op->ti_cb (op->cls, NULL, NULL);
     }
     else
     {
-      if (NULL != op->tr_cb)
-        op->tr_cb (op->cls, &msg->ticket);
+      if (NULL != op->ti_cb)
+        op->ti_cb (op->cls,
+                   &msg->ticket,
+                   (0 < pres_len) ? pres : NULL);
     }
+    if (0 < pres_len)
+      GNUNET_RECLAIM_presentation_list_destroy (pres);
     free_op (op);
     return;
   }
@@ -985,14 +1023,14 @@ reconnect (struct GNUNET_RECLAIM_Handle *h)
                            GNUNET_MESSAGE_TYPE_RECLAIM_ATTRIBUTE_RESULT,
                            struct AttributeResultMessage,
                            h),
-    GNUNET_MQ_hd_var_size (attestation_result,
-                           GNUNET_MESSAGE_TYPE_RECLAIM_ATTESTATION_RESULT,
-                           struct AttestationResultMessage,
+    GNUNET_MQ_hd_var_size (credential_result,
+                           GNUNET_MESSAGE_TYPE_RECLAIM_CREDENTIAL_RESULT,
+                           struct CredentialResultMessage,
+                           h),
+    GNUNET_MQ_hd_var_size (ticket_result,
+                           GNUNET_MESSAGE_TYPE_RECLAIM_TICKET_RESULT,
+                           struct TicketResultMessage,
                            h),
-    GNUNET_MQ_hd_fixed_size (ticket_result,
-                             GNUNET_MESSAGE_TYPE_RECLAIM_TICKET_RESULT,
-                             struct TicketResultMessage,
-                             h),
     GNUNET_MQ_hd_var_size (consume_ticket_result,
                            GNUNET_MESSAGE_TYPE_RECLAIM_CONSUME_TICKET_RESULT,
                            struct ConsumeTicketResultMessage,
@@ -1174,22 +1212,22 @@ GNUNET_RECLAIM_attribute_delete (
 
 
 /**
-   * Store an attestation.  If the attestation is already present,
-   * it is replaced with the new attestation.
+   * Store an credential.  If the credential is already present,
+   * it is replaced with the new credential.
    *
    * @param h handle to the re:claimID service
    * @param pkey private key of the identity
-   * @param attr the attestation value
-   * @param exp_interval the relative expiration interval for the attestation
+   * @param attr the credential value
+   * @param exp_interval the relative expiration interval for the credential
    * @param cont continuation to call when done
    * @param cont_cls closure for @a cont
    * @return handle to abort the request
    */
 struct GNUNET_RECLAIM_Operation *
-GNUNET_RECLAIM_attestation_store (
+GNUNET_RECLAIM_credential_store (
   struct GNUNET_RECLAIM_Handle *h,
   const struct GNUNET_CRYPTO_EcdsaPrivateKey *pkey,
-  const struct GNUNET_RECLAIM_Attestation *attr,
+  const struct GNUNET_RECLAIM_Credential *attr,
   const struct GNUNET_TIME_Relative *exp_interval,
   GNUNET_RECLAIM_ContinuationWithStatus cont,
   void *cont_cls)
@@ -1204,15 +1242,15 @@ GNUNET_RECLAIM_attestation_store (
   op->cls = cont_cls;
   op->r_id = h->r_id_gen++;
   GNUNET_CONTAINER_DLL_insert_tail (h->op_head, h->op_tail, op);
-  attr_len = GNUNET_RECLAIM_attestation_serialize_get_size (attr);
+  attr_len = GNUNET_RECLAIM_credential_serialize_get_size (attr);
   op->env = GNUNET_MQ_msg_extra (sam,
                                  attr_len,
-                                 GNUNET_MESSAGE_TYPE_RECLAIM_ATTESTATION_STORE);
+                                 GNUNET_MESSAGE_TYPE_RECLAIM_CREDENTIAL_STORE);
   sam->identity = *pkey;
   sam->id = htonl (op->r_id);
   sam->exp = GNUNET_htonll (exp_interval->rel_value_us);
 
-  GNUNET_RECLAIM_attestation_serialize (attr, (char *) &sam[1]);
+  GNUNET_RECLAIM_credential_serialize (attr, (char *) &sam[1]);
 
   sam->attr_len = htons (attr_len);
   if (NULL != h->mq)
@@ -1222,21 +1260,21 @@ GNUNET_RECLAIM_attestation_store (
 
 
 /**
-   * Delete an attestation. Tickets used to share this attestation are updated
+   * Delete an credential. Tickets used to share this credential are updated
    * accordingly.
    *
    * @param h handle to the re:claimID service
    * @param pkey Private key of the identity to add an attribute to
-   * @param attr The attestation
+   * @param attr The credential
    * @param cont Continuation to call when done
    * @param cont_cls Closure for @a cont
    * @return handle Used to to abort the request
    */
 struct GNUNET_RECLAIM_Operation *
-GNUNET_RECLAIM_attestation_delete (
+GNUNET_RECLAIM_credential_delete (
   struct GNUNET_RECLAIM_Handle *h,
   const struct GNUNET_CRYPTO_EcdsaPrivateKey *pkey,
-  const struct GNUNET_RECLAIM_Attestation *attr,
+  const struct GNUNET_RECLAIM_Credential *attr,
   GNUNET_RECLAIM_ContinuationWithStatus cont,
   void *cont_cls)
 {
@@ -1250,13 +1288,13 @@ GNUNET_RECLAIM_attestation_delete (
   op->cls = cont_cls;
   op->r_id = h->r_id_gen++;
   GNUNET_CONTAINER_DLL_insert_tail (h->op_head, h->op_tail, op);
-  attr_len = GNUNET_RECLAIM_attestation_serialize_get_size (attr);
+  attr_len = GNUNET_RECLAIM_credential_serialize_get_size (attr);
   op->env = GNUNET_MQ_msg_extra (dam,
                                  attr_len,
-                                 GNUNET_MESSAGE_TYPE_RECLAIM_ATTESTATION_DELETE);
+                                 GNUNET_MESSAGE_TYPE_RECLAIM_CREDENTIAL_DELETE);
   dam->identity = *pkey;
   dam->id = htonl (op->r_id);
-  GNUNET_RECLAIM_attestation_serialize (attr, (char *) &dam[1]);
+  GNUNET_RECLAIM_credential_serialize (attr, (char *) &dam[1]);
 
   dam->attr_len = htons (attr_len);
   if (NULL != h->mq)
@@ -1375,12 +1413,12 @@ GNUNET_RECLAIM_get_attributes_stop (struct GNUNET_RECLAIM_AttributeIterator *it)
 
 
 /**
- * List all attestations for a local identity.
+ * List all credentials for a local identity.
  * This MUST lock the `struct GNUNET_RECLAIM_Handle`
- * for any other calls than #GNUNET_RECLAIM_get_attestations_next() and
- * #GNUNET_RECLAIM_get_attestations_stop. @a proc will be called once
+ * for any other calls than #GNUNET_RECLAIM_get_credentials_next() and
+ * #GNUNET_RECLAIM_get_credentials_stop. @a proc will be called once
  * immediately, and then again after
- * #GNUNET_RECLAIM_get_attestations_next() is invoked.
+ * #GNUNET_RECLAIM_get_credentials_next() is invoked.
  *
  * On error (disconnect), @a error_cb will be invoked.
  * On normal completion, @a finish_cb proc will be
@@ -1391,31 +1429,31 @@ GNUNET_RECLAIM_get_attributes_stop (struct GNUNET_RECLAIM_AttributeIterator *it)
  * @param error_cb Function to call on error (i.e. disconnect),
  *        the handle is afterwards invalid
  * @param error_cb_cls Closure for @a error_cb
- * @param proc Function to call on each attestation
+ * @param proc Function to call on each credential
  * @param proc_cls Closure for @a proc
  * @param finish_cb Function to call on completion
  *        the handle is afterwards invalid
  * @param finish_cb_cls Closure for @a finish_cb
  * @return an iterator Handle to use for iteration
  */
-struct GNUNET_RECLAIM_AttestationIterator *
-GNUNET_RECLAIM_get_attestations_start (
+struct GNUNET_RECLAIM_CredentialIterator *
+GNUNET_RECLAIM_get_credentials_start (
   struct GNUNET_RECLAIM_Handle *h,
   const struct GNUNET_CRYPTO_EcdsaPrivateKey *identity,
   GNUNET_SCHEDULER_TaskCallback error_cb,
   void *error_cb_cls,
-  GNUNET_RECLAIM_AttestationResult proc,
+  GNUNET_RECLAIM_CredentialResult proc,
   void *proc_cls,
   GNUNET_SCHEDULER_TaskCallback finish_cb,
   void *finish_cb_cls)
 {
-  struct GNUNET_RECLAIM_AttestationIterator *ait;
+  struct GNUNET_RECLAIM_CredentialIterator *ait;
   struct GNUNET_MQ_Envelope *env;
-  struct AttestationIterationStartMessage *msg;
+  struct CredentialIterationStartMessage *msg;
   uint32_t rid;
 
   rid = h->r_id_gen++;
-  ait = GNUNET_new (struct GNUNET_RECLAIM_AttestationIterator);
+  ait = GNUNET_new (struct GNUNET_RECLAIM_CredentialIterator);
   ait->h = h;
   ait->error_cb = error_cb;
   ait->error_cb_cls = error_cb_cls;
@@ -1428,7 +1466,7 @@ GNUNET_RECLAIM_get_attestations_start (
   GNUNET_CONTAINER_DLL_insert_tail (h->ait_head, h->ait_tail, ait);
   env =
     GNUNET_MQ_msg (msg,
-                   GNUNET_MESSAGE_TYPE_RECLAIM_ATTESTATION_ITERATION_START);
+                   GNUNET_MESSAGE_TYPE_RECLAIM_CREDENTIAL_ITERATION_START);
   msg->id = htonl (rid);
   msg->identity = *identity;
   if (NULL == h->mq)
@@ -1440,21 +1478,21 @@ GNUNET_RECLAIM_get_attestations_start (
 
 
 /**
- * Calls the record processor specified in #GNUNET_RECLAIM_get_attestation_start
+ * Calls the record processor specified in #GNUNET_RECLAIM_get_credential_start
  * for the next record.
  *
  * @param it the iterator
  */
 void
-GNUNET_RECLAIM_get_attestations_next (struct
-                                      GNUNET_RECLAIM_AttestationIterator *ait)
+GNUNET_RECLAIM_get_credentials_next (struct
+                                      GNUNET_RECLAIM_CredentialIterator *ait)
 {
   struct GNUNET_RECLAIM_Handle *h = ait->h;
-  struct AttestationIterationNextMessage *msg;
+  struct CredentialIterationNextMessage *msg;
   struct GNUNET_MQ_Envelope *env;
 
   env =
-    GNUNET_MQ_msg (msg, GNUNET_MESSAGE_TYPE_RECLAIM_ATTESTATION_ITERATION_NEXT);
+    GNUNET_MQ_msg (msg, GNUNET_MESSAGE_TYPE_RECLAIM_CREDENTIAL_ITERATION_NEXT);
   msg->id = htonl (ait->r_id);
   GNUNET_MQ_send (h->mq, env);
 }
@@ -1468,18 +1506,18 @@ GNUNET_RECLAIM_get_attestations_next (struct
  * @param it the iterator
  */
 void
-GNUNET_RECLAIM_get_attestations_stop (struct
-                                      GNUNET_RECLAIM_AttestationIterator *ait)
+GNUNET_RECLAIM_get_credentials_stop (struct
+                                      GNUNET_RECLAIM_CredentialIterator *ait)
 {
   struct GNUNET_RECLAIM_Handle *h = ait->h;
   struct GNUNET_MQ_Envelope *env;
-  struct AttestationIterationStopMessage *msg;
+  struct CredentialIterationStopMessage *msg;
 
   if (NULL != h->mq)
   {
     env =
       GNUNET_MQ_msg (msg,
-                     GNUNET_MESSAGE_TYPE_RECLAIM_ATTESTATION_ITERATION_STOP);
+                     GNUNET_MESSAGE_TYPE_RECLAIM_CREDENTIAL_ITERATION_STOP);
     msg->id = htonl (ait->r_id);
     GNUNET_MQ_send (h->mq, env);
   }
@@ -1506,7 +1544,7 @@ GNUNET_RECLAIM_ticket_issue (
   const struct GNUNET_CRYPTO_EcdsaPrivateKey *iss,
   const struct GNUNET_CRYPTO_EcdsaPublicKey *rp,
   const struct GNUNET_RECLAIM_AttributeList *attrs,
-  GNUNET_RECLAIM_TicketCallback cb,
+  GNUNET_RECLAIM_IssueTicketCallback cb,
   void *cb_cls)
 {
   struct GNUNET_RECLAIM_Operation *op;
@@ -1516,7 +1554,7 @@ GNUNET_RECLAIM_ticket_issue (
   fprintf (stderr, "Issuing ticket\n");
   op = GNUNET_new (struct GNUNET_RECLAIM_Operation);
   op->h = h;
-  op->tr_cb = cb;
+  op->ti_cb = cb;
   op->cls = cb_cls;
   op->r_id = h->r_id_gen++;
   GNUNET_CONTAINER_DLL_insert_tail (h->op_head, h->op_tail, op);
@@ -1572,6 +1610,8 @@ GNUNET_RECLAIM_ticket_consume (
   ctm->ticket = *ticket;
   if (NULL != h->mq)
     GNUNET_MQ_send_copy (h->mq, op->env);
+  else
+    reconnect (h);
   return op;
 }
 
diff --git a/src/reclaim/reclaim_attribute.c b/src/reclaim/reclaim_attribute.c
index 69c5351d3c77a95602c232955b5734ef9092bde3..2217987acd6b1778e7b0a908b7918719009b03ab 100644
--- a/src/reclaim/reclaim_attribute.c
+++ b/src/reclaim/reclaim_attribute.c
@@ -222,7 +222,7 @@ GNUNET_RECLAIM_attribute_value_to_string (uint32_t type,
  * Create a new attribute.
  *
  * @param attr_name the attribute name
- * @param attestation attestation ID of the attribute (maybe NULL)
+ * @param credential credential ID of the attribute (maybe NULL)
  * @param type the attribute type
  * @param data the attribute value
  * @param data_size the attribute value size
@@ -230,7 +230,8 @@ GNUNET_RECLAIM_attribute_value_to_string (uint32_t type,
  */
 struct GNUNET_RECLAIM_Attribute *
 GNUNET_RECLAIM_attribute_new (const char *attr_name,
-                              const struct GNUNET_RECLAIM_Identifier *attestation,
+                              const struct
+                              GNUNET_RECLAIM_Identifier *credential,
                               uint32_t type,
                               const void *data,
                               size_t data_size)
@@ -243,8 +244,8 @@ GNUNET_RECLAIM_attribute_new (const char *attr_name,
 
   attr = GNUNET_malloc (sizeof(struct GNUNET_RECLAIM_Attribute)
                         + strlen (attr_name_tmp) + 1 + data_size);
-  if (NULL != attestation)
-    attr->attestation = *attestation;
+  if (NULL != credential)
+    attr->credential = *credential;
   attr->type = type;
   attr->data_size = data_size;
   attr->flag = 0;
@@ -271,7 +272,7 @@ void
 GNUNET_RECLAIM_attribute_list_add (
   struct GNUNET_RECLAIM_AttributeList *al,
   const char *attr_name,
-  const struct GNUNET_RECLAIM_Identifier *attestation,
+  const struct GNUNET_RECLAIM_Identifier *credential,
   uint32_t type,
   const void *data,
   size_t data_size)
@@ -280,7 +281,7 @@ GNUNET_RECLAIM_attribute_list_add (
 
   ale = GNUNET_new (struct GNUNET_RECLAIM_AttributeListEntry);
   ale->attribute =
-    GNUNET_RECLAIM_attribute_new (attr_name, attestation,
+    GNUNET_RECLAIM_attribute_new (attr_name, credential,
                                   type, data, data_size);
   GNUNET_CONTAINER_DLL_insert (al->list_head,
                                al->list_tail,
@@ -305,7 +306,6 @@ GNUNET_RECLAIM_attribute_list_serialize_get_size (
   {
     GNUNET_assert (NULL != ale->attribute);
     len += GNUNET_RECLAIM_attribute_serialize_get_size (ale->attribute);
-    len += sizeof(struct GNUNET_RECLAIM_AttributeListEntry);
   }
   return len;
 }
@@ -354,27 +354,28 @@ GNUNET_RECLAIM_attribute_list_deserialize (const char *data, size_t data_size)
   struct GNUNET_RECLAIM_AttributeListEntry *ale;
   size_t attr_len;
   const char *read_ptr;
+  size_t left = data_size;
 
   al = GNUNET_new (struct GNUNET_RECLAIM_AttributeList);
-  if (data_size < sizeof(struct Attribute) + sizeof(struct
-                                                    GNUNET_RECLAIM_AttributeListEntry))
+  if (data_size < sizeof(struct Attribute))
     return al;
   read_ptr = data;
-  while (((data + data_size) - read_ptr) >= sizeof(struct Attribute))
+  while (left >= sizeof(struct Attribute))
   {
     ale = GNUNET_new (struct GNUNET_RECLAIM_AttributeListEntry);
-    ale->attribute =
+    attr_len =
       GNUNET_RECLAIM_attribute_deserialize (read_ptr,
-                                            data_size - (read_ptr - data));
-    if (NULL == ale->attribute)
+                                            left,
+                                            &ale->attribute);
+    if (-1 == attr_len)
     {
       GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
                   "Failed to deserialize malformed attribute.\n");
       GNUNET_free (ale);
       return al;
     }
+    left -= attr_len;
     GNUNET_CONTAINER_DLL_insert (al->list_head, al->list_tail, ale);
-    attr_len = GNUNET_RECLAIM_attribute_serialize_get_size (ale->attribute);
     read_ptr += attr_len;
   }
   return al;
@@ -402,7 +403,7 @@ GNUNET_RECLAIM_attribute_list_dup (
     {
       result_ale->attribute =
         GNUNET_RECLAIM_attribute_new (ale->attribute->name,
-                                      &ale->attribute->attestation,
+                                      &ale->attribute->credential,
                                       ale->attribute->type,
                                       ale->attribute->data,
                                       ale->attribute->data_size);
@@ -477,7 +478,7 @@ GNUNET_RECLAIM_attribute_serialize (
   attr_ser->attribute_type = htons (attr->type);
   attr_ser->attribute_flag = htonl (attr->flag);
   attr_ser->attribute_id = attr->id;
-  attr_ser->attestation_id = attr->attestation;
+  attr_ser->credential_id = attr->credential;
   name_len = strlen (attr->name);
   attr_ser->name_len = htons (name_len);
   write_ptr = (char *) &attr_ser[1];
@@ -502,17 +503,18 @@ GNUNET_RECLAIM_attribute_serialize (
  *
  * @return a GNUNET_IDENTITY_PROVIDER_Attribute, must be free'd by caller
  */
-struct GNUNET_RECLAIM_Attribute *
-GNUNET_RECLAIM_attribute_deserialize (const char *data, size_t data_size)
+ssize_t
+GNUNET_RECLAIM_attribute_deserialize (const char *data, size_t data_size,
+                                      struct GNUNET_RECLAIM_Attribute **attr)
 {
-  struct GNUNET_RECLAIM_Attribute *attr;
   struct Attribute *attr_ser;
+  struct GNUNET_RECLAIM_Attribute *attribute;
   size_t data_len;
   size_t name_len;
   char *write_ptr;
 
   if (data_size < sizeof(struct Attribute))
-    return NULL;
+    return -1;
 
   attr_ser = (struct Attribute *) data;
   data_len = ntohs (attr_ser->data_size);
@@ -521,25 +523,27 @@ GNUNET_RECLAIM_attribute_deserialize (const char *data, size_t data_size)
   {
     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
                 "Buffer too small to deserialize\n");
-    return NULL;
+    return -1;
   }
-  attr = GNUNET_malloc (sizeof(struct GNUNET_RECLAIM_Attribute)
+  attribute = GNUNET_malloc (sizeof(struct GNUNET_RECLAIM_Attribute)
                         + data_len + name_len + 1);
-  attr->type = ntohs (attr_ser->attribute_type);
-  attr->flag = ntohl (attr_ser->attribute_flag);
-  attr->id = attr_ser->attribute_id;
-  attr->attestation = attr_ser->attestation_id;
-  attr->data_size = data_len;
+  attribute->type = ntohs (attr_ser->attribute_type);
+  attribute->flag = ntohl (attr_ser->attribute_flag);
+  attribute->id = attr_ser->attribute_id;
+  attribute->credential = attr_ser->credential_id;
+  attribute->data_size = data_len;
 
-  write_ptr = (char *) &attr[1];
+  write_ptr = (char *) &attribute[1];
   GNUNET_memcpy (write_ptr, &attr_ser[1], name_len);
   write_ptr[name_len] = '\0';
-  attr->name = write_ptr;
+  attribute->name = write_ptr;
 
   write_ptr += name_len + 1;
-  GNUNET_memcpy (write_ptr, (char *) &attr_ser[1] + name_len, attr->data_size);
-  attr->data = write_ptr;
-  return attr;
+  GNUNET_memcpy (write_ptr, (char *) &attr_ser[1] + name_len,
+                attribute->data_size);
+  *attr = attribute;
+  attribute->data = write_ptr;
+  return sizeof(struct Attribute) + data_len + name_len;
 }
 
 
diff --git a/src/reclaim/reclaim_attribute.h b/src/reclaim/reclaim_attribute.h
index e54b210b90e7f0e29f56369e4a3091fb86db796e..285d75d8387df3eb987dc59644a63a633d18f452 100644
--- a/src/reclaim/reclaim_attribute.h
+++ b/src/reclaim/reclaim_attribute.h
@@ -28,6 +28,8 @@
 
 #include "gnunet_reclaim_service.h"
 
+GNUNET_NETWORK_STRUCT_BEGIN
+
 /**
  * Serialized claim
  */
@@ -36,12 +38,12 @@ struct Attribute
   /**
    * Attribute type
    */
-  uint32_t attribute_type;
+  uint32_t attribute_type GNUNET_PACKED;
 
   /**
    * Attribute flag
    */
-  uint32_t attribute_flag;
+  uint32_t attribute_flag GNUNET_PACKED;
 
   /**
    * Attribute ID
@@ -49,54 +51,23 @@ struct Attribute
   struct GNUNET_RECLAIM_Identifier attribute_id;
 
   /**
-   * Attestation ID
+   * Credential ID
    */
-  struct GNUNET_RECLAIM_Identifier attestation_id;
+  struct GNUNET_RECLAIM_Identifier credential_id;
 
   /**
    * Name length
    */
-  uint32_t name_len;
+  uint32_t name_len GNUNET_PACKED;
 
   /**
    * Data size
    */
-  uint32_t data_size;
+  uint32_t data_size GNUNET_PACKED;
 
   // followed by data_size Attribute value data
 };
 
-/**
- * Serialized attestation claim
- */
-struct Attestation
-{
-  /**
-   * Attestation type
-   */
-  uint32_t attestation_type;
-
-  /**
-   * Attestation flag
-   */
-  uint32_t attestation_flag;
-
-  /**
-   * Attestation ID
-   */
-  struct GNUNET_RECLAIM_Identifier attestation_id;
-
-  /**
-   * Name length
-   */
-  uint32_t name_len;
-
-  /**
-   * Data size
-   */
-  uint32_t data_size;
-
-  // followed by data_size Attestation value data
-};
+GNUNET_NETWORK_STRUCT_BEGIN
 
 #endif
diff --git a/src/reclaim/reclaim_credential.c b/src/reclaim/reclaim_credential.c
new file mode 100644
index 0000000000000000000000000000000000000000..5c897440014f2ae4c10f261984c1709f051245ee
--- /dev/null
+++ b/src/reclaim/reclaim_credential.c
@@ -0,0 +1,1037 @@
+/*
+   This file is part of GNUnet
+   Copyright (C) 2010-2015 GNUnet e.V.
+
+   GNUnet is free software: you can redistribute it and/or modify it
+   under the terms of the GNU Affero General Public License as published
+   by the Free Software Foundation, either version 3 of the License,
+   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
+   Affero General Public License for more details.
+
+   You should have received a copy of the GNU Affero General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+   SPDX-License-Identifier: AGPL3.0-or-later
+ */
+
+/**
+ * @file reclaim/reclaim_credential.c
+ * @brief helper library to manage identity attribute credentials
+ * @author Martin Schanzenbach
+ */
+#include "platform.h"
+#include "gnunet_util_lib.h"
+#include "gnunet_reclaim_plugin.h"
+#include "reclaim_credential.h"
+
+
+/**
+ * Handle for a plugin
+ */
+struct Plugin
+{
+  /**
+   * Name of the plugin
+   */
+  char *library_name;
+
+  /**
+   * Plugin API
+   */
+  struct GNUNET_RECLAIM_CredentialPluginFunctions *api;
+};
+
+
+/**
+ * Plugins
+ */
+static struct Plugin **credential_plugins;
+
+
+/**
+ * Number of plugins
+ */
+static unsigned int num_plugins;
+
+
+/**
+ * Init canary
+ */
+static int initialized;
+
+
+/**
+ * Add a plugin
+ *
+ * @param cls closure
+ * @param library_name name of the API library
+ * @param lib_ret the plugin API pointer
+ */
+static void
+add_plugin (void *cls, const char *library_name, void *lib_ret)
+{
+  struct GNUNET_RECLAIM_CredentialPluginFunctions *api = lib_ret;
+  struct Plugin *plugin;
+
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "Loading credential plugin `%s'\n",
+              library_name);
+  plugin = GNUNET_new (struct Plugin);
+  plugin->api = api;
+  plugin->library_name = GNUNET_strdup (library_name);
+  GNUNET_array_append (credential_plugins, num_plugins, plugin);
+}
+
+
+/**
+ * Load plugins
+ */
+static void
+init ()
+{
+  if (GNUNET_YES == initialized)
+    return;
+  initialized = GNUNET_YES;
+  GNUNET_PLUGIN_load_all ("libgnunet_plugin_reclaim_credential_",
+                          NULL,
+                          &add_plugin,
+                          NULL);
+}
+
+
+/**
+ * Convert an credential type name to the corresponding number
+ *
+ * @param typename name to convert
+ * @return corresponding number, UINT32_MAX on error
+ */
+uint32_t
+GNUNET_RECLAIM_credential_typename_to_number (const char *typename)
+{
+  unsigned int i;
+  struct Plugin *plugin;
+  uint32_t ret;
+  init ();
+  for (i = 0; i < num_plugins; i++)
+  {
+    plugin = credential_plugins[i];
+    if (UINT32_MAX !=
+        (ret = plugin->api->typename_to_number (plugin->api->cls,
+                                                typename)))
+      return ret;
+  }
+  return UINT32_MAX;
+}
+
+
+/**
+ * Convert an credential type number to the corresponding credential type string
+ *
+ * @param type number of a type
+ * @return corresponding typestring, NULL on error
+ */
+const char *
+GNUNET_RECLAIM_credential_number_to_typename (uint32_t type)
+{
+  unsigned int i;
+  struct Plugin *plugin;
+  const char *ret;
+
+  init ();
+  for (i = 0; i < num_plugins; i++)
+  {
+    plugin = credential_plugins[i];
+    if (NULL !=
+        (ret = plugin->api->number_to_typename (plugin->api->cls, type)))
+      return ret;
+  }
+  return NULL;
+}
+
+
+/**
+ * Convert human-readable version of a 'claim' of an credential to the binary
+ * representation
+ *
+ * @param type type of the claim
+ * @param s human-readable string
+ * @param data set to value in binary encoding (will be allocated)
+ * @param data_size set to number of bytes in @a data
+ * @return #GNUNET_OK on success
+ */
+int
+GNUNET_RECLAIM_credential_string_to_value (uint32_t type,
+                                           const char *s,
+                                           void **data,
+                                           size_t *data_size)
+{
+  unsigned int i;
+  struct Plugin *plugin;
+
+  init ();
+  for (i = 0; i < num_plugins; i++)
+  {
+    plugin = credential_plugins[i];
+    if (GNUNET_OK == plugin->api->string_to_value (plugin->api->cls,
+                                                   type,
+                                                   s,
+                                                   data,
+                                                   data_size))
+      return GNUNET_OK;
+  }
+  return GNUNET_SYSERR;
+}
+
+
+/**
+ * Convert the 'claim' of an credential to a string
+ *
+ * @param type the type of credential
+ * @param data claim in binary encoding
+ * @param data_size number of bytes in @a data
+ * @return NULL on error, otherwise human-readable representation of the claim
+ */
+char *
+GNUNET_RECLAIM_credential_value_to_string (uint32_t type,
+                                           const void *data,
+                                           size_t data_size)
+{
+  unsigned int i;
+  struct Plugin *plugin;
+  char *ret;
+
+  init ();
+  for (i = 0; i < num_plugins; i++)
+  {
+    plugin = credential_plugins[i];
+    if (NULL != (ret = plugin->api->value_to_string (plugin->api->cls,
+                                                     type,
+                                                     data,
+                                                     data_size)))
+      return ret;
+  }
+  return NULL;
+}
+
+
+/**
+   * Create a new credential.
+   *
+   * @param attr_name the credential name
+   * @param type the credential type
+   * @param data the credential value
+   * @param data_size the credential value size
+   * @return the new credential
+   */
+struct GNUNET_RECLAIM_Credential *
+GNUNET_RECLAIM_credential_new (const char *attr_name,
+                               uint32_t type,
+                               const void *data,
+                               size_t data_size)
+{
+  struct GNUNET_RECLAIM_Credential *attr;
+  char *write_ptr;
+  char *attr_name_tmp = GNUNET_strdup (attr_name);
+
+  GNUNET_STRINGS_utf8_tolower (attr_name, attr_name_tmp);
+
+  attr = GNUNET_malloc (sizeof(struct GNUNET_RECLAIM_Credential)
+                        + strlen (attr_name_tmp) + 1 + data_size);
+  attr->type = type;
+  attr->data_size = data_size;
+  attr->flag = 0;
+  write_ptr = (char *) &attr[1];
+  GNUNET_memcpy (write_ptr, attr_name_tmp, strlen (attr_name_tmp) + 1);
+  attr->name = write_ptr;
+  write_ptr += strlen (attr->name) + 1;
+  GNUNET_memcpy (write_ptr, data, data_size);
+  attr->data = write_ptr;
+  GNUNET_free (attr_name_tmp);
+  return attr;
+}
+
+
+/**
+ * Get required size for serialization buffer
+ *
+ * @param attrs the attribute list to serialize
+ * @return the required buffer size
+ */
+size_t
+GNUNET_RECLAIM_credential_list_serialize_get_size (
+  const struct GNUNET_RECLAIM_CredentialList *credentials)
+{
+  struct GNUNET_RECLAIM_CredentialListEntry *le;
+  size_t len = 0;
+
+  for (le = credentials->list_head; NULL != le; le = le->next)
+  {
+    GNUNET_assert (NULL != le->credential);
+    len += GNUNET_RECLAIM_credential_serialize_get_size (le->credential);
+    len += sizeof(struct GNUNET_RECLAIM_CredentialListEntry);
+  }
+  return len;
+}
+
+
+/**
+ * Serialize an attribute list
+ *
+ * @param attrs the attribute list to serialize
+ * @param result the serialized attribute
+ * @return length of serialized data
+ */
+size_t
+GNUNET_RECLAIM_credential_list_serialize (
+  const struct GNUNET_RECLAIM_CredentialList *credentials,
+  char *result)
+{
+  struct GNUNET_RECLAIM_CredentialListEntry *le;
+  size_t len;
+  size_t total_len;
+  char *write_ptr;
+  write_ptr = result;
+  total_len = 0;
+  for (le = credentials->list_head; NULL != le; le = le->next)
+  {
+    GNUNET_assert (NULL != le->credential);
+    len = GNUNET_RECLAIM_credential_serialize (le->credential, write_ptr);
+    total_len += len;
+    write_ptr += len;
+  }
+  return total_len;
+}
+
+
+/**
+ * Deserialize an credential list
+ *
+ * @param data the serialized attribute list
+ * @param data_size the length of the serialized data
+ * @return a GNUNET_IDENTITY_PROVIDER_AttributeList, must be free'd by caller
+ */
+struct GNUNET_RECLAIM_CredentialList *
+GNUNET_RECLAIM_credential_list_deserialize (const char *data, size_t data_size)
+{
+  struct GNUNET_RECLAIM_CredentialList *al;
+  struct GNUNET_RECLAIM_CredentialListEntry *ale;
+  size_t att_len;
+  const char *read_ptr;
+
+  al = GNUNET_new (struct GNUNET_RECLAIM_CredentialList);
+
+  if ((data_size < sizeof(struct
+                          Credential)
+       + sizeof(struct GNUNET_RECLAIM_CredentialListEntry)))
+    return al;
+
+  read_ptr = data;
+  while (((data + data_size) - read_ptr) >= sizeof(struct Credential))
+  {
+    ale = GNUNET_new (struct GNUNET_RECLAIM_CredentialListEntry);
+    ale->credential =
+      GNUNET_RECLAIM_credential_deserialize (read_ptr,
+                                             data_size - (read_ptr - data));
+    if (NULL == ale->credential)
+    {
+      GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+                  "Failed to deserialize malformed credential.\n");
+      GNUNET_free (ale);
+      return al;
+    }
+    GNUNET_CONTAINER_DLL_insert (al->list_head, al->list_tail, ale);
+    att_len = GNUNET_RECLAIM_credential_serialize_get_size (ale->credential);
+    read_ptr += att_len;
+  }
+  return al;
+}
+
+
+/**
+ * Make a (deep) copy of the credential list
+ * @param attrs claim list to copy
+ * @return copied claim list
+ */
+struct GNUNET_RECLAIM_CredentialList *
+GNUNET_RECLAIM_credential_list_dup (
+  const struct GNUNET_RECLAIM_CredentialList *al)
+{
+  struct GNUNET_RECLAIM_CredentialListEntry *ale;
+  struct GNUNET_RECLAIM_CredentialListEntry *result_ale;
+  struct GNUNET_RECLAIM_CredentialList *result;
+
+  result = GNUNET_new (struct GNUNET_RECLAIM_CredentialList);
+  for (ale = al->list_head; NULL != ale; ale = ale->next)
+  {
+    result_ale = GNUNET_new (struct GNUNET_RECLAIM_CredentialListEntry);
+    GNUNET_assert (NULL != ale->credential);
+    result_ale->credential =
+      GNUNET_RECLAIM_credential_new (ale->credential->name,
+                                     ale->credential->type,
+                                     ale->credential->data,
+                                     ale->credential->data_size);
+    result_ale->credential->id = ale->credential->id;
+    GNUNET_CONTAINER_DLL_insert (result->list_head,
+                                 result->list_tail,
+                                 result_ale);
+  }
+  return result;
+}
+
+
+/**
+ * Destroy credential list
+ *
+ * @param attrs list to destroy
+ */
+void
+GNUNET_RECLAIM_credential_list_destroy (
+  struct GNUNET_RECLAIM_CredentialList *al)
+{
+  struct GNUNET_RECLAIM_CredentialListEntry *ale;
+  struct GNUNET_RECLAIM_CredentialListEntry *tmp_ale;
+
+  for (ale = al->list_head; NULL != ale;)
+  {
+    if (NULL != ale->credential)
+      GNUNET_free (ale->credential);
+    tmp_ale = ale;
+    ale = ale->next;
+    GNUNET_free (tmp_ale);
+  }
+  GNUNET_free (al);
+}
+
+
+/**
+ * Get required size for serialization buffer
+ *
+ * @param attr the credential to serialize
+ * @return the required buffer size
+ */
+size_t
+GNUNET_RECLAIM_credential_serialize_get_size (
+  const struct GNUNET_RECLAIM_Credential *credential)
+{
+  return sizeof(struct Credential) + strlen (credential->name)
+         + credential->data_size;
+}
+
+
+/**
+ * Serialize an credential
+ *
+ * @param attr the credential to serialize
+ * @param result the serialized credential
+ * @return length of serialized data
+ */
+size_t
+GNUNET_RECLAIM_credential_serialize (
+  const struct GNUNET_RECLAIM_Credential *credential,
+  char *result)
+{
+  size_t data_len_ser;
+  size_t name_len;
+  struct Credential *atts;
+  char *write_ptr;
+
+  atts = (struct Credential *) result;
+  atts->credential_type = htons (credential->type);
+  atts->credential_flag = htonl (credential->flag);
+  atts->credential_id = credential->id;
+  name_len = strlen (credential->name);
+  atts->name_len = htons (name_len);
+  write_ptr = (char *) &atts[1];
+  GNUNET_memcpy (write_ptr, credential->name, name_len);
+  write_ptr += name_len;
+  // TODO plugin-ize
+  // data_len_ser = plugin->serialize_attribute_value (attr,
+  //                                                  &attr_ser[1]);
+  data_len_ser = credential->data_size;
+  GNUNET_memcpy (write_ptr, credential->data, credential->data_size);
+  atts->data_size = htons (data_len_ser);
+
+  return sizeof(struct Credential) + strlen (credential->name)
+         + credential->data_size;
+}
+
+
+/**
+ * Deserialize an credential
+ *
+ * @param data the serialized credential
+ * @param data_size the length of the serialized data
+ *
+ * @return a GNUNET_IDENTITY_PROVIDER_Attribute, must be free'd by caller
+ */
+struct GNUNET_RECLAIM_Credential *
+GNUNET_RECLAIM_credential_deserialize (const char *data, size_t data_size)
+{
+  struct GNUNET_RECLAIM_Credential *credential;
+  struct Credential *atts;
+  size_t data_len;
+  size_t name_len;
+  char *write_ptr;
+
+  if (data_size < sizeof(struct Credential))
+    return NULL;
+
+  atts = (struct Credential *) data;
+  data_len = ntohs (atts->data_size);
+  name_len = ntohs (atts->name_len);
+  if (data_size < sizeof(struct Credential) + data_len + name_len)
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                "Buffer too small to deserialize\n");
+    return NULL;
+  }
+  credential = GNUNET_malloc (sizeof(struct GNUNET_RECLAIM_Credential)
+                              + data_len + name_len + 1);
+  credential->type = ntohs (atts->credential_type);
+  credential->flag = ntohl (atts->credential_flag);
+  credential->id = atts->credential_id;
+  credential->data_size = data_len;
+
+  write_ptr = (char *) &credential[1];
+  GNUNET_memcpy (write_ptr, &atts[1], name_len);
+  write_ptr[name_len] = '\0';
+  credential->name = write_ptr;
+
+  write_ptr += name_len + 1;
+  GNUNET_memcpy (write_ptr, (char *) &atts[1] + name_len,
+                 credential->data_size);
+  credential->data = write_ptr;
+  return credential;
+}
+
+
+struct GNUNET_RECLAIM_AttributeList*
+GNUNET_RECLAIM_credential_get_attributes (const struct
+                                          GNUNET_RECLAIM_Credential *credential)
+{
+  unsigned int i;
+  struct Plugin *plugin;
+  struct GNUNET_RECLAIM_AttributeList *ret;
+  init ();
+  for (i = 0; i < num_plugins; i++)
+  {
+    plugin = credential_plugins[i];
+    if (NULL !=
+        (ret = plugin->api->get_attributes (plugin->api->cls,
+                                            credential)))
+      return ret;
+  }
+  return NULL;
+}
+
+
+char*
+GNUNET_RECLAIM_credential_get_issuer (const struct
+                                      GNUNET_RECLAIM_Credential *credential)
+{
+  unsigned int i;
+  struct Plugin *plugin;
+  char *ret;
+  init ();
+  for (i = 0; i < num_plugins; i++)
+  {
+    plugin = credential_plugins[i];
+    if (NULL !=
+        (ret = plugin->api->get_issuer (plugin->api->cls,
+                                        credential)))
+      return ret;
+  }
+  return NULL;
+}
+
+
+int
+GNUNET_RECLAIM_credential_get_expiration (const struct
+                                          GNUNET_RECLAIM_Credential *credential,
+                                          struct GNUNET_TIME_Absolute*exp)
+{
+  unsigned int i;
+  struct Plugin *plugin;
+  init ();
+  for (i = 0; i < num_plugins; i++)
+  {
+    plugin = credential_plugins[i];
+    if (GNUNET_OK !=  plugin->api->get_expiration (plugin->api->cls,
+                                                   credential,
+                                                   exp))
+      continue;
+    return GNUNET_OK;
+  }
+  return GNUNET_SYSERR;
+}
+
+
+/**
+ * Convert an presentation type name to the corresponding number
+ *
+ * @param typename name to convert
+ * @return corresponding number, UINT32_MAX on error
+ */
+uint32_t
+GNUNET_RECLAIM_presentation_typename_to_number (const char *typename)
+{
+  unsigned int i;
+  struct Plugin *plugin;
+  uint32_t ret;
+  init ();
+  for (i = 0; i < num_plugins; i++)
+  {
+    plugin = credential_plugins[i];
+    if (UINT32_MAX !=
+        (ret = plugin->api->typename_to_number_p (plugin->api->cls,
+                                                  typename)))
+      return ret;
+  }
+  return UINT32_MAX;
+}
+
+
+/**
+ * Convert an presentation type number to the corresponding presentation type string
+ *
+ * @param type number of a type
+ * @return corresponding typestring, NULL on error
+ */
+const char *
+GNUNET_RECLAIM_presentation_number_to_typename (uint32_t type)
+{
+  unsigned int i;
+  struct Plugin *plugin;
+  const char *ret;
+
+  init ();
+  for (i = 0; i < num_plugins; i++)
+  {
+    plugin = credential_plugins[i];
+    if (NULL !=
+        (ret = plugin->api->number_to_typename_p (plugin->api->cls, type)))
+      return ret;
+  }
+  return NULL;
+}
+
+
+/**
+ * Convert human-readable version of a 'claim' of an presentation to the binary
+ * representation
+ *
+ * @param type type of the claim
+ * @param s human-readable string
+ * @param data set to value in binary encoding (will be allocated)
+ * @param data_size set to number of bytes in @a data
+ * @return #GNUNET_OK on success
+ */
+int
+GNUNET_RECLAIM_presentation_string_to_value (uint32_t type,
+                                             const char *s,
+                                             void **data,
+                                             size_t *data_size)
+{
+  unsigned int i;
+  struct Plugin *plugin;
+
+  init ();
+  for (i = 0; i < num_plugins; i++)
+  {
+    plugin = credential_plugins[i];
+    if (GNUNET_OK == plugin->api->string_to_value_p (plugin->api->cls,
+                                                     type,
+                                                     s,
+                                                     data,
+                                                     data_size))
+      return GNUNET_OK;
+  }
+  return GNUNET_SYSERR;
+}
+
+
+/**
+ * Convert the 'claim' of an presentation to a string
+ *
+ * @param type the type of presentation
+ * @param data claim in binary encoding
+ * @param data_size number of bytes in @a data
+ * @return NULL on error, otherwise human-readable representation of the claim
+ */
+char *
+GNUNET_RECLAIM_presentation_value_to_string (uint32_t type,
+                                             const void *data,
+                                             size_t data_size)
+{
+  unsigned int i;
+  struct Plugin *plugin;
+  char *ret;
+
+  init ();
+  for (i = 0; i < num_plugins; i++)
+  {
+    plugin = credential_plugins[i];
+    if (NULL != (ret = plugin->api->value_to_string_p (plugin->api->cls,
+                                                       type,
+                                                       data,
+                                                       data_size)))
+      return ret;
+  }
+  return NULL;
+}
+
+
+struct GNUNET_RECLAIM_Presentation *
+GNUNET_RECLAIM_presentation_new (uint32_t type,
+                                 const void *data,
+                                 size_t data_size)
+{
+  struct GNUNET_RECLAIM_Presentation *attr;
+  char *write_ptr;
+
+  attr = GNUNET_malloc (sizeof(struct GNUNET_RECLAIM_Presentation)
+                        + data_size);
+  attr->type = type;
+  attr->data_size = data_size;
+  write_ptr = (char *) &attr[1];
+  GNUNET_memcpy (write_ptr, data, data_size);
+  attr->data = write_ptr;
+  return attr;
+}
+
+
+/**
+ * Get required size for serialization buffer
+ *
+ * @param attrs the attribute list to serialize
+ * @return the required buffer size
+ */
+size_t
+GNUNET_RECLAIM_presentation_list_serialize_get_size (
+  const struct GNUNET_RECLAIM_PresentationList *presentations)
+{
+  struct GNUNET_RECLAIM_PresentationListEntry *le;
+  size_t len = 0;
+
+  for (le = presentations->list_head; NULL != le; le = le->next)
+  {
+    GNUNET_assert (NULL != le->presentation);
+    len += GNUNET_RECLAIM_presentation_serialize_get_size (le->presentation);
+    len += sizeof(struct GNUNET_RECLAIM_PresentationListEntry);
+  }
+  return len;
+}
+
+
+/**
+ * Serialize an attribute list
+ *
+ * @param attrs the attribute list to serialize
+ * @param result the serialized attribute
+ * @return length of serialized data
+ */
+size_t
+GNUNET_RECLAIM_presentation_list_serialize (
+  const struct GNUNET_RECLAIM_PresentationList *presentations,
+  char *result)
+{
+  struct GNUNET_RECLAIM_PresentationListEntry *le;
+  size_t len;
+  size_t total_len;
+  char *write_ptr;
+  write_ptr = result;
+  total_len = 0;
+  for (le = presentations->list_head; NULL != le; le = le->next)
+  {
+    GNUNET_assert (NULL != le->presentation);
+    len = GNUNET_RECLAIM_presentation_serialize (le->presentation, write_ptr);
+    total_len += len;
+    write_ptr += len;
+  }
+  return total_len;
+}
+
+
+/**
+ * Deserialize an presentation list
+ *
+ * @param data the serialized attribute list
+ * @param data_size the length of the serialized data
+ * @return a GNUNET_IDENTITY_PROVIDER_AttributeList, must be free'd by caller
+ */
+struct GNUNET_RECLAIM_PresentationList *
+GNUNET_RECLAIM_presentation_list_deserialize (const char *data, size_t
+                                              data_size)
+{
+  struct GNUNET_RECLAIM_PresentationList *al;
+  struct GNUNET_RECLAIM_PresentationListEntry *ale;
+  size_t att_len;
+  const char *read_ptr;
+
+  al = GNUNET_new (struct GNUNET_RECLAIM_PresentationList);
+
+  if ((data_size < sizeof(struct Presentation)
+       + sizeof(struct GNUNET_RECLAIM_PresentationListEntry)))
+    return al;
+
+  read_ptr = data;
+  while (((data + data_size) - read_ptr) >= sizeof(struct Presentation))
+  {
+    ale = GNUNET_new (struct GNUNET_RECLAIM_PresentationListEntry);
+    ale->presentation =
+      GNUNET_RECLAIM_presentation_deserialize (read_ptr,
+                                               data_size - (read_ptr - data));
+    if (NULL == ale->presentation)
+    {
+      GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+                  "Failed to deserialize malformed presentation.\n");
+      GNUNET_free (ale);
+      return al;
+    }
+    GNUNET_CONTAINER_DLL_insert (al->list_head, al->list_tail, ale);
+    att_len = GNUNET_RECLAIM_presentation_serialize_get_size (
+      ale->presentation);
+    read_ptr += att_len;
+  }
+  return al;
+}
+
+
+/**
+ * Make a (deep) copy of the presentation list
+ * @param attrs claim list to copy
+ * @return copied claim list
+ */
+struct GNUNET_RECLAIM_PresentationList *
+GNUNET_RECLAIM_presentation_list_dup (
+  const struct GNUNET_RECLAIM_PresentationList *al)
+{
+  struct GNUNET_RECLAIM_PresentationListEntry *ale;
+  struct GNUNET_RECLAIM_PresentationListEntry *result_ale;
+  struct GNUNET_RECLAIM_PresentationList *result;
+
+  result = GNUNET_new (struct GNUNET_RECLAIM_PresentationList);
+  for (ale = al->list_head; NULL != ale; ale = ale->next)
+  {
+    result_ale = GNUNET_new (struct GNUNET_RECLAIM_PresentationListEntry);
+    GNUNET_assert (NULL != ale->presentation);
+    result_ale->presentation =
+      GNUNET_RECLAIM_presentation_new (ale->presentation->type,
+                                       ale->presentation->data,
+                                       ale->presentation->data_size);
+    result_ale->presentation->credential_id = ale->presentation->credential_id;
+    GNUNET_CONTAINER_DLL_insert (result->list_head,
+                                 result->list_tail,
+                                 result_ale);
+  }
+  return result;
+}
+
+
+/**
+ * Destroy presentation list
+ *
+ * @param attrs list to destroy
+ */
+void
+GNUNET_RECLAIM_presentation_list_destroy (
+  struct GNUNET_RECLAIM_PresentationList *al)
+{
+  struct GNUNET_RECLAIM_PresentationListEntry *ale;
+  struct GNUNET_RECLAIM_PresentationListEntry *tmp_ale;
+
+  for (ale = al->list_head; NULL != ale;)
+  {
+    if (NULL != ale->presentation)
+      GNUNET_free (ale->presentation);
+    tmp_ale = ale;
+    ale = ale->next;
+    GNUNET_free (tmp_ale);
+  }
+  GNUNET_free (al);
+}
+
+
+/**
+ * Get required size for serialization buffer
+ *
+ * @param attr the presentation to serialize
+ * @return the required buffer size
+ */
+size_t
+GNUNET_RECLAIM_presentation_serialize_get_size (
+  const struct GNUNET_RECLAIM_Presentation *presentation)
+{
+  return sizeof(struct Presentation) + presentation->data_size;
+}
+
+
+/**
+ * Serialize an presentation
+ *
+ * @param attr the presentation to serialize
+ * @param result the serialized presentation
+ * @return length of serialized data
+ */
+size_t
+GNUNET_RECLAIM_presentation_serialize (
+  const struct GNUNET_RECLAIM_Presentation *presentation,
+  char *result)
+{
+  struct Presentation *atts;
+  char *write_ptr;
+
+  atts = (struct Presentation *) result;
+  atts->presentation_type = htons (presentation->type);
+  atts->credential_id = presentation->credential_id;
+  write_ptr = (char *) &atts[1];
+  GNUNET_memcpy (write_ptr, presentation->data, presentation->data_size);
+  atts->data_size = htons (presentation->data_size);
+
+  return sizeof(struct Presentation) + presentation->data_size;
+}
+
+
+/**
+ * Deserialize an presentation
+ *
+ * @param data the serialized presentation
+ * @param data_size the length of the serialized data
+ *
+ * @return a GNUNET_IDENTITY_PROVIDER_Attribute, must be free'd by caller
+ */
+struct GNUNET_RECLAIM_Presentation *
+GNUNET_RECLAIM_presentation_deserialize (const char *data, size_t data_size)
+{
+  struct GNUNET_RECLAIM_Presentation *presentation;
+  struct Presentation *atts;
+  size_t data_len;
+  char *write_ptr;
+
+  if (data_size < sizeof(struct Presentation))
+    return NULL;
+
+  atts = (struct Presentation *) data;
+  data_len = ntohs (atts->data_size);
+  if (data_size < sizeof(struct Presentation) + data_len)
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                "Buffer too small to deserialize\n");
+    return NULL;
+  }
+  presentation = GNUNET_malloc (sizeof(struct GNUNET_RECLAIM_Presentation)
+                                + data_len);
+  presentation->type = ntohs (atts->presentation_type);
+  presentation->credential_id = atts->credential_id;
+  presentation->data_size = data_len;
+
+  write_ptr = (char *) &presentation[1];
+  GNUNET_memcpy (write_ptr, &atts[1], data_len);
+  presentation->data = write_ptr;
+  return presentation;
+}
+
+
+struct GNUNET_RECLAIM_AttributeList*
+GNUNET_RECLAIM_presentation_get_attributes (const struct
+                                            GNUNET_RECLAIM_Presentation *
+                                            presentation)
+{
+  unsigned int i;
+  struct Plugin *plugin;
+  struct GNUNET_RECLAIM_AttributeList *ret;
+  init ();
+  for (i = 0; i < num_plugins; i++)
+  {
+    plugin = credential_plugins[i];
+    if (NULL !=
+        (ret = plugin->api->get_attributes_p (plugin->api->cls,
+                                              presentation)))
+      return ret;
+  }
+  return NULL;
+}
+
+
+char*
+GNUNET_RECLAIM_presentation_get_issuer (const struct
+                                        GNUNET_RECLAIM_Presentation *
+                                        presentation)
+{
+  unsigned int i;
+  struct Plugin *plugin;
+  char *ret;
+  init ();
+  for (i = 0; i < num_plugins; i++)
+  {
+    plugin = credential_plugins[i];
+    if (NULL !=
+        (ret = plugin->api->get_issuer_p (plugin->api->cls,
+                                          presentation)))
+      return ret;
+  }
+  return NULL;
+}
+
+
+int
+GNUNET_RECLAIM_presentation_get_expiration (const struct
+                                            GNUNET_RECLAIM_Presentation *
+                                            presentation,
+                                            struct GNUNET_TIME_Absolute*exp)
+{
+  unsigned int i;
+  struct Plugin *plugin;
+  init ();
+  for (i = 0; i < num_plugins; i++)
+  {
+    plugin = credential_plugins[i];
+    if (GNUNET_OK !=  plugin->api->get_expiration_p (plugin->api->cls,
+                                                     presentation,
+                                                     exp))
+      continue;
+    return GNUNET_OK;
+  }
+  return GNUNET_SYSERR;
+}
+
+/**
+ * Create a presentation from a credential and a lift of (selected)
+ * attributes in the credential.
+ * FIXME not yet implemented
+ *
+ * @param cred the credential to use
+ * @param attrs the attributes to present from the credential
+ * @return the credential presentation presenting the attributes according
+ *         to the presentation mechanism of the credential
+ *         or NULL on error.
+ */
+int
+GNUNET_RECLAIM_credential_get_presentation (
+                              const struct GNUNET_RECLAIM_Credential *cred,
+                              const struct GNUNET_RECLAIM_AttributeList *attrs,
+                              struct GNUNET_RECLAIM_Presentation **pres)
+{
+  unsigned int i;
+  struct Plugin *plugin;
+  init ();
+  for (i = 0; i < num_plugins; i++)
+  {
+    plugin = credential_plugins[i];
+    if (GNUNET_OK !=  plugin->api->create_presentation (plugin->api->cls,
+                                                        cred,
+                                                        attrs,
+                                                        pres))
+      continue;
+    (*pres)->credential_id = cred->id;
+    return GNUNET_OK;
+  }
+  return GNUNET_SYSERR;
+}
+
+
+
diff --git a/src/reclaim/reclaim_credential.h b/src/reclaim/reclaim_credential.h
new file mode 100644
index 0000000000000000000000000000000000000000..7704ed9682428dfa4edb4d2b5ebe1e0046d7cc0a
--- /dev/null
+++ b/src/reclaim/reclaim_credential.h
@@ -0,0 +1,99 @@
+/*
+   This file is part of GNUnet.
+   Copyright (C) 2012-2015 GNUnet e.V.
+
+   GNUnet is free software: you can redistribute it and/or modify it
+   under the terms of the GNU Affero General Public License as published
+   by the Free Software Foundation, either version 3 of the License,
+   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
+   Affero General Public License for more details.
+
+   You should have received a copy of the GNU Affero General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+   SPDX-License-Identifier: AGPL3.0-or-later
+ */
+/**
+ * @author Martin Schanzenbach
+ * @file reclaim/reclaim_credential.h
+ * @brief GNUnet reclaim identity attribute credentials
+ *
+ */
+#ifndef RECLAIM_CREDENTIAL_H
+#define RECLAIM_CREDENTIAL_H
+
+#include "gnunet_reclaim_service.h"
+
+/**
+ * Serialized credential claim
+ */
+struct Credential
+{
+  /**
+   * Credential type
+   */
+  uint32_t credential_type;
+
+  /**
+   * Credential flag
+   */
+  uint32_t credential_flag;
+
+  /**
+   * Credential ID
+   */
+  struct GNUNET_RECLAIM_Identifier credential_id;
+
+  /**
+   * Name length
+   */
+  uint32_t name_len;
+
+  /**
+   * Data size
+   */
+  uint32_t data_size;
+
+  // followed by data_size Credential value data
+};
+
+
+/**
+ * Serialized presentation claim
+ */
+struct Presentation
+{
+  /**
+   * Presentation type
+   */
+  uint32_t presentation_type;
+
+  /**
+   * Presentation flag
+   */
+  uint32_t presentation_flag;
+
+  /**
+   * Credential ID
+   */
+  struct GNUNET_RECLAIM_Identifier credential_id;
+
+  /**
+   * Name length
+   */
+  uint32_t name_len;
+
+  /**
+   * Data size
+   */
+  uint32_t data_size;
+
+  // followed by data_size Presentation value data
+};
+
+
+#endif
diff --git a/src/reclaim/test_reclaim.sh b/src/reclaim/test_reclaim.sh
new file mode 100755
index 0000000000000000000000000000000000000000..da93b10f7949fc5e59fa11156807decb47996744
--- /dev/null
+++ b/src/reclaim/test_reclaim.sh
@@ -0,0 +1,31 @@
+#!/bin/sh
+#trap "gnunet-arm -e -c test_reclaim_lookup.conf" SIGINT
+
+LOCATION=$(which gnunet-config)
+if [ -z $LOCATION ]
+then
+  LOCATION="gnunet-config"
+fi
+$LOCATION --version 1> /dev/null
+if test $? != 0
+then
+	echo "GNUnet command line tools cannot be found, check environmental variables PATH and GNUNET_PREFIX"
+	exit 77
+fi
+
+rm -rf `gnunet-config -c test_reclaim.conf -s PATHS -o GNUNET_HOME -f`
+
+#  (1) PKEY1.user -> PKEY2.resu.user
+#  (2) PKEY2.resu -> PKEY3
+#  (3) PKEY3.user -> PKEY4
+
+
+which timeout > /dev/null 2>&1 && DO_TIMEOUT="timeout 30"
+
+TEST_ATTR="test"
+gnunet-arm -s -c test_reclaim.conf
+gnunet-identity -C testego -c test_reclaim.conf
+valgrind gnunet-reclaim -e testego -a email -V john@doe.gnu -c test_reclaim.conf
+gnunet-reclaim -e testego -a name -V John -c test_reclaim.conf
+gnunet-reclaim -e testego -D -c test_reclaim.conf
+gnunet-arm -e -c test_reclaim.conf
diff --git a/src/reclaim/test_reclaim_attribute.c b/src/reclaim/test_reclaim_attribute.c
new file mode 100644
index 0000000000000000000000000000000000000000..f71d86b56a58f678371f62358fe173c55821fc40
--- /dev/null
+++ b/src/reclaim/test_reclaim_attribute.c
@@ -0,0 +1,51 @@
+#include "platform.h"
+#include "gnunet_common.h"
+#include "gnunet_reclaim_lib.h"
+#include "gnunet_container_lib.h"
+
+int
+main (int argc, char *argv[])
+{
+  struct GNUNET_RECLAIM_AttributeList *al;
+  struct GNUNET_RECLAIM_AttributeList *al_two;
+  struct GNUNET_RECLAIM_AttributeListEntry *ale;
+  struct GNUNET_RECLAIM_Attribute *attr;
+  char attrname[100];
+  char attrdata[100];
+  size_t ser_len_claimed;
+  size_t ser_len_actual;
+  ssize_t deser_len;
+  char *ser_data;
+  int count = 0;
+
+  al = GNUNET_new (struct GNUNET_RECLAIM_AttributeList);
+  for (int i = 0; i < 12; i++)
+  {
+    memset (attrname, 0, 100);
+    memset (attrdata, 0, 100);
+    sprintf (attrname, "attr%d", i);
+    sprintf (attrdata, "%d", i);
+    ale = GNUNET_new (struct GNUNET_RECLAIM_AttributeListEntry);
+    ale->attribute = GNUNET_RECLAIM_attribute_new (attrname,
+                                                   &GNUNET_RECLAIM_ID_ZERO,
+                                                   GNUNET_RECLAIM_ATTRIBUTE_TYPE_STRING,
+                                                   attrdata,
+                                                   strlen (attrdata));
+    GNUNET_CONTAINER_DLL_insert (al->list_head,
+                                 al->list_tail,
+                                 ale);
+  }
+  ser_len_claimed = GNUNET_RECLAIM_attribute_list_serialize_get_size (al);
+  ser_data = GNUNET_malloc (ser_len_claimed);
+  ser_len_actual = GNUNET_RECLAIM_attribute_list_serialize (al,
+                                                            ser_data);
+  GNUNET_assert (ser_len_claimed == ser_len_actual);
+  al_two = GNUNET_RECLAIM_attribute_list_deserialize (ser_data,
+                                                      ser_len_actual);
+  for (ale = al_two->list_head; NULL != ale; ale = ale->next)
+    count++;
+  GNUNET_assert (12 == count);
+  //GNUNET_assert (-1 != deser_len);
+  GNUNET_free (ser_data);
+  GNUNET_RECLAIM_attribute_list_destroy (al);
+}
diff --git a/src/reclaim/test_reclaim_revoke.sh b/src/reclaim/test_reclaim_revoke.sh
new file mode 100755
index 0000000000000000000000000000000000000000..ffbc7ef2b8fe81bfa949d3be32f462d11489aa72
--- /dev/null
+++ b/src/reclaim/test_reclaim_revoke.sh
@@ -0,0 +1,65 @@
+#!/bin/bash
+trap "gnunet-arm -e -c test_reclaim.conf" SIGINT
+
+LOCATION=$(which gnunet-config)
+if [ -z $LOCATION ]
+then
+  LOCATION="gnunet-config"
+fi
+$LOCATION --version 1> /dev/null
+if test $? != 0
+then
+	echo "GNUnet command line tools cannot be found, check environmental variables PATH and GNUNET_PREFIX"
+	exit 77
+fi
+
+rm -rf `gnunet-config -c test_reclaim.conf -s PATHS -o GNUNET_HOME -f`
+
+#  (1) PKEY1.user -> PKEY2.resu.user
+#  (2) PKEY2.resu -> PKEY3
+#  (3) PKEY3.user -> PKEY4
+
+
+which timeout &> /dev/null && DO_TIMEOUT="timeout 30"
+
+TEST_ATTR="test"
+gnunet-arm -s -c test_reclaim.conf 2&>1 > /dev/null
+gnunet-identity -C alice -c test_reclaim.conf
+gnunet-identity -C bob -c test_reclaim.conf
+gnunet-identity -C eve -c test_reclaim.conf
+ALICE_KEY=$(gnunet-identity -d -e alice -q -c test_reclaim.conf)
+BOB_KEY=$(gnunet-identity -d -e bob -q -c test_reclaim.conf)
+EVE_KEY=$(gnunet-identity -d -e eve -q -c test_reclaim.conf)
+gnunet-reclaim -e alice -E 15s -a email -V john@doe.gnu -c test_reclaim.conf
+gnunet-reclaim -e alice -E 15s -a name -V John -c test_reclaim.conf
+TICKET_BOB=$(gnunet-reclaim -e alice -i "email,name" -r $BOB_KEY -c test_reclaim.conf | awk '{print $1}')
+#gnunet-reclaim -e bob -C $TICKET_BOB -c test_reclaim.conf
+TICKET_EVE=$(gnunet-reclaim -e alice -i "email" -r $EVE_KEY -c test_reclaim.conf | awk '{print $1}')
+gnunet-namestore -z alice -D
+echo "Revoking $TICKET"
+gnunet-reclaim -e alice -R $TICKET_EVE -c test_reclaim.conf
+gnunet-namestore -z alice -D
+sleep 16
+echo "Consuming $TICKET"
+
+gnunet-reclaim -e eve -C $TICKET_EVE -c test_reclaim.conf
+if test $? == 0
+then
+  echo "Eve can still resolve attributes..."
+  gnunet-arm -e -c test_reclaim.conf
+  exit 1
+fi
+
+gnunet-arm -e -c test_reclaim.conf
+gnunet-arm -s -c test_reclaim.conf 2&>1 > /dev/null
+
+gnunet-reclaim -e bob -C $TICKET_BOB -c test_reclaim.conf
+#gnunet-reclaim -e bob -C $TICKET_BOB -c test_reclaim.conf 2&>1 >/dev/null
+if test $? != 0
+then
+  echo "Bob cannot resolve attributes..."
+  gnunet-arm -e -c test_reclaim.conf
+  exit 1
+fi
+
+gnunet-arm -e -c test_reclaim.conf
diff --git a/src/regex/.gitignore b/src/regex/.gitignore
new file mode 100644
index 0000000000000000000000000000000000000000..39dc89c8832ede38056fabd3b26bac826e25775e
--- /dev/null
+++ b/src/regex/.gitignore
@@ -0,0 +1,12 @@
+perf-regex
+gnunet-daemon-regexprofiler
+gnunet-regex-profiler
+gnunet-regex-simulation-profiler
+gnunet-service-regex
+test_graph.dot
+test_regex_api
+test_regex_eval_api
+test_regex_graph_api
+test_regex_integration
+test_regex_iterate_api
+test_regex_proofs
diff --git a/src/regex/perf-data.tar.gz b/src/regex/perf-data.tar.gz
new file mode 100644
index 0000000000000000000000000000000000000000..9e909e58e8016a6bb61c9da4d314033a9eb82a37
Binary files /dev/null and b/src/regex/perf-data.tar.gz differ
diff --git a/src/rest/.gitignore b/src/rest/.gitignore
new file mode 100644
index 0000000000000000000000000000000000000000..07e69218edc758cd2c1d0495c3e23f4851354490
--- /dev/null
+++ b/src/rest/.gitignore
@@ -0,0 +1 @@
+gnunet-rest-server
diff --git a/src/rest/gnunet-rest-server.c b/src/rest/gnunet-rest-server.c
index 875509536682b8a69c399faaddadc2a1f64d6dc6..e6e03b16dd5c1fd6a1f4b1a47f43913de1e7b7f5 100644
--- a/src/rest/gnunet-rest-server.c
+++ b/src/rest/gnunet-rest-server.c
@@ -114,11 +114,6 @@ static struct MHD_Response *failure_response;
  */
 static const struct GNUNET_CONFIGURATION_Handle *cfg;
 
-/**
- * Map of loaded plugins.
- */
-static struct GNUNET_CONTAINER_MultiHashMap *plugin_map;
-
 /**
  * Echo request Origin in CORS
  */
@@ -139,6 +134,38 @@ static char *allow_headers;
  */
 static char *allow_credentials;
 
+/**
+ * Plugin list head
+ */
+static struct PluginListEntry *plugins_head;
+
+/**
+ * Plugin list tail
+ */
+static struct PluginListEntry *plugins_tail;
+
+/**
+ * A plugin list entry
+ */
+struct PluginListEntry
+{
+  /* DLL */
+  struct PluginListEntry *next;
+
+  /* DLL */
+  struct PluginListEntry *prev;
+
+  /**
+   * libname (to cleanup)
+   */
+  char *libname;
+
+  /**
+   * The plugin
+   */
+  struct GNUNET_REST_Plugin *plugin;
+};
+
 /**
  * MHD Connection handle
  */
@@ -148,8 +175,6 @@ struct MhdConnectionHandle
 
   struct MHD_Response *response;
 
-  struct GNUNET_REST_Plugin *plugin;
-
   struct GNUNET_REST_RequestHandle *data_handle;
 
   struct MHD_PostProcessor *pp;
@@ -159,6 +184,47 @@ struct MhdConnectionHandle
   int state;
 };
 
+/**
+ * Accepted requests
+ */
+struct AcceptedRequest
+{
+  /**
+   * DLL
+   */
+  struct AcceptedRequest *next;
+
+  /**
+   * DLL
+   */
+  struct AcceptedRequest *prev;
+
+  /**
+   * Socket
+   */
+  struct GNUNET_NETWORK_Handle *sock;
+
+  /**
+   * Connection
+   */
+  struct MhdConnectionHandle *con_handle;
+
+  /**
+   * State
+   */
+  int socket_with_mhd;
+};
+
+/**
+ * AcceptedRequest list head
+ */
+static struct AcceptedRequest *req_list_head;
+
+/**
+ * AcceptedRequest list tail
+ */
+static struct AcceptedRequest *req_list_tail;
+
 /* ************************* Global helpers ********************* */
 
 
@@ -213,7 +279,6 @@ cleanup_url_map (void *cls, const struct GNUNET_HashCode *key, void *value)
   return GNUNET_YES;
 }
 
-
 static void
 cleanup_handle (struct MhdConnectionHandle *handle)
 {
@@ -243,6 +308,25 @@ cleanup_handle (struct MhdConnectionHandle *handle)
   GNUNET_free (handle);
 }
 
+static void
+cleanup_ar (struct AcceptedRequest *ar)
+{
+  if (NULL != ar->con_handle)
+  {
+    cleanup_handle (ar->con_handle);
+  }
+  if (GNUNET_YES == ar->socket_with_mhd)
+  {
+    GNUNET_NETWORK_socket_free_memory_only_ (ar->sock);
+  } else {
+    GNUNET_NETWORK_socket_close (ar->sock);
+  }
+  ar->sock = NULL;
+  GNUNET_CONTAINER_DLL_remove (req_list_head,
+                               req_list_tail,
+                               ar);
+  GNUNET_free (ar);
+}
 
 static int
 header_iterator (void *cls,
@@ -321,19 +405,24 @@ post_data_iter (void *cls,
     return MHD_YES;
 
   GNUNET_CRYPTO_hash (key, strlen (key), &hkey);
-  GNUNET_asprintf (&val, "%s", data);
-  if (GNUNET_OK != GNUNET_CONTAINER_multihashmap_put (
-        handle->url_param_map,
-        &hkey,
-        val,
-        GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY))
+  val = GNUNET_CONTAINER_multihashmap_get (handle->url_param_map,
+                                           &hkey);
+  if (NULL == val)
   {
-    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                "Could not load add url param '%s'=%s\n",
-                key,
-                data);
-    GNUNET_free (val);
+    val = GNUNET_malloc (65536);
+    if (GNUNET_OK != GNUNET_CONTAINER_multihashmap_put (
+          handle->url_param_map,
+          &hkey,
+          val,
+          GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY))
+    {
+      GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                  "Could not add url param '%s'\n",
+                  key);
+      GNUNET_free (val);
+    }
   }
+  memcpy (val + off, data, size);
   return MHD_YES;
 }
 
@@ -373,41 +462,30 @@ create_response (void *cls,
                  size_t *upload_data_size,
                  void **con_cls)
 {
-  char *plugin_name;
   char *origin;
+  struct AcceptedRequest *ar;
   struct GNUNET_HashCode key;
   struct MhdConnectionHandle *con_handle;
   struct GNUNET_REST_RequestHandle *rest_conndata_handle;
+  struct PluginListEntry *ple;
 
-  con_handle = *con_cls;
+  ar = *con_cls;
+  if (NULL == ar)
+  {
+    GNUNET_break (0);
+    return MHD_NO;
+  }
 
-  if (NULL == *con_cls)
+  if (NULL == ar->con_handle)
   {
     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "New connection %s\n", url);
-    char tmp_url[strlen (url) + 1];
-    strcpy (tmp_url, url);
     con_handle = GNUNET_new (struct MhdConnectionHandle);
     con_handle->con = con;
     con_handle->state = GN_REST_STATE_INIT;
-    *con_cls = con_handle;
-
-    plugin_name = strtok (tmp_url, "/");
-
-    if (NULL != plugin_name)
-    {
-      GNUNET_CRYPTO_hash (plugin_name, strlen (plugin_name), &key);
-
-      con_handle->plugin = GNUNET_CONTAINER_multihashmap_get (plugin_map, &key);
-    }
-    if (NULL == con_handle->plugin)
-    {
-      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Queueing response with MHD\n");
-      GNUNET_free (con_handle);
-      return MHD_queue_response (con, MHD_HTTP_NOT_FOUND, failure_response);
-    }
-
+    ar->con_handle = con_handle;
     return MHD_YES;
   }
+  con_handle = ar->con_handle;
   if (GN_REST_STATE_INIT == con_handle->state)
   {
     rest_conndata_handle = GNUNET_new (struct GNUNET_REST_RequestHandle);
@@ -428,6 +506,7 @@ create_response (void *cls,
                                MHD_HEADER_KIND,
                                (MHD_KeyValueIterator) & header_iterator,
                                rest_conndata_handle);
+
     con_handle->pp = MHD_create_post_processor (con,
                                                 65536,
                                                 &post_data_iter,
@@ -439,9 +518,18 @@ create_response (void *cls,
     MHD_destroy_post_processor (con_handle->pp);
 
     con_handle->state = GN_REST_STATE_PROCESSING;
-    con_handle->plugin->process_request (rest_conndata_handle,
-                                         &plugin_callback,
-                                         con_handle);
+    for (ple = plugins_head; NULL != ple; ple = ple->next)
+    {
+      if (GNUNET_YES == ple->plugin->process_request (rest_conndata_handle,
+                                                      &plugin_callback,
+                                                      con_handle))
+        break; /* Request handled */
+    }
+    if (NULL == ple)
+    {
+      /** Request not handled **/
+      MHD_queue_response (con, MHD_HTTP_NOT_FOUND, failure_response);
+    }
     *upload_data_size = 0;
     run_mhd_now ();
     return MHD_YES;
@@ -452,7 +540,7 @@ create_response (void *cls,
     MHD_suspend_connection (con_handle->con);
     return MHD_YES;
   }
-  MHD_resume_connection (con_handle->con);
+  //MHD_resume_connection (con_handle->con);
   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
               "Queueing response from plugin with MHD\n");
   // Handle Preflights for extensions
@@ -513,7 +601,7 @@ create_response (void *cls,
     MHD_RESULT ret = MHD_queue_response (con,
                                          con_handle->status,
                                          con_handle->response);
-    cleanup_handle (con_handle);
+    //cleanup_handle (con_handle);
     return ret;
   }
 }
@@ -521,27 +609,6 @@ create_response (void *cls,
 
 /* ******************** MHD HTTP setup and event loop ******************** */
 
-/**
- * Function called when MHD decides that we are done with a connection.
- *
- * @param cls NULL
- * @param connection connection handle
- * @param con_cls value as set by the last call to
- *        the MHD_AccessHandlerCallback, should be our handle
- * @param toe reason for request termination (ignored)
- */
-static void
-mhd_completed_cb (void *cls,
-                  struct MHD_Connection *connection,
-                  void **con_cls,
-                  enum MHD_RequestTerminationCode toe)
-{
-  if (MHD_REQUEST_TERMINATED_COMPLETED_OK != toe)
-    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                "MHD encountered error handling request: %d\n",
-                toe);
-}
-
 
 /**
  * Kill the MHD daemon.
@@ -649,6 +716,135 @@ schedule_httpd ()
     GNUNET_NETWORK_fdset_destroy (wws);
 }
 
+/**
+ * Function called when MHD first processes an incoming connection.
+ * Gives us the respective URI information.
+ *
+ * We use this to associate the `struct MHD_Connection` with our
+ * internal `struct AcceptedRequest` data structure (by checking
+ * for matching sockets).
+ *
+ * @param cls the HTTP server handle (a `struct MhdHttpList`)
+ * @param url the URL that is being requested
+ * @param connection MHD connection object for the request
+ * @return the `struct Socks5Request` that this @a connection is for
+ */
+static void *
+mhd_log_callback (void *cls,
+                  const char *url,
+                  struct MHD_Connection *connection)
+{
+  struct AcceptedRequest *ar;
+  const union MHD_ConnectionInfo *ci;
+
+  ci = MHD_get_connection_info (connection,
+                                MHD_CONNECTION_INFO_SOCKET_CONTEXT);
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Processing %s\n", url);
+  if (NULL == ci)
+  {
+    GNUNET_break (0);
+    return NULL;
+  }
+  ar = ci->socket_context;
+  return ar;
+}
+
+
+
+/**
+ * Function called when MHD decides that we are done with a connection.
+ *
+ * @param cls NULL
+ * @param connection connection handle
+ * @param con_cls value as set by the last call to
+ *        the MHD_AccessHandlerCallback, should be our handle
+ * @param toe reason for request termination (ignored)
+ */
+static void
+mhd_completed_cb (void *cls,
+                  struct MHD_Connection *connection,
+                  void **con_cls,
+                  enum MHD_RequestTerminationCode toe)
+{
+  struct AcceptedRequest *ar = *con_cls;
+  if (MHD_REQUEST_TERMINATED_COMPLETED_OK != toe)
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                "MHD encountered error handling request: %d\n",
+                toe);
+  if (NULL == ar)
+    return;
+  if (NULL != ar->con_handle)
+  {
+    cleanup_handle (ar->con_handle);
+    ar->con_handle = NULL;
+  }
+  ar->socket_with_mhd = GNUNET_YES;
+  *con_cls = NULL;
+}
+
+/**
+ * Function called when MHD connection is opened or closed.
+ *
+ * @param cls NULL
+ * @param connection connection handle
+ * @param con_cls value as set by the last call to
+ *        the MHD_AccessHandlerCallback, should be our `struct Socks5Request *`
+ * @param toe connection notification type
+ */
+static void
+mhd_connection_cb (void *cls,
+                   struct MHD_Connection *connection,
+                   void **con_cls,
+                   enum MHD_ConnectionNotificationCode cnc)
+{
+  struct AcceptedRequest *ar;
+  const union MHD_ConnectionInfo *ci;
+  int sock;
+
+  switch (cnc)
+  {
+  case MHD_CONNECTION_NOTIFY_STARTED:
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Connection started...\n");
+    ci = MHD_get_connection_info (connection,
+                                  MHD_CONNECTION_INFO_CONNECTION_FD);
+    if (NULL == ci)
+    {
+      GNUNET_break (0);
+      return;
+    }
+    sock = ci->connect_fd;
+    for (ar = req_list_head; NULL != ar; ar = ar->next)
+    {
+      if (GNUNET_NETWORK_get_fd (ar->sock) == sock)
+      {
+        GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                    "Context set...\n");
+        *con_cls = ar;
+        break;
+      }
+    }
+    break;
+
+  case MHD_CONNECTION_NOTIFY_CLOSED:
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                "Connection closed... cleaning up\n");
+    ar = *con_cls;
+    if (NULL == ar)
+    {
+      GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                  "Connection stale!\n");
+      return;
+    }
+    cleanup_ar (ar);
+    *con_cls = NULL;
+    break;
+
+  default:
+    GNUNET_break (0);
+  }
+}
+
+
 
 /**
  * Task run whenever HTTP server operations are pending.
@@ -674,7 +870,7 @@ static void
 do_accept (void *cls)
 {
   struct GNUNET_NETWORK_Handle *lsock = cls;
-  struct GNUNET_NETWORK_Handle *s;
+  struct AcceptedRequest *ar;
   int fd;
   const struct sockaddr *addr;
   socklen_t len;
@@ -696,24 +892,31 @@ do_accept (void *cls)
   }
   else
     GNUNET_assert (0);
-  s = GNUNET_NETWORK_socket_accept (lsock, NULL, NULL);
-  if (NULL == s)
+  ar = GNUNET_new (struct AcceptedRequest);
+  ar->socket_with_mhd = GNUNET_YES;
+  ar->sock = GNUNET_NETWORK_socket_accept (lsock, NULL, NULL);
+  if (NULL == ar->sock)
   {
+    GNUNET_free (ar);
     GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "accept");
     return;
   }
   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
               "Got an inbound connection, waiting for data\n");
-  fd = GNUNET_NETWORK_get_fd (s);
-  addr = GNUNET_NETWORK_get_addr (s);
-  len = GNUNET_NETWORK_get_addrlen (s);
+  fd = GNUNET_NETWORK_get_fd (ar->sock);
+  addr = GNUNET_NETWORK_get_addr (ar->sock);
+  len = GNUNET_NETWORK_get_addrlen (ar->sock);
+  GNUNET_CONTAINER_DLL_insert (req_list_head,
+                               req_list_tail,
+                               ar);
   if (MHD_YES != MHD_add_connection (httpd, fd, addr, len))
   {
+    GNUNET_NETWORK_socket_close (ar->sock);
+    GNUNET_free (ar);
     GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
                 _ ("Failed to pass client to MHD\n"));
     return;
   }
-  GNUNET_free (s);
   schedule_httpd ();
 }
 
@@ -726,6 +929,18 @@ do_accept (void *cls)
 static void
 do_shutdown (void *cls)
 {
+  struct PluginListEntry *ple;
+
+  while (NULL != plugins_head)
+  {
+    ple = plugins_head;
+    GNUNET_CONTAINER_DLL_remove (plugins_head,
+                                 plugins_tail,
+                                 ple);
+    GNUNET_PLUGIN_unload (ple->libname, ple->plugin);
+    GNUNET_free (ple->libname);
+    GNUNET_free (ple);
+  }
   GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Shutting down...\n");
   kill_httpd ();
   GNUNET_free (allow_credentials);
@@ -814,7 +1029,7 @@ static void
 load_plugin (void *cls, const char *libname, void *lib_ret)
 {
   struct GNUNET_REST_Plugin *plugin = lib_ret;
-  struct GNUNET_HashCode key;
+  struct PluginListEntry *ple;
 
   if (NULL == lib_ret)
   {
@@ -825,18 +1040,12 @@ load_plugin (void *cls, const char *libname, void *lib_ret)
   }
   GNUNET_assert (1 < strlen (plugin->name));
   GNUNET_assert ('/' == *plugin->name);
-  GNUNET_CRYPTO_hash (plugin->name + 1, strlen (plugin->name + 1), &key);
-  if (GNUNET_OK != GNUNET_CONTAINER_multihashmap_put (
-        plugin_map,
-        &key,
-        plugin,
-        GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY))
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                "Could not load add plugin `%s'\n",
-                libname);
-    return;
-  }
+  ple = GNUNET_new (struct PluginListEntry);
+  ple->libname = GNUNET_strdup (libname);
+  ple->plugin = plugin;
+  GNUNET_CONTAINER_DLL_insert (plugins_head,
+                               plugins_tail,
+                               ple);
   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Loaded plugin `%s'\n", libname);
 }
 
@@ -858,8 +1067,8 @@ run (void *cls,
   char *addr_str;
 
   cfg = c;
-  plugin_map = GNUNET_CONTAINER_multihashmap_create (10, GNUNET_NO);
-
+  plugins_head = NULL;
+  plugins_tail = NULL;
   /* Get port to bind to */
   if (GNUNET_OK !=
       GNUNET_CONFIGURATION_get_value_number (cfg, "rest", "HTTP_PORT", &port))
@@ -1004,6 +1213,12 @@ run (void *cls,
                             NULL,
                             MHD_OPTION_CONNECTION_TIMEOUT,
                             (unsigned int) 16,
+                            MHD_OPTION_NOTIFY_CONNECTION,
+                            &mhd_connection_cb,
+                            NULL,
+                            MHD_OPTION_URI_LOG_CALLBACK,
+                            mhd_log_callback,
+                            NULL,
                             MHD_OPTION_NOTIFY_COMPLETED,
                             &mhd_completed_cb,
                             NULL,
diff --git a/src/rest/plugin_rest_config.c b/src/rest/plugin_rest_config.c
index 43dea1b9f9dc4f68ea522e92c2633c5f58c689e5..af833efff60e6527a5315c4e6541e8f2afd52cf3 100644
--- a/src/rest/plugin_rest_config.c
+++ b/src/rest/plugin_rest_config.c
@@ -44,6 +44,16 @@ const struct GNUNET_CONFIGURATION_Handle *cfg;
 
 struct RequestHandle
 {
+  /**
+   * DLL
+   */
+  struct RequestHandle *next;
+
+  /**
+   * DLL
+   */
+  struct RequestHandle *prev;
+
   /**
    * Handle to rest request
    */
@@ -70,6 +80,17 @@ struct RequestHandle
   char *url;
 };
 
+/**
+ * DLL
+ */
+static struct RequestHandle *requests_head;
+
+/**
+ * DLL
+ */
+static struct RequestHandle *requests_tail;
+
+
 
 /**
  * Cleanup request handle.
@@ -82,6 +103,9 @@ cleanup_handle (struct RequestHandle *handle)
   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Cleaning up\n");
   if (NULL != handle->url)
     GNUNET_free (handle->url);
+  GNUNET_CONTAINER_DLL_remove (requests_head,
+                               requests_tail,
+                               handle);
   GNUNET_free (handle);
 }
 
@@ -347,7 +371,7 @@ options_cont (struct GNUNET_REST_RequestHandle *con_handle,
  * @param proc_cls closure for @a proc
  * @return #GNUNET_OK if request accepted
  */
-static void
+static enum GNUNET_GenericReturnValue
 rest_config_process_request (struct GNUNET_REST_RequestHandle *conndata_handle,
                              GNUNET_REST_ResultProcessor proc,
                              void *proc_cls)
@@ -367,13 +391,16 @@ rest_config_process_request (struct GNUNET_REST_RequestHandle *conndata_handle,
   handle->url = GNUNET_strdup (conndata_handle->url);
   if (handle->url[strlen (handle->url) - 1] == '/')
     handle->url[strlen (handle->url) - 1] = '\0';
-
+  GNUNET_CONTAINER_DLL_insert (requests_head,
+                               requests_tail,
+                               handle);
   if (GNUNET_NO ==
       GNUNET_REST_handle_request (conndata_handle, handlers, &err, handle))
   {
-    handle->response_code = err.error_code;
-    GNUNET_SCHEDULER_add_now (&do_error, handle);
+    cleanup_handle (handle);
+    return GNUNET_NO;
   }
+  return GNUNET_YES;
 }
 
 
@@ -391,15 +418,13 @@ libgnunet_plugin_rest_config_init (void *cls)
   cfg = cls;
   struct GNUNET_REST_Plugin *api;
 
-  if (NULL != plugin.cfg)
-    return NULL; /* can only initialize once! */
   memset (&plugin, 0, sizeof(struct Plugin));
   plugin.cfg = cfg;
   api = GNUNET_new (struct GNUNET_REST_Plugin);
   api->cls = &plugin;
   api->name = GNUNET_REST_API_NS_CONFIG;
   api->process_request = &rest_config_process_request;
-  GNUNET_log (GNUNET_ERROR_TYPE_INFO, _ ("CONFIG REST API initialized\n"));
+  GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("CONFIG REST API initialized\n"));
   return api;
 }
 
@@ -414,8 +439,11 @@ void *
 libgnunet_plugin_rest_config_done (void *cls)
 {
   struct GNUNET_REST_Plugin *api = cls;
-  struct Plugin *plugin = api->cls;
+  struct Plugin *plugin;
 
+  while (NULL != requests_head)
+    cleanup_handle (requests_head);
+  plugin = api->cls;
   plugin->cfg = NULL;
   GNUNET_free (api);
   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "CONFIG REST plugin is finished\n");
diff --git a/src/rest/plugin_rest_copying.c b/src/rest/plugin_rest_copying.c
index e601e505e86e243fe71550eb1688f9cced8a10b6..6d074d3d1755f04b033279ed2c1036fa1424981e 100644
--- a/src/rest/plugin_rest_copying.c
+++ b/src/rest/plugin_rest_copying.c
@@ -45,6 +45,16 @@ const struct GNUNET_CONFIGURATION_Handle *cfg;
 
 struct RequestHandle
 {
+  /**
+   * DLL
+   */
+  struct RequestHandle *next;
+
+  /**
+   * DLL
+   */
+  struct RequestHandle *prev;
+
   /**
    * Handle to rest request
    */
@@ -66,6 +76,15 @@ struct RequestHandle
   int response_code;
 };
 
+/**
+ * DLL
+ */
+static struct RequestHandle *requests_head;
+
+/**
+ * DLL
+ */
+static struct RequestHandle *requests_tail;
 
 /**
  * Cleanup request handle.
@@ -77,28 +96,13 @@ cleanup_handle (struct RequestHandle *handle)
 {
   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
               "Cleaning up\n");
+  GNUNET_CONTAINER_DLL_remove (requests_head,
+                               requests_tail,
+                               handle);
   GNUNET_free (handle);
 }
 
 
-/**
- * Task run on shutdown.  Cleans up everything.
- *
- * @param cls unused
- * @param tc scheduler context
- */
-static void
-do_error (void *cls)
-{
-  struct RequestHandle *handle = cls;
-  struct MHD_Response *resp;
-
-  resp = GNUNET_REST_create_response (NULL);
-  handle->proc (handle->proc_cls, resp, handle->response_code);
-  cleanup_handle (handle);
-}
-
-
 /**
  * Handle rest request
  *
@@ -155,7 +159,7 @@ options_cont (struct GNUNET_REST_RequestHandle *con_handle,
  * @param proc_cls closure for @a proc
  * @return #GNUNET_OK if request accepted
  */
-static void
+static enum GNUNET_GenericReturnValue
 rest_copying_process_request (struct GNUNET_REST_RequestHandle *conndata_handle,
                               GNUNET_REST_ResultProcessor proc,
                               void *proc_cls)
@@ -171,15 +175,13 @@ rest_copying_process_request (struct GNUNET_REST_RequestHandle *conndata_handle,
   handle->proc_cls = proc_cls;
   handle->proc = proc;
   handle->rest_handle = conndata_handle;
-
-  if (GNUNET_NO == GNUNET_REST_handle_request (conndata_handle,
-                                               handlers,
-                                               &err,
-                                               handle))
-  {
-    handle->response_code = err.error_code;
-    GNUNET_SCHEDULER_add_now (&do_error, handle);
-  }
+  GNUNET_CONTAINER_DLL_insert (requests_head,
+                               requests_tail,
+                               handle);
+  return GNUNET_REST_handle_request (conndata_handle,
+                                     handlers,
+                                     &err,
+                                     handle);
 }
 
 
@@ -223,6 +225,8 @@ libgnunet_plugin_rest_copying_done (void *cls)
   struct GNUNET_REST_Plugin *api = cls;
   struct Plugin *plugin = api->cls;
 
+  while (NULL != requests_head)
+    cleanup_handle (requests_head);
   plugin->cfg = NULL;
   GNUNET_free (api);
   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
diff --git a/src/revocation/.gitignore b/src/revocation/.gitignore
new file mode 100644
index 0000000000000000000000000000000000000000..1432f7922b74f237b7f47b6d61adc98bdabd29c5
--- /dev/null
+++ b/src/revocation/.gitignore
@@ -0,0 +1,5 @@
+gnunet-service-revocation
+gnunet-revocation
+test_revocation
+test_local_revocation.py
+gnunet-revocation-tvg
diff --git a/src/revocation/Makefile.am b/src/revocation/Makefile.am
index a90f8cd79b315256af95a71043a015fd39f66dc2..9d98502a66de9a492eabb9d05c10897c3e8936c2 100644
--- a/src/revocation/Makefile.am
+++ b/src/revocation/Makefile.am
@@ -78,7 +78,7 @@ gnunet_service_revocation_SOURCES = \
 gnunet_service_revocation_LDADD = \
   libgnunetrevocation.la \
   $(top_builddir)/src/core/libgnunetcore.la \
-  $(top_builddir)/src/set/libgnunetset.la \
+  $(top_builddir)/src/setu/libgnunetsetu.la \
   $(top_builddir)/src/statistics/libgnunetstatistics.la \
   $(top_builddir)/src/util/libgnunetutil.la \
   -lm \
diff --git a/src/revocation/gnunet-revocation-tvg.c b/src/revocation/gnunet-revocation-tvg.c
index b8f462b285fe00caa7ec86a99d8585060dde0fa0..29df1bb4ddfdcf1e18c8ccd8c7ab57f734505ec1 100644
--- a/src/revocation/gnunet-revocation-tvg.c
+++ b/src/revocation/gnunet-revocation-tvg.c
@@ -43,13 +43,14 @@ print_bytes (void *buf,
 
   for (i = 0; i < buf_len; i++)
   {
-    if ((0 != i) && (0 != fold) && (i%fold == 0))
-      printf("\n");
-    printf("%02x", ((unsigned char*)buf)[i]);
+    if ((0 != i) && (0 != fold) && (i % fold == 0))
+      printf ("\n");
+    printf ("%02x", ((unsigned char*) buf)[i]);
   }
-  printf("\n");
+  printf ("\n");
 }
 
+
 /**
  * Main function that will be run.
  *
@@ -73,12 +74,12 @@ run (void *cls,
   GNUNET_CRYPTO_ecdsa_key_create (&id_priv);
   GNUNET_CRYPTO_ecdsa_key_get_public (&id_priv,
                                       &id_pub);
-  fprintf(stdout, "Zone private key (d, little-endian scalar):\n");
+  fprintf (stdout, "Zone private key (d, little-endian scalar):\n");
   print_bytes (&id_priv, sizeof(id_priv), 0);
-  fprintf(stdout, "\n");
-  fprintf(stdout, "Zone public key (zk):\n");
+  fprintf (stdout, "\n");
+  fprintf (stdout, "Zone public key (zk):\n");
   print_bytes (&id_pub, sizeof(id_pub), 0);
-  fprintf(stdout, "\n");
+  fprintf (stdout, "\n");
   memset (&pow, 0, sizeof (pow));
   GNUNET_REVOCATION_pow_init (&id_priv,
                               &pow);
@@ -99,7 +100,7 @@ run (void *cls,
   GNUNET_assert (GNUNET_OK == GNUNET_REVOCATION_check_pow (&pow,
                                                            TEST_DIFFICULTY,
                                                            exp));
-  fprintf(stdout, "Proof:\n");
+  fprintf (stdout, "Proof:\n");
   print_bytes (&pow,
                sizeof (pow),
                8);
diff --git a/src/revocation/gnunet-service-revocation.c b/src/revocation/gnunet-service-revocation.c
index 81a30748cb61c9c2f9df1ab8b9a32d540a8ca34f..ddebb38adeb5cf4a732ce04d4658df54b7fd8c9a 100644
--- a/src/revocation/gnunet-service-revocation.c
+++ b/src/revocation/gnunet-service-revocation.c
@@ -45,7 +45,7 @@
 #include "gnunet_statistics_service.h"
 #include "gnunet_core_service.h"
 #include "gnunet_revocation_service.h"
-#include "gnunet_set_service.h"
+#include "gnunet_setu_service.h"
 #include "revocation.h"
 #include <gcrypt.h>
 
@@ -73,14 +73,14 @@ struct PeerEntry
   /**
    * Handle to active set union operation (over revocation sets).
    */
-  struct GNUNET_SET_OperationHandle *so;
+  struct GNUNET_SETU_OperationHandle *so;
 };
 
 
 /**
  * Set from all revocations known to us.
  */
-static struct GNUNET_SET_Handle *revocation_set;
+static struct GNUNET_SETU_Handle *revocation_set;
 
 /**
  * Hash map with all revoked keys, maps the hash of the public key
@@ -121,7 +121,7 @@ static struct GNUNET_DISK_FileHandle *revocation_db;
 /**
  * Handle for us listening to incoming revocation set union requests.
  */
-static struct GNUNET_SET_ListenHandle *revocation_union_listen_handle;
+static struct GNUNET_SETU_ListenHandle *revocation_union_listen_handle;
 
 /**
  * Amount of work required (W-bit collisions) for REVOCATION proofs, in collision-bits.
@@ -302,7 +302,7 @@ publicize_rm (const struct RevokeMessage *rm)
 {
   struct RevokeMessage *cp;
   struct GNUNET_HashCode hc;
-  struct GNUNET_SET_Element e;
+  struct GNUNET_SETU_Element e;
 
   GNUNET_CRYPTO_hash (&rm->proof_of_work.key,
                       sizeof(struct GNUNET_CRYPTO_EcdsaPublicKey),
@@ -350,10 +350,10 @@ publicize_rm (const struct RevokeMessage *rm)
   e.element_type = GNUNET_BLOCK_TYPE_REVOCATION;
   e.data = rm;
   if (GNUNET_OK !=
-      GNUNET_SET_add_element (revocation_set,
-                              &e,
-                              NULL,
-                              NULL))
+      GNUNET_SETU_add_element (revocation_set,
+                               &e,
+                               NULL,
+                               NULL))
   {
     GNUNET_break (0);
     return GNUNET_OK;
@@ -426,22 +426,22 @@ handle_p2p_revoke (void *cls,
  * validate and then add to our revocation list (and set).
  *
  * @param cls closure
- * @param element a result element, only valid if status is #GNUNET_SET_STATUS_OK
+ * @param element a result element, only valid if status is #GNUNET_SETU_STATUS_OK
  * @param current_size current set size
- * @param status see `enum GNUNET_SET_Status`
+ * @param status see `enum GNUNET_SETU_Status`
  */
 static void
 add_revocation (void *cls,
-                const struct GNUNET_SET_Element *element,
+                const struct GNUNET_SETU_Element *element,
                 uint64_t current_size,
-                enum GNUNET_SET_Status status)
+                enum GNUNET_SETU_Status status)
 {
   struct PeerEntry *peer_entry = cls;
   const struct RevokeMessage *rm;
 
   switch (status)
   {
-  case GNUNET_SET_STATUS_OK:
+  case GNUNET_SETU_STATUS_ADD_LOCAL:
     if (element->size != sizeof(struct RevokeMessage))
     {
       GNUNET_break_op (0);
@@ -464,8 +464,7 @@ add_revocation (void *cls,
                                 "# revocation messages received via set union"),
                               1, GNUNET_NO);
     break;
-
-  case GNUNET_SET_STATUS_FAILURE:
+  case GNUNET_SETU_STATUS_FAILURE:
     GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
                 _ ("Error computing revocation set union with %s\n"),
                 GNUNET_i2s (&peer_entry->id));
@@ -475,11 +474,7 @@ add_revocation (void *cls,
                               1,
                               GNUNET_NO);
     break;
-
-  case GNUNET_SET_STATUS_HALF_DONE:
-    break;
-
-  case GNUNET_SET_STATUS_DONE:
+  case GNUNET_SETU_STATUS_DONE:
     peer_entry->so = NULL;
     GNUNET_STATISTICS_update (stats,
                               gettext_noop (
@@ -487,7 +482,6 @@ add_revocation (void *cls,
                               1,
                               GNUNET_NO);
     break;
-
   default:
     GNUNET_break (0);
     break;
@@ -511,16 +505,15 @@ transmit_task_cb (void *cls)
               GNUNET_i2s (&peer_entry->id));
   peer_entry->transmit_task = NULL;
   GNUNET_assert (NULL == peer_entry->so);
-  peer_entry->so = GNUNET_SET_prepare (&peer_entry->id,
-                                       &revocation_set_union_app_id,
-                                       NULL,
-                                       GNUNET_SET_RESULT_ADDED,
-                                       (struct GNUNET_SET_Option[]) { { 0 } },
-                                       &add_revocation,
-                                       peer_entry);
+  peer_entry->so = GNUNET_SETU_prepare (&peer_entry->id,
+                                        &revocation_set_union_app_id,
+                                        NULL,
+                                        (struct GNUNET_SETU_Option[]) { { 0 } },
+                                        &add_revocation,
+                                        peer_entry);
   if (GNUNET_OK !=
-      GNUNET_SET_commit (peer_entry->so,
-                         revocation_set))
+      GNUNET_SETU_commit (peer_entry->so,
+                          revocation_set))
   {
     GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
                 _ ("SET service crashed, terminating revocation service\n"));
@@ -626,7 +619,7 @@ handle_core_disconnect (void *cls,
   }
   if (NULL != peer_entry->so)
   {
-    GNUNET_SET_operation_cancel (peer_entry->so);
+    GNUNET_SETU_operation_cancel (peer_entry->so);
     peer_entry->so = NULL;
   }
   GNUNET_free (peer_entry);
@@ -665,12 +658,12 @@ shutdown_task (void *cls)
 {
   if (NULL != revocation_set)
   {
-    GNUNET_SET_destroy (revocation_set);
+    GNUNET_SETU_destroy (revocation_set);
     revocation_set = NULL;
   }
   if (NULL != revocation_union_listen_handle)
   {
-    GNUNET_SET_listen_cancel (revocation_union_listen_handle);
+    GNUNET_SETU_listen_cancel (revocation_union_listen_handle);
     revocation_union_listen_handle = NULL;
   }
   if (NULL != core_api)
@@ -729,7 +722,7 @@ core_init (void *cls,
  * @param other_peer the other peer
  * @param context_msg message with application specific information from
  *        the other peer
- * @param request request from the other peer (never NULL), use GNUNET_SET_accept()
+ * @param request request from the other peer (never NULL), use GNUNET_SETU_accept()
  *        to accept it, otherwise the request will be refused
  *        Note that we can't just return value from the listen callback,
  *        as it is also necessary to specify the set we want to do the
@@ -740,7 +733,7 @@ static void
 handle_revocation_union_request (void *cls,
                                  const struct GNUNET_PeerIdentity *other_peer,
                                  const struct GNUNET_MessageHeader *context_msg,
-                                 struct GNUNET_SET_Request *request)
+                                 struct GNUNET_SETU_Request *request)
 {
   struct PeerEntry *peer_entry;
 
@@ -763,14 +756,13 @@ handle_revocation_union_request (void *cls,
     GNUNET_break_op (0);
     return;
   }
-  peer_entry->so = GNUNET_SET_accept (request,
-                                      GNUNET_SET_RESULT_ADDED,
-                                      (struct GNUNET_SET_Option[]) { { 0 } },
-                                      &add_revocation,
-                                      peer_entry);
+  peer_entry->so = GNUNET_SETU_accept (request,
+                                       (struct GNUNET_SETU_Option[]) { { 0 } },
+                                       &add_revocation,
+                                       peer_entry);
   if (GNUNET_OK !=
-      GNUNET_SET_commit (peer_entry->so,
-                         revocation_set))
+      GNUNET_SETU_commit (peer_entry->so,
+                          revocation_set))
   {
     GNUNET_break (0);
     GNUNET_SCHEDULER_shutdown ();
@@ -858,14 +850,12 @@ run (void *cls,
     return;
   }
 
-  revocation_set = GNUNET_SET_create (cfg,
-                                      GNUNET_SET_OPERATION_UNION);
+  revocation_set = GNUNET_SETU_create (cfg);
   revocation_union_listen_handle
-    = GNUNET_SET_listen (cfg,
-                         GNUNET_SET_OPERATION_UNION,
-                         &revocation_set_union_app_id,
-                         &handle_revocation_union_request,
-                         NULL);
+    = GNUNET_SETU_listen (cfg,
+                          &revocation_set_union_app_id,
+                          &handle_revocation_union_request,
+                          NULL);
   revocation_db = GNUNET_DISK_file_open (fn,
                                          GNUNET_DISK_OPEN_READWRITE
                                          | GNUNET_DISK_OPEN_CREATE,
diff --git a/src/revocation/revocation_api.c b/src/revocation/revocation_api.c
index 3815e47b0f0f4ab5b9c74cc194974a31920c1788..75cfd8761c54945772c604cbfc71eb689d031135 100644
--- a/src/revocation/revocation_api.c
+++ b/src/revocation/revocation_api.c
@@ -103,6 +103,8 @@ struct GNUNET_REVOCATION_PowCalculationHandle
 
 };
 
+static struct GNUNET_CRYPTO_PowSalt salt = { "GnsRevocationPow" };
+
 /**
  * Generic error handler, called with the appropriate
  * error code and the same closure specified at the creation of
@@ -468,9 +470,9 @@ GNUNET_REVOCATION_check_pow (const struct GNUNET_REVOCATION_PowP *pow,
   /**
    * First, check if PoW set is strictly monotically increasing
    */
-  for (unsigned int i = 0; i < POW_COUNT-1; i++)
+  for (unsigned int i = 0; i < POW_COUNT - 1; i++)
   {
-    if (GNUNET_ntohll (pow->pow[i]) >= GNUNET_ntohll (pow->pow[i+1]))
+    if (GNUNET_ntohll (pow->pow[i]) >= GNUNET_ntohll (pow->pow[i + 1]))
       return GNUNET_NO;
   }
   GNUNET_memcpy (&buf[sizeof(uint64_t)],
@@ -483,7 +485,7 @@ GNUNET_REVOCATION_check_pow (const struct GNUNET_REVOCATION_PowP *pow,
   {
     pow_val = GNUNET_ntohll (pow->pow[i]);
     GNUNET_memcpy (buf, &pow->pow[i], sizeof(uint64_t));
-    GNUNET_CRYPTO_pow_hash ("GnsRevocationPow",
+    GNUNET_CRYPTO_pow_hash (&salt,
                             buf,
                             sizeof(buf),
                             &result);
@@ -592,6 +594,7 @@ GNUNET_REVOCATION_pow_start (struct GNUNET_REVOCATION_PowP *pow,
   return pc;
 }
 
+
 /**
  * Comparison function for quicksort
  *
@@ -602,9 +605,10 @@ GNUNET_REVOCATION_pow_start (struct GNUNET_REVOCATION_PowP *pow,
 static int
 cmp_pow_value (const void *a, const void *b)
 {
-  return ( GNUNET_ntohll(*(uint64_t*)a) - GNUNET_ntohll(*(uint64_t*)b));
+  return (GNUNET_ntohll (*(uint64_t*) a) - GNUNET_ntohll (*(uint64_t*) b));
 }
 
+
 /**
  * Calculate a key revocation valid for broadcasting for a number
  * of epochs.
@@ -642,7 +646,7 @@ GNUNET_REVOCATION_pow_round (struct GNUNET_REVOCATION_PowCalculationHandle *pc)
   GNUNET_memcpy (&buf[sizeof(uint64_t) * 2],
                  &pc->pow->key,
                  sizeof(struct GNUNET_CRYPTO_EcdsaPublicKey));
-  GNUNET_CRYPTO_pow_hash ("GnsRevocationPow",
+  GNUNET_CRYPTO_pow_hash (&salt,
                           buf,
                           sizeof(buf),
                           &result);
diff --git a/src/rps/.gitignore b/src/rps/.gitignore
new file mode 100644
index 0000000000000000000000000000000000000000..9e78e2ca08c8aefc4e2cb68f4abe6bbe6a6614b0
--- /dev/null
+++ b/src/rps/.gitignore
@@ -0,0 +1,16 @@
+gnunet-service-rps
+gnunet-rps
+gnunet-rps-profiler
+test_rps_single_req
+test_rps_req_cancel
+test_rps_sub
+test_rps_seed_big
+test_rps_seed_request
+test_service_rps_custommap
+test_service_rps_sampler_elem
+test_service_rps_view
+test_rps_churn
+test_service_rps_peers
+test_rps_malicious_1
+test_rps_malicious_2
+test_rps_malicious_3
diff --git a/src/rps/gnunet-rps-profiler.c b/src/rps/gnunet-rps-profiler.c
index af43a0fa1ef58e991afdc7de048c3cee40dc7942..08d1d2d34715954a373d1fa9ff57dcb423066995 100644
--- a/src/rps/gnunet-rps-profiler.c
+++ b/src/rps/gnunet-rps-profiler.c
@@ -924,10 +924,10 @@ tofile_ (const char *file_name, const char *line)
     int size; \
     size = GNUNET_snprintf (tmp_buf, sizeof(tmp_buf), __VA_ARGS__); \
     if (0 > size) \
-      GNUNET_log (GNUNET_ERROR_TYPE_WARNING, \
-                  "Failed to create tmp_buf\n"); \
+    GNUNET_log (GNUNET_ERROR_TYPE_WARNING, \
+                "Failed to create tmp_buf\n"); \
     else \
-      tofile_ (file_name, tmp_buf); \
+    tofile_ (file_name, tmp_buf); \
 } while (0);
 
 
diff --git a/src/rps/profiler_rps.conf b/src/rps/profiler_rps.conf
new file mode 100644
index 0000000000000000000000000000000000000000..5edd6d3ff15ff6135241c669ffb2990d37fac5a8
--- /dev/null
+++ b/src/rps/profiler_rps.conf
@@ -0,0 +1,139 @@
+[rps]
+#PREFIX = valgrind --leak-check=full --show-leak-kinds=all --log-file=/tmp/rps/valgrind!gnunet-service-rps!%p
+#PREFIX = valgrind --log-file=/tmp/rps/valgrind!gnunet-service-rps!%p
+#PREFIX = valgrind
+UNIXPATH = $GNUNET_TMP/gnunet-service-rps.sock
+HOME = $SERVICEHOME
+# PORT = 2106
+#@UNIXONLY@ PORT = 2087
+IMMEDIATE_START = YES
+START_ON_DEMAND = NO
+NOARMBIND = YES
+#OPTIONS=-l /tmp/rps_profiler_logs/rps-[]-%Y-%m-%d.log
+
+# This is the timeinterval between the rounds
+ROUNDINTERVAL = 2 s
+FILENAME_VALID_PEERS = $GNUNET_DATA_HOME/rps/valid_peers.txt
+
+# This is the 'estimate' in the beginning.
+# This determines the size of the peers we keep in memory
+# until we receive the first estimate from NSE.
+# Keep in mind, that (networksize)^(1/3) should be enough.
+# So, 50 is enough for a network of size 50^3 = 125000
+MINSIZE = 4
+
+DESIRED_PROBABILITY = 0.75
+
+DEFICIENCY_FACTOR = 0.4
+
+
+[testbed]
+HOSTNAME = localhost
+
+# MAX_PARALLEL_TOPOLOGY_CONFIG_OPERATIONS = 100
+
+#OVERLAY_TOPOLOGY = CLIQUE
+
+#OVERLAY_TOPOLOGY = SCALE_FREE
+#SCALE_FREE_TOPOLOGY_CAP = 100
+#SCALE_FREE_TOPOLOGY_M = 2
+
+OVERLAY_TOPOLOGY = RANDOM
+## We take half of the links a complete graph would have, so (n * n-1)/4
+## for n = 128, this would be
+OVERLAY_RANDOM_LINKS = 4064
+
+#OVERLAY_TOPOLOGY = SMALL_WORLD
+#OVERLAY_RANDOM_LINKS = 25
+
+SETUP_TIMEOUT = 1 h
+
+[nse]
+WORKBITS = 0
+
+[nat]
+# Use addresses from the local network interfaces (inluding loopback, but also others)
+USE_LOCALADDR = YES
+ENABLE_UPNP = NO
+
+# Do we use addresses from localhost address ranges? (::1, 127.0.0.0/8)
+RETURN_LOCAL_ADDRESSES = YES
+
+[transport]
+PLUGINS = unix
+
+[ats]
+# Network specific inbound/outbound quotas
+UNSPECIFIED_QUOTA_IN = unlimited
+UNSPECIFIED_QUOTA_OUT = unlimited
+# LOOPBACK
+LOOPBACK_QUOTA_IN = unlimited
+LOOPBACK_QUOTA_OUT = unlimited
+# LAN
+LAN_QUOTA_IN = unlimited
+LAN_QUOTA_OUT = unlimited
+#WAN
+WAN_QUOTA_OUT = unlimited
+WAN_QUOTA_IN = unlimited
+# WLAN
+WLAN_QUOTA_IN = unlimited
+WLAN_QUOTA_OUT = unlimited
+# BLUETOOTH
+BLUETOOTH_QUOTA_IN = unlimited
+BLUETOOTH_QUOTA_OUT = unlimited
+
+[dht]
+DISABLE_TRY_CONNECT = YES
+
+[cadet]
+OPTIONS=-l /tmp/rps_profiler_logs/cadet-[]-%Y-%m-%d.log
+
+#[arm]
+#GLOBAL_POSTFIX=-l /tmp/rps_profiler_logs/other-[]-%Y-%m-%d.log
+
+#[statistics]
+#IMMEDIATE_START = NO
+#START_ON_DEMAND = NO
+
+[peerinfo]
+NO_IO = YES
+
+[hostlist]
+IMMEDIATE_START = NO
+START_ON_DEMAND = NO
+
+[zonemaster]
+IMMEDIATE_START = NO
+START_ON_DEMAND = NO
+
+[namecache]
+IMMEDIATE_START = NO
+START_ON_DEMAND = NO
+
+[namestore]
+IMMEDIATE_START = NO
+START_ON_DEMAND = NO
+
+[topology]
+IMMEDIATE_START = NO
+START_ON_DEMAND = NO
+
+[vpn]
+IMMEDIATE_START = NO
+START_ON_DEMAND = NO
+
+[revocation]
+IMMEDIATE_START = NO
+START_ON_DEMAND = NO
+
+[gns]
+IMMEDIATE_START = NO
+START_ON_DEMAND = NO
+
+[fs]
+IMMEDIATE_START = NO
+START_ON_DEMAND = NO
+
+[zonemaster-monitor]
+IMMEDIATE_START = NO
+START_ON_DEMAND = NO
diff --git a/src/rps/test_rps.c b/src/rps/test_rps.c
index 81cf63c7296ef39586f0bbde53260c3adb0f9a2c..a7dc3aa0037e2fa61e09f74062e1e851bacf6f74 100644
--- a/src/rps/test_rps.c
+++ b/src/rps/test_rps.c
@@ -656,10 +656,10 @@ tofile_ (const char *file_name, const char *line)
     int size; \
     size = GNUNET_snprintf (tmp_buf, sizeof(tmp_buf), __VA_ARGS__); \
     if (0 > size) \
-      GNUNET_log (GNUNET_ERROR_TYPE_WARNING, \
-                  "Failed to create tmp_buf\n"); \
+    GNUNET_log (GNUNET_ERROR_TYPE_WARNING, \
+                "Failed to create tmp_buf\n"); \
     else \
-      tofile_ (file_name, tmp_buf); \
+    tofile_ (file_name, tmp_buf); \
 } while (0);
 
 
diff --git a/src/rps/test_rps_api.c b/src/rps/test_rps_api.c
new file mode 100644
index 0000000000000000000000000000000000000000..06dad2887e8eb92314468234c9c1b985225cf112
--- /dev/null
+++ b/src/rps/test_rps_api.c
@@ -0,0 +1,87 @@
+/*
+     This file is part of GNUnet.
+     Copyright (C)
+
+     GNUnet is free software: you can redistribute it and/or modify it
+     under the terms of the GNU Affero General Public License as published
+     by the Free Software Foundation, either version 3 of the License,
+     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
+     Affero General Public License for more details.
+
+     You should have received a copy of the GNU Affero General Public License
+     along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+     SPDX-License-Identifier: AGPL3.0-or-later
+ */
+/**
+ * @file rps/test_rps_api.c
+ * @brief testcase for rps_api.c
+ */
+#include "platform.h"
+#include "gnunet_util_lib.h"
+#include "gnunet_rps_service.h"
+
+
+static int ok = 1;
+
+
+static void
+run (void *cls,
+     char *const *args,
+     const char *cfgfile,
+     const struct GNUNET_CONFIGURATION_Handle *cfg)
+{
+  ok = 0;
+}
+
+
+static int
+check ()
+{
+  char *const argv[] = { "test-rps-api", NULL };
+  struct GNUNET_GETOPT_CommandLineOption options[] = {
+    GNUNET_GETOPT_OPTION_END
+  };
+  struct GNUNET_OS_Process *proc;
+  char *path = GNUNET_OS_get_libexec_binary_path ("gnunet-service-rps");
+
+  if (NULL == path)
+  {
+    fprintf (stderr, "Service executable not found `%s'\n",
+             "gnunet-service-rps");
+    return;
+  }
+
+  proc = GNUNET_OS_start_process (GNUNET_NO, GNUNET_OS_INHERIT_STD_ALL, NULL,
+                                  NULL, NULL, path, "gnunet-service-rps", NULL);
+
+  GNUNET_free (path);
+  GNUNET_assert (NULL != proc);
+  GNUNET_PROGRAM_run (1, argv, "test-rps-api", "nohelp",
+                      options, &run, &ok);
+  if (0 != GNUNET_OS_process_kill (proc, SIGTERM))
+  {
+    GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "kill");
+    ok = 1;
+  }
+  GNUNET_OS_process_wait (proc);
+  GNUNET_OS_process_destroy (proc);
+  return ok;
+}
+
+
+int
+main (int argc, char *argv[])
+{
+  GNUNET_log_setup ("test_statistics_api",
+                    "WARNING",
+                    NULL);
+  return check ();
+}
+
+
+/* end of test_rps_api.c */
diff --git a/src/scalarproduct/.gitignore b/src/scalarproduct/.gitignore
new file mode 100644
index 0000000000000000000000000000000000000000..19909a3f924a360f5e97b698bb74cdce2c3a087a
--- /dev/null
+++ b/src/scalarproduct/.gitignore
@@ -0,0 +1,6 @@
+gnunet-service-scalarproduct-ecc-bob
+gnunet-scalarproduct
+gnunet-service-scalarproduct-alice
+gnunet-service-scalarproduct-bob
+gnunet-service-scalarproduct-ecc-alice
+test_ecc_scalarproduct
diff --git a/src/scalarproduct/Makefile.am b/src/scalarproduct/Makefile.am
index 311cfd1af3977c8f53e699c75be4e643afbfb98e..f3448725abe2f6f4477d8b38de2bbf71f7374c5a 100644
--- a/src/scalarproduct/Makefile.am
+++ b/src/scalarproduct/Makefile.am
@@ -39,7 +39,7 @@ gnunet_service_scalarproduct_alice_SOURCES = \
 gnunet_service_scalarproduct_alice_LDADD = \
   $(top_builddir)/src/util/libgnunetutil.la \
   $(top_builddir)/src/cadet/libgnunetcadet.la \
-  $(top_builddir)/src/set/libgnunetset.la \
+  $(top_builddir)/src/seti/libgnunetseti.la \
   $(LIBGCRYPT_LIBS) \
   -lgcrypt \
   $(GN_LIBINTL)
@@ -50,7 +50,7 @@ gnunet_service_scalarproduct_bob_SOURCES = \
 gnunet_service_scalarproduct_bob_LDADD = \
   $(top_builddir)/src/util/libgnunetutil.la \
   $(top_builddir)/src/cadet/libgnunetcadet.la \
-  $(top_builddir)/src/set/libgnunetset.la \
+  $(top_builddir)/src/seti/libgnunetseti.la \
   $(LIBGCRYPT_LIBS) \
   -lgcrypt \
   $(GN_LIBINTL)
@@ -61,7 +61,7 @@ gnunet_service_scalarproduct_ecc_alice_SOURCES = \
 gnunet_service_scalarproduct_ecc_alice_LDADD = \
   $(top_builddir)/src/util/libgnunetutil.la \
   $(top_builddir)/src/cadet/libgnunetcadet.la \
-  $(top_builddir)/src/set/libgnunetset.la \
+  $(top_builddir)/src/seti/libgnunetseti.la \
   $(LIBGCRYPT_LIBS) \
   -lgcrypt \
   $(GN_LIBINTL)
@@ -72,7 +72,7 @@ gnunet_service_scalarproduct_ecc_bob_SOURCES = \
 gnunet_service_scalarproduct_ecc_bob_LDADD = \
   $(top_builddir)/src/util/libgnunetutil.la \
   $(top_builddir)/src/cadet/libgnunetcadet.la \
-  $(top_builddir)/src/set/libgnunetset.la \
+  $(top_builddir)/src/seti/libgnunetseti.la \
   $(LIBGCRYPT_LIBS) \
   -lgcrypt \
   $(GN_LIBINTL)
diff --git a/src/scalarproduct/gnunet-service-scalarproduct-ecc_alice.c b/src/scalarproduct/gnunet-service-scalarproduct-ecc_alice.c
index 20ab292cf2af14b3b2a11f93ce63f85bc1d2c9a9..447451aefdaadcd15b550efbc3b487f5b088a813 100644
--- a/src/scalarproduct/gnunet-service-scalarproduct-ecc_alice.c
+++ b/src/scalarproduct/gnunet-service-scalarproduct-ecc_alice.c
@@ -32,7 +32,7 @@
 #include "gnunet_applications.h"
 #include "gnunet_protocols.h"
 #include "gnunet_scalarproduct_service.h"
-#include "gnunet_set_service.h"
+#include "gnunet_seti_service.h"
 #include "scalarproduct.h"
 #include "gnunet-service-scalarproduct-ecc.h"
 
@@ -114,18 +114,18 @@ struct AliceServiceSession
    * Set of elements for which will conduction an intersection.
    * the resulting elements are then used for computing the scalar product.
    */
-  struct GNUNET_SET_Handle *intersection_set;
+  struct GNUNET_SETI_Handle *intersection_set;
 
   /**
    * Set of elements for which will conduction an intersection.
    * the resulting elements are then used for computing the scalar product.
    */
-  struct GNUNET_SET_OperationHandle *intersection_op;
+  struct GNUNET_SETI_OperationHandle *intersection_op;
 
   /**
    * Handle to Alice's Intersection operation listening for Bob
    */
-  struct GNUNET_SET_ListenHandle *intersection_listen;
+  struct GNUNET_SETI_ListenHandle *intersection_listen;
 
   /**
    * channel-handle associated with our cadet handle
@@ -256,18 +256,18 @@ destroy_service_session (struct AliceServiceSession *s)
   }
   if (NULL != s->intersection_listen)
   {
-    GNUNET_SET_listen_cancel (s->intersection_listen);
+    GNUNET_SETI_listen_cancel (s->intersection_listen);
     s->intersection_listen = NULL;
   }
   if (NULL != s->intersection_op)
   {
     LOG (GNUNET_ERROR_TYPE_DEBUG, "Set intersection, op still ongoing!\n");
-    GNUNET_SET_operation_cancel (s->intersection_op);
+    GNUNET_SETI_operation_cancel (s->intersection_op);
     s->intersection_op = NULL;
   }
   if (NULL != s->intersection_set)
   {
-    GNUNET_SET_destroy (s->intersection_set);
+    GNUNET_SETI_destroy (s->intersection_set);
     s->intersection_set = NULL;
   }
   if (NULL != s->sorted_elements)
@@ -649,22 +649,22 @@ send_alices_cryptodata_message (struct AliceServiceSession *s)
  * to indicate that the set intersection operation is done.
  *
  * @param cls closure with the `struct AliceServiceSession`
- * @param element a result element, only valid if status is #GNUNET_SET_STATUS_OK
+ * @param element a result element, only valid if status is #GNUNET_SETI_STATUS_OK
  * @param current_size current set size
  * @param status what has happened with the set intersection?
  */
 static void
 cb_intersection_element_removed (void *cls,
-                                 const struct GNUNET_SET_Element *element,
+                                 const struct GNUNET_SETI_Element *element,
                                  uint64_t current_size,
-                                 enum GNUNET_SET_Status status)
+                                 enum GNUNET_SETI_Status status)
 {
   struct AliceServiceSession *s = cls;
   struct GNUNET_SCALARPRODUCT_Element *se;
 
   switch (status)
   {
-  case GNUNET_SET_STATUS_OK:
+  case GNUNET_SETI_STATUS_DEL_LOCAL:
     /* this element has been removed from the set */
     se = GNUNET_CONTAINER_multihashmap_get (s->intersected_elements,
                                             element->data);
@@ -680,34 +680,27 @@ cb_intersection_element_removed (void *cls,
                                             se));
     GNUNET_free (se);
     return;
-
-  case GNUNET_SET_STATUS_DONE:
+  case GNUNET_SETI_STATUS_DONE:
     s->intersection_op = NULL;
     if (NULL != s->intersection_set)
     {
-      GNUNET_SET_destroy (s->intersection_set);
+      GNUNET_SETI_destroy (s->intersection_set);
       s->intersection_set = NULL;
     }
     send_alices_cryptodata_message (s);
     return;
-
-  case GNUNET_SET_STATUS_HALF_DONE:
-    /* unexpected for intersection */
-    GNUNET_break (0);
-    return;
-
-  case GNUNET_SET_STATUS_FAILURE:
+  case GNUNET_SETI_STATUS_FAILURE:
     /* unhandled status code */
     LOG (GNUNET_ERROR_TYPE_DEBUG, "Set intersection failed!\n");
     if (NULL != s->intersection_listen)
     {
-      GNUNET_SET_listen_cancel (s->intersection_listen);
+      GNUNET_SETI_listen_cancel (s->intersection_listen);
       s->intersection_listen = NULL;
     }
     s->intersection_op = NULL;
     if (NULL != s->intersection_set)
     {
-      GNUNET_SET_destroy (s->intersection_set);
+      GNUNET_SETI_destroy (s->intersection_set);
       s->intersection_set = NULL;
     }
     s->status = GNUNET_SCALARPRODUCT_STATUS_FAILURE;
@@ -729,7 +722,7 @@ cb_intersection_element_removed (void *cls,
  * @param other_peer the other peer
  * @param context_msg message with application specific information from
  *        the other peer
- * @param request request from the other peer (never NULL), use GNUNET_SET_accept()
+ * @param request request from the other peer (never NULL), use GNUNET_SETI_accept()
  *        to accept it, otherwise the request will be refused
  *        Note that we can't just return value from the listen callback,
  *        as it is also necessary to specify the set we want to do the
@@ -740,7 +733,7 @@ static void
 cb_intersection_request_alice (void *cls,
                                const struct GNUNET_PeerIdentity *other_peer,
                                const struct GNUNET_MessageHeader *context_msg,
-                               struct GNUNET_SET_Request *request)
+                               struct GNUNET_SETI_Request *request)
 {
   struct AliceServiceSession *s = cls;
 
@@ -752,11 +745,11 @@ cb_intersection_request_alice (void *cls,
     GNUNET_break_op (0);
     return;
   }
-  s->intersection_op = GNUNET_SET_accept (request,
-                                          GNUNET_SET_RESULT_REMOVED,
-                                          (struct GNUNET_SET_Option[]){ { 0 } },
-                                          &cb_intersection_element_removed,
-                                          s);
+  s->intersection_op = GNUNET_SETI_accept (request,
+                                           (struct
+                                            GNUNET_SETI_Option[]){ { 0 } },
+                                           &cb_intersection_element_removed,
+                                           s);
   if (NULL == s->intersection_op)
   {
     GNUNET_break (0);
@@ -764,7 +757,7 @@ cb_intersection_request_alice (void *cls,
     prepare_client_end_notification (s);
     return;
   }
-  if (GNUNET_OK != GNUNET_SET_commit (s->intersection_op, s->intersection_set))
+  if (GNUNET_OK != GNUNET_SETI_commit (s->intersection_op, s->intersection_set))
   {
     GNUNET_break (0);
     s->status = GNUNET_SCALARPRODUCT_STATUS_FAILURE;
@@ -812,11 +805,10 @@ client_request_complete_alice (struct AliceServiceSession *s)
     return;
   }
   s->cadet_mq = GNUNET_CADET_get_mq (s->channel);
-  s->intersection_listen = GNUNET_SET_listen (cfg,
-                                              GNUNET_SET_OPERATION_INTERSECTION,
-                                              &set_sid,
-                                              &cb_intersection_request_alice,
-                                              s);
+  s->intersection_listen = GNUNET_SETI_listen (cfg,
+                                               &set_sid,
+                                               &cb_intersection_request_alice,
+                                               s);
   if (NULL == s->intersection_listen)
   {
     s->status = GNUNET_SCALARPRODUCT_STATUS_FAILURE;
@@ -883,7 +875,7 @@ handle_alice_client_message_multipart (
   struct AliceServiceSession *s = cls;
   uint32_t contained_count;
   const struct GNUNET_SCALARPRODUCT_Element *elements;
-  struct GNUNET_SET_Element set_elem;
+  struct GNUNET_SETI_Element set_elem;
   struct GNUNET_SCALARPRODUCT_Element *elem;
 
   contained_count = ntohl (msg->element_count_contained);
@@ -908,7 +900,7 @@ handle_alice_client_message_multipart (
     set_elem.data = &elem->key;
     set_elem.size = sizeof(elem->key);
     set_elem.element_type = 0;
-    GNUNET_SET_add_element (s->intersection_set, &set_elem, NULL, NULL);
+    GNUNET_SETI_add_element (s->intersection_set, &set_elem, NULL, NULL);
     s->used_element_count++;
   }
   GNUNET_SERVICE_client_continue (s->client);
@@ -978,7 +970,7 @@ handle_alice_client_message (void *cls,
   uint32_t contained_count;
   uint32_t total_count;
   const struct GNUNET_SCALARPRODUCT_Element *elements;
-  struct GNUNET_SET_Element set_elem;
+  struct GNUNET_SETI_Element set_elem;
   struct GNUNET_SCALARPRODUCT_Element *elem;
 
   total_count = ntohl (msg->element_count_total);
@@ -991,8 +983,7 @@ handle_alice_client_message (void *cls,
   elements = (const struct GNUNET_SCALARPRODUCT_Element *) &msg[1];
   s->intersected_elements =
     GNUNET_CONTAINER_multihashmap_create (s->total, GNUNET_YES);
-  s->intersection_set =
-    GNUNET_SET_create (cfg, GNUNET_SET_OPERATION_INTERSECTION);
+  s->intersection_set = GNUNET_SETI_create (cfg);
   for (uint32_t i = 0; i < contained_count; i++)
   {
     if (0 == GNUNET_ntohll (elements[i].value))
@@ -1015,7 +1006,7 @@ handle_alice_client_message (void *cls,
     set_elem.data = &elem->key;
     set_elem.size = sizeof(elem->key);
     set_elem.element_type = 0;
-    GNUNET_SET_add_element (s->intersection_set, &set_elem, NULL, NULL);
+    GNUNET_SETI_add_element (s->intersection_set, &set_elem, NULL, NULL);
     s->used_element_count++;
   }
   GNUNET_SERVICE_client_continue (s->client);
diff --git a/src/scalarproduct/gnunet-service-scalarproduct-ecc_bob.c b/src/scalarproduct/gnunet-service-scalarproduct-ecc_bob.c
index 2da79f84539968c373577b5e311dec5a29edb099..4c835d52aecbcc6f5b3f644fdd8f64edff865a34 100644
--- a/src/scalarproduct/gnunet-service-scalarproduct-ecc_bob.c
+++ b/src/scalarproduct/gnunet-service-scalarproduct-ecc_bob.c
@@ -32,7 +32,7 @@
 #include "gnunet_applications.h"
 #include "gnunet_protocols.h"
 #include "gnunet_scalarproduct_service.h"
-#include "gnunet_set_service.h"
+#include "gnunet_seti_service.h"
 #include "scalarproduct.h"
 #include "gnunet-service-scalarproduct-ecc.h"
 
@@ -83,13 +83,13 @@ struct BobServiceSession
    * Set of elements for which we will be conducting an intersection.
    * The resulting elements are then used for computing the scalar product.
    */
-  struct GNUNET_SET_Handle *intersection_set;
+  struct GNUNET_SETI_Handle *intersection_set;
 
   /**
    * Set of elements for which will conduction an intersection.
    * the resulting elements are then used for computing the scalar product.
    */
-  struct GNUNET_SET_OperationHandle *intersection_op;
+  struct GNUNET_SETI_OperationHandle *intersection_op;
 
   /**
    * Our open port.
@@ -235,12 +235,12 @@ destroy_service_session (struct BobServiceSession *s)
   }
   if (NULL != s->intersection_op)
   {
-    GNUNET_SET_operation_cancel (s->intersection_op);
+    GNUNET_SETI_operation_cancel (s->intersection_op);
     s->intersection_op = NULL;
   }
   if (NULL != s->intersection_set)
   {
-    GNUNET_SET_destroy (s->intersection_set);
+    GNUNET_SETI_destroy (s->intersection_set);
     s->intersection_set = NULL;
   }
   if (NULL != s->sorted_elements)
@@ -578,22 +578,22 @@ handle_alices_cryptodata_message (void *cls,
  * that needs to be removed from the result set.
  *
  * @param cls closure with the `struct BobServiceSession`
- * @param element a result element, only valid if status is #GNUNET_SET_STATUS_OK
+ * @param element a result element, only valid if status is #GNUNET_SETI_STATUS_OK
  * @param current_size current set size
  * @param status what has happened with the set intersection?
  */
 static void
 cb_intersection_element_removed (void *cls,
-                                 const struct GNUNET_SET_Element *element,
+                                 const struct GNUNET_SETI_Element *element,
                                  uint64_t current_size,
-                                 enum GNUNET_SET_Status status)
+                                 enum GNUNET_SETI_Status status)
 {
   struct BobServiceSession *s = cls;
   struct GNUNET_SCALARPRODUCT_Element *se;
 
   switch (status)
   {
-  case GNUNET_SET_STATUS_OK:
+  case GNUNET_SETI_STATUS_DEL_LOCAL:
     /* this element has been removed from the set */
     se = GNUNET_CONTAINER_multihashmap_get (s->intersected_elements,
                                             element->data);
@@ -609,8 +609,7 @@ cb_intersection_element_removed (void *cls,
                      se));
     GNUNET_free (se);
     return;
-
-  case GNUNET_SET_STATUS_DONE:
+  case GNUNET_SETI_STATUS_DONE:
     s->intersection_op = NULL;
     GNUNET_break (NULL == s->intersection_set);
     GNUNET_CADET_receive_done (s->channel);
@@ -625,20 +624,14 @@ cb_intersection_element_removed (void *cls,
       transmit_bobs_cryptodata_message (s);
     }
     return;
-
-  case GNUNET_SET_STATUS_HALF_DONE:
-    /* unexpected for intersection */
-    GNUNET_break (0);
-    return;
-
-  case GNUNET_SET_STATUS_FAILURE:
+  case GNUNET_SETI_STATUS_FAILURE:
     /* unhandled status code */
     LOG (GNUNET_ERROR_TYPE_DEBUG,
          "Set intersection failed!\n");
     s->intersection_op = NULL;
     if (NULL != s->intersection_set)
     {
-      GNUNET_SET_destroy (s->intersection_set);
+      GNUNET_SETI_destroy (s->intersection_set);
       s->intersection_set = NULL;
     }
     s->status = GNUNET_SCALARPRODUCT_STATUS_FAILURE;
@@ -672,23 +665,22 @@ start_intersection (struct BobServiceSession *s)
               (unsigned int) s->total);
 
   s->intersection_op
-    = GNUNET_SET_prepare (&s->peer,
-                          &set_sid,
-                          NULL,
-                          GNUNET_SET_RESULT_REMOVED,
-                          (struct GNUNET_SET_Option[]) { { 0 } },
-                          &cb_intersection_element_removed,
-                          s);
+    = GNUNET_SETI_prepare (&s->peer,
+                           &set_sid,
+                           NULL,
+                           (struct GNUNET_SETI_Option[]) { { 0 } },
+                           &cb_intersection_element_removed,
+                           s);
   if (GNUNET_OK !=
-      GNUNET_SET_commit (s->intersection_op,
-                         s->intersection_set))
+      GNUNET_SETI_commit (s->intersection_op,
+                          s->intersection_set))
   {
     GNUNET_break (0);
     s->status = GNUNET_SCALARPRODUCT_STATUS_FAILURE;
     prepare_client_end_notification (s);
     return;
   }
-  GNUNET_SET_destroy (s->intersection_set);
+  GNUNET_SETI_destroy (s->intersection_set);
   s->intersection_set = NULL;
 }
 
@@ -797,7 +789,7 @@ handle_bob_client_message_multipart (void *cls,
   struct BobServiceSession *s = cls;
   uint32_t contained_count;
   const struct GNUNET_SCALARPRODUCT_Element *elements;
-  struct GNUNET_SET_Element set_elem;
+  struct GNUNET_SETI_Element set_elem;
   struct GNUNET_SCALARPRODUCT_Element *elem;
 
   contained_count = ntohl (msg->element_count_contained);
@@ -821,9 +813,9 @@ handle_bob_client_message_multipart (void *cls,
     set_elem.data = &elem->key;
     set_elem.size = sizeof(elem->key);
     set_elem.element_type = 0;
-    GNUNET_SET_add_element (s->intersection_set,
-                            &set_elem,
-                            NULL, NULL);
+    GNUNET_SETI_add_element (s->intersection_set,
+                             &set_elem,
+                             NULL, NULL);
   }
   s->client_received_element_count += contained_count;
   GNUNET_SERVICE_client_continue (s->client);
@@ -913,7 +905,7 @@ handle_bob_client_message (void *cls,
   uint32_t contained_count;
   uint32_t total_count;
   const struct GNUNET_SCALARPRODUCT_Element *elements;
-  struct GNUNET_SET_Element set_elem;
+  struct GNUNET_SETI_Element set_elem;
   struct GNUNET_SCALARPRODUCT_Element *elem;
 
   total_count = ntohl (msg->element_count_total);
@@ -927,9 +919,7 @@ handle_bob_client_message (void *cls,
   s->intersected_elements
     = GNUNET_CONTAINER_multihashmap_create (s->total,
                                             GNUNET_YES);
-  s->intersection_set
-    = GNUNET_SET_create (cfg,
-                         GNUNET_SET_OPERATION_INTERSECTION);
+  s->intersection_set = GNUNET_SETI_create (cfg);
   for (uint32_t i = 0; i < contained_count; i++)
   {
     if (0 == GNUNET_ntohll (elements[i].value))
@@ -951,9 +941,9 @@ handle_bob_client_message (void *cls,
     set_elem.data = &elem->key;
     set_elem.size = sizeof(elem->key);
     set_elem.element_type = 0;
-    GNUNET_SET_add_element (s->intersection_set,
-                            &set_elem,
-                            NULL, NULL);
+    GNUNET_SETI_add_element (s->intersection_set,
+                             &set_elem,
+                             NULL, NULL);
     s->used_element_count++;
   }
   GNUNET_SERVICE_client_continue (s->client);
diff --git a/src/scalarproduct/gnunet-service-scalarproduct_alice.c b/src/scalarproduct/gnunet-service-scalarproduct_alice.c
index 44534c8503013c1fa9c9209778edab50a16addde..1ca7f61dada0e5115bd5a2120a7651415a6e230d 100644
--- a/src/scalarproduct/gnunet-service-scalarproduct_alice.c
+++ b/src/scalarproduct/gnunet-service-scalarproduct_alice.c
@@ -32,7 +32,7 @@
 #include "gnunet_applications.h"
 #include "gnunet_protocols.h"
 #include "gnunet_scalarproduct_service.h"
-#include "gnunet_set_service.h"
+#include "gnunet_seti_service.h"
 #include "scalarproduct.h"
 #include "gnunet-service-scalarproduct.h"
 
@@ -99,18 +99,18 @@ struct AliceServiceSession
    * Set of elements for which will conduction an intersection.
    * the resulting elements are then used for computing the scalar product.
    */
-  struct GNUNET_SET_Handle *intersection_set;
+  struct GNUNET_SETI_Handle *intersection_set;
 
   /**
    * Set of elements for which will conduction an intersection.
    * the resulting elements are then used for computing the scalar product.
    */
-  struct GNUNET_SET_OperationHandle *intersection_op;
+  struct GNUNET_SETI_OperationHandle *intersection_op;
 
   /**
    * Handle to Alice's Intersection operation listening for Bob
    */
-  struct GNUNET_SET_ListenHandle *intersection_listen;
+  struct GNUNET_SETI_ListenHandle *intersection_listen;
 
   /**
    * channel-handle associated with our cadet handle
@@ -265,17 +265,17 @@ destroy_service_session (struct AliceServiceSession *s)
   }
   if (NULL != s->intersection_listen)
   {
-    GNUNET_SET_listen_cancel (s->intersection_listen);
+    GNUNET_SETI_listen_cancel (s->intersection_listen);
     s->intersection_listen = NULL;
   }
   if (NULL != s->intersection_op)
   {
-    GNUNET_SET_operation_cancel (s->intersection_op);
+    GNUNET_SETI_operation_cancel (s->intersection_op);
     s->intersection_op = NULL;
   }
   if (NULL != s->intersection_set)
   {
-    GNUNET_SET_destroy (s->intersection_set);
+    GNUNET_SETI_destroy (s->intersection_set);
     s->intersection_set = NULL;
   }
   if (NULL != s->sorted_elements)
@@ -894,22 +894,22 @@ send_alices_cryptodata_message (struct AliceServiceSession *s)
  * to indicate that the set intersection operation is done.
  *
  * @param cls closure with the `struct AliceServiceSession`
- * @param element a result element, only valid if status is #GNUNET_SET_STATUS_OK
+ * @param element a result element, only valid if status is #GNUNET_SETI_STATUS_OK
  * @param current_size current set size
  * @param status what has happened with the set intersection?
  */
 static void
 cb_intersection_element_removed (void *cls,
-                                 const struct GNUNET_SET_Element *element,
+                                 const struct GNUNET_SETI_Element *element,
                                  uint64_t current_size,
-                                 enum GNUNET_SET_Status status)
+                                 enum GNUNET_SETI_Status status)
 {
   struct AliceServiceSession *s = cls;
   struct GNUNET_SCALARPRODUCT_Element *se;
 
   switch (status)
   {
-  case GNUNET_SET_STATUS_OK:
+  case GNUNET_SETI_STATUS_DEL_LOCAL:
     /* this element has been removed from the set */
     se = GNUNET_CONTAINER_multihashmap_get (s->intersected_elements,
                                             element->data);
@@ -926,33 +926,27 @@ cb_intersection_element_removed (void *cls,
     GNUNET_free (se);
     return;
 
-  case GNUNET_SET_STATUS_DONE:
+  case GNUNET_SETI_STATUS_DONE:
     s->intersection_op = NULL;
     if (NULL != s->intersection_set)
     {
-      GNUNET_SET_destroy (s->intersection_set);
+      GNUNET_SETI_destroy (s->intersection_set);
       s->intersection_set = NULL;
     }
     send_alices_cryptodata_message (s);
     return;
-
-  case GNUNET_SET_STATUS_HALF_DONE:
-    /* unexpected for intersection */
-    GNUNET_break (0);
-    return;
-
-  case GNUNET_SET_STATUS_FAILURE:
+  case GNUNET_SETI_STATUS_FAILURE:
     /* unhandled status code */
     LOG (GNUNET_ERROR_TYPE_DEBUG, "Set intersection failed!\n");
     if (NULL != s->intersection_listen)
     {
-      GNUNET_SET_listen_cancel (s->intersection_listen);
+      GNUNET_SETI_listen_cancel (s->intersection_listen);
       s->intersection_listen = NULL;
     }
     s->intersection_op = NULL;
     if (NULL != s->intersection_set)
     {
-      GNUNET_SET_destroy (s->intersection_set);
+      GNUNET_SETI_destroy (s->intersection_set);
       s->intersection_set = NULL;
     }
     s->status = GNUNET_SCALARPRODUCT_STATUS_FAILURE;
@@ -974,7 +968,7 @@ cb_intersection_element_removed (void *cls,
  * @param other_peer the other peer
  * @param context_msg message with application specific information from
  *        the other peer
- * @param request request from the other peer (never NULL), use GNUNET_SET_accept()
+ * @param request request from the other peer (never NULL), use GNUNET_SETI_accept()
  *        to accept it, otherwise the request will be refused
  *        Note that we can't just return value from the listen callback,
  *        as it is also necessary to specify the set we want to do the
@@ -985,7 +979,7 @@ static void
 cb_intersection_request_alice (void *cls,
                                const struct GNUNET_PeerIdentity *other_peer,
                                const struct GNUNET_MessageHeader *context_msg,
-                               struct GNUNET_SET_Request *request)
+                               struct GNUNET_SETI_Request *request)
 {
   struct AliceServiceSession *s = cls;
 
@@ -994,11 +988,11 @@ cb_intersection_request_alice (void *cls,
     GNUNET_break_op (0);
     return;
   }
-  s->intersection_op = GNUNET_SET_accept (request,
-                                          GNUNET_SET_RESULT_REMOVED,
-                                          (struct GNUNET_SET_Option[]){ { 0 } },
-                                          &cb_intersection_element_removed,
-                                          s);
+  s->intersection_op = GNUNET_SETI_accept (request,
+                                           (struct
+                                            GNUNET_SETI_Option[]){ { 0 } },
+                                           &cb_intersection_element_removed,
+                                           s);
   if (NULL == s->intersection_op)
   {
     GNUNET_break (0);
@@ -1006,7 +1000,7 @@ cb_intersection_request_alice (void *cls,
     prepare_client_end_notification (s);
     return;
   }
-  if (GNUNET_OK != GNUNET_SET_commit (s->intersection_op, s->intersection_set))
+  if (GNUNET_OK != GNUNET_SETI_commit (s->intersection_op, s->intersection_set))
   {
     GNUNET_break (0);
     s->status = GNUNET_SCALARPRODUCT_STATUS_FAILURE;
@@ -1055,11 +1049,10 @@ client_request_complete_alice (struct AliceServiceSession *s)
     return;
   }
   s->cadet_mq = GNUNET_CADET_get_mq (s->channel);
-  s->intersection_listen = GNUNET_SET_listen (cfg,
-                                              GNUNET_SET_OPERATION_INTERSECTION,
-                                              &s->session_id,
-                                              &cb_intersection_request_alice,
-                                              s);
+  s->intersection_listen = GNUNET_SETI_listen (cfg,
+                                               &s->session_id,
+                                               &cb_intersection_request_alice,
+                                               s);
   if (NULL == s->intersection_listen)
   {
     s->status = GNUNET_SCALARPRODUCT_STATUS_FAILURE;
@@ -1125,7 +1118,7 @@ handle_alice_client_message_multipart (
   struct AliceServiceSession *s = cls;
   uint32_t contained_count;
   const struct GNUNET_SCALARPRODUCT_Element *elements;
-  struct GNUNET_SET_Element set_elem;
+  struct GNUNET_SETI_Element set_elem;
   struct GNUNET_SCALARPRODUCT_Element *elem;
 
   contained_count = ntohl (msg->element_count_contained);
@@ -1150,7 +1143,7 @@ handle_alice_client_message_multipart (
     set_elem.data = &elem->key;
     set_elem.size = sizeof(elem->key);
     set_elem.element_type = 0;
-    GNUNET_SET_add_element (s->intersection_set, &set_elem, NULL, NULL);
+    GNUNET_SETI_add_element (s->intersection_set, &set_elem, NULL, NULL);
     s->used_element_count++;
   }
   GNUNET_SERVICE_client_continue (s->client);
@@ -1217,7 +1210,7 @@ handle_alice_client_message (void *cls,
   uint32_t contained_count;
   uint32_t total_count;
   const struct GNUNET_SCALARPRODUCT_Element *elements;
-  struct GNUNET_SET_Element set_elem;
+  struct GNUNET_SETI_Element set_elem;
   struct GNUNET_SCALARPRODUCT_Element *elem;
 
   total_count = ntohl (msg->element_count_total);
@@ -1230,8 +1223,7 @@ handle_alice_client_message (void *cls,
   elements = (const struct GNUNET_SCALARPRODUCT_Element *) &msg[1];
   s->intersected_elements =
     GNUNET_CONTAINER_multihashmap_create (s->total, GNUNET_YES);
-  s->intersection_set =
-    GNUNET_SET_create (cfg, GNUNET_SET_OPERATION_INTERSECTION);
+  s->intersection_set = GNUNET_SETI_create (cfg);
 
   for (uint32_t i = 0; i < contained_count; i++)
   {
@@ -1255,7 +1247,10 @@ handle_alice_client_message (void *cls,
     set_elem.data = &elem->key;
     set_elem.size = sizeof(elem->key);
     set_elem.element_type = 0;
-    GNUNET_SET_add_element (s->intersection_set, &set_elem, NULL, NULL);
+    GNUNET_SETI_add_element (s->intersection_set,
+                             &set_elem,
+                             NULL,
+                             NULL);
     s->used_element_count++;
   }
   GNUNET_SERVICE_client_continue (s->client);
diff --git a/src/scalarproduct/gnunet-service-scalarproduct_bob.c b/src/scalarproduct/gnunet-service-scalarproduct_bob.c
index c000749af8b8c5bb2fc39617c8bb79f548253b73..b0299779d8f9cc15554445bd3eae316bb23d4a47 100644
--- a/src/scalarproduct/gnunet-service-scalarproduct_bob.c
+++ b/src/scalarproduct/gnunet-service-scalarproduct_bob.c
@@ -32,7 +32,7 @@
 #include "gnunet_applications.h"
 #include "gnunet_protocols.h"
 #include "gnunet_scalarproduct_service.h"
-#include "gnunet_set_service.h"
+#include "gnunet_seti_service.h"
 #include "scalarproduct.h"
 #include "gnunet-service-scalarproduct.h"
 
@@ -88,13 +88,13 @@ struct BobServiceSession
    * Set of elements for which we will be conducting an intersection.
    * The resulting elements are then used for computing the scalar product.
    */
-  struct GNUNET_SET_Handle *intersection_set;
+  struct GNUNET_SETI_Handle *intersection_set;
 
   /**
    * Set of elements for which will conduction an intersection.
    * the resulting elements are then used for computing the scalar product.
    */
-  struct GNUNET_SET_OperationHandle *intersection_op;
+  struct GNUNET_SETI_OperationHandle *intersection_op;
 
   /**
    * CADET port we are listening on.
@@ -277,12 +277,12 @@ destroy_service_session (struct BobServiceSession *s)
   }
   if (NULL != s->intersection_op)
   {
-    GNUNET_SET_operation_cancel (s->intersection_op);
+    GNUNET_SETI_operation_cancel (s->intersection_op);
     s->intersection_op = NULL;
   }
   if (NULL != s->intersection_set)
   {
-    GNUNET_SET_destroy (s->intersection_set);
+    GNUNET_SETI_destroy (s->intersection_set);
     s->intersection_set = NULL;
   }
   if (NULL != s->e_a)
@@ -888,22 +888,22 @@ handle_alices_cryptodata_message (void *cls,
  * that needs to be removed from the result set.
  *
  * @param cls closure with the `struct BobServiceSession`
- * @param element a result element, only valid if status is #GNUNET_SET_STATUS_OK
+ * @param element a result element, only valid if status is #GNUNET_SETI_STATUS_OK
  * @param current_size current set size
  * @param status what has happened with the set intersection?
  */
 static void
 cb_intersection_element_removed (void *cls,
-                                 const struct GNUNET_SET_Element *element,
+                                 const struct GNUNET_SETI_Element *element,
                                  uint64_t current_size,
-                                 enum GNUNET_SET_Status status)
+                                 enum GNUNET_SETI_Status status)
 {
   struct BobServiceSession *s = cls;
   struct GNUNET_SCALARPRODUCT_Element *se;
 
   switch (status)
   {
-  case GNUNET_SET_STATUS_OK:
+  case GNUNET_SETI_STATUS_DEL_LOCAL:
     /* this element has been removed from the set */
     se = GNUNET_CONTAINER_multihashmap_get (s->intersected_elements,
                                             element->data);
@@ -919,8 +919,7 @@ cb_intersection_element_removed (void *cls,
                      se));
     GNUNET_free (se);
     return;
-
-  case GNUNET_SET_STATUS_DONE:
+  case GNUNET_SETI_STATUS_DONE:
     s->intersection_op = NULL;
     GNUNET_break (NULL == s->intersection_set);
     GNUNET_CADET_receive_done (s->channel);
@@ -935,26 +934,19 @@ cb_intersection_element_removed (void *cls,
       transmit_cryptographic_reply (s);
     }
     return;
-
-  case GNUNET_SET_STATUS_HALF_DONE:
-    /* unexpected for intersection */
-    GNUNET_break (0);
-    return;
-
-  case GNUNET_SET_STATUS_FAILURE:
+  case GNUNET_SETI_STATUS_FAILURE:
     /* unhandled status code */
     LOG (GNUNET_ERROR_TYPE_DEBUG,
          "Set intersection failed!\n");
     s->intersection_op = NULL;
     if (NULL != s->intersection_set)
     {
-      GNUNET_SET_destroy (s->intersection_set);
+      GNUNET_SETI_destroy (s->intersection_set);
       s->intersection_set = NULL;
     }
     s->status = GNUNET_SCALARPRODUCT_STATUS_FAILURE;
     prepare_client_end_notification (s);
     return;
-
   default:
     GNUNET_break (0);
     return;
@@ -977,23 +969,22 @@ start_intersection (struct BobServiceSession *s)
               (unsigned int) s->total);
 
   s->intersection_op
-    = GNUNET_SET_prepare (&s->peer,
-                          &s->session_id,
-                          NULL,
-                          GNUNET_SET_RESULT_REMOVED,
-                          (struct GNUNET_SET_Option[]) { { 0 } },
-                          &cb_intersection_element_removed,
-                          s);
+    = GNUNET_SETI_prepare (&s->peer,
+                           &s->session_id,
+                           NULL,
+                           (struct GNUNET_SETI_Option[]) { { 0 } },
+                           &cb_intersection_element_removed,
+                           s);
   if (GNUNET_OK !=
-      GNUNET_SET_commit (s->intersection_op,
-                         s->intersection_set))
+      GNUNET_SETI_commit (s->intersection_op,
+                          s->intersection_set))
   {
     GNUNET_break (0);
     s->status = GNUNET_SCALARPRODUCT_STATUS_FAILURE;
     prepare_client_end_notification (s);
     return;
   }
-  GNUNET_SET_destroy (s->intersection_set);
+  GNUNET_SETI_destroy (s->intersection_set);
   s->intersection_set = NULL;
 }
 
@@ -1096,7 +1087,7 @@ handle_bob_client_message_multipart (void *cls,
   struct BobServiceSession *s = cls;
   uint32_t contained_count;
   const struct GNUNET_SCALARPRODUCT_Element *elements;
-  struct GNUNET_SET_Element set_elem;
+  struct GNUNET_SETI_Element set_elem;
   struct GNUNET_SCALARPRODUCT_Element *elem;
 
   contained_count = ntohl (msg->element_count_contained);
@@ -1120,9 +1111,9 @@ handle_bob_client_message_multipart (void *cls,
     set_elem.data = &elem->key;
     set_elem.size = sizeof(elem->key);
     set_elem.element_type = 0;
-    GNUNET_SET_add_element (s->intersection_set,
-                            &set_elem,
-                            NULL, NULL);
+    GNUNET_SETI_add_element (s->intersection_set,
+                             &set_elem,
+                             NULL, NULL);
   }
   s->client_received_element_count += contained_count;
   GNUNET_SERVICE_client_continue (s->client);
@@ -1206,7 +1197,7 @@ handle_bob_client_message (void *cls,
   uint32_t contained_count;
   uint32_t total_count;
   const struct GNUNET_SCALARPRODUCT_Element *elements;
-  struct GNUNET_SET_Element set_elem;
+  struct GNUNET_SETI_Element set_elem;
   struct GNUNET_SCALARPRODUCT_Element *elem;
 
   total_count = ntohl (msg->element_count_total);
@@ -1220,9 +1211,7 @@ handle_bob_client_message (void *cls,
   s->intersected_elements
     = GNUNET_CONTAINER_multihashmap_create (s->total,
                                             GNUNET_YES);
-  s->intersection_set
-    = GNUNET_SET_create (cfg,
-                         GNUNET_SET_OPERATION_INTERSECTION);
+  s->intersection_set = GNUNET_SETI_create (cfg);
   for (uint32_t i = 0; i < contained_count; i++)
   {
     if (0 == GNUNET_ntohll (elements[i].value))
@@ -1244,9 +1233,9 @@ handle_bob_client_message (void *cls,
     set_elem.data = &elem->key;
     set_elem.size = sizeof(elem->key);
     set_elem.element_type = 0;
-    GNUNET_SET_add_element (s->intersection_set,
-                            &set_elem,
-                            NULL, NULL);
+    GNUNET_SETI_add_element (s->intersection_set,
+                             &set_elem,
+                             NULL, NULL);
     s->used_element_count++;
   }
   GNUNET_SERVICE_client_continue (s->client);
diff --git a/src/scalarproduct/perf_scalarproduct.sh b/src/scalarproduct/perf_scalarproduct.sh
new file mode 100755
index 0000000000000000000000000000000000000000..a7935873e4a0142cb9664241cc65743af67054c9
--- /dev/null
+++ b/src/scalarproduct/perf_scalarproduct.sh
@@ -0,0 +1,60 @@
+#!/bin/bash
+# Computes a simple scalar product, with configurable vector size.
+#
+# Some results (wall-clock for Alice+Bob, single-core, i7):
+# SIZE   2048-H(s)  2048-O(s)    1024-O(s)      ECC-2^20-H(s)  ECC-2^28-H(s)
+#  25     10          14            3              2               29
+#  50     17          21            5              2               29
+# 100     32          39            7              2               29
+# 200                 77           13              3               30
+# 400                149           23             OOR              31
+# 800                304           32             OOR              33
+
+# Bandwidth (including set intersection):
+#              RSA-2048       ECC
+# 800:         3846 kb       70 kb
+# Configure benchmark size:
+SIZE=800
+#
+# Construct input vectors:
+INPUTALICE="-k CCC -e '"
+INPUTBOB="-k CCC -e '"
+for X in `seq 1 $SIZE`
+do
+  INPUTALICE="${INPUTALICE}A${X},$X;"
+  INPUTBOB="${INPUTBOB}A${X},$X;"
+done
+INPUTALICE="${INPUTALICE}BC,-20000;RO,1000;FL,100;LOL,24;'"
+INPUTBOB="${INPUTBOB}AB,10;RO,3;FL,3;LOL,-1;'"
+
+# necessary to make the testing prefix deterministic, so we can access the config files
+PREFIX=/tmp/test-scalarproduct`date +%H%M%S`
+
+# where can we find the peers config files?
+CFGALICE="-c $PREFIX/0/config"
+CFGBOB="-c $PREFIX/1/config"
+
+# launch two peers in line topology non-interactively
+#
+# interactive mode would terminate the test immediately
+# because the rest of the script is already in stdin,
+# thus redirecting stdin does not suffice)
+#GNUNET_FORCE_LOG=';;;;ERROR'
+#GNUNET_FORCE_LOG='scalarproduct*;;;;DEBUG/cadet-api*;;;;DEBUG'
+GNUNET_TESTING_PREFIX=$PREFIX ../testbed/gnunet-testbed-profiler -n -c test_scalarproduct.conf -p 2 &
+PID=$!
+# sleep 1 is too short on most systems, 2 works on most, 5 seems to be safe
+echo "Waiting for peers to start..."
+sleep 5
+# get Bob's peer ID, necessary for Alice
+PEERIDBOB=`gnunet-peerinfo -qs $CFGBOB`
+
+echo "Running problem of size $SIZE"
+gnunet-scalarproduct $CFGBOB $INPUTBOB &
+time RESULT=`gnunet-scalarproduct $CFGALICE $INPUTALICE -p $PEERIDBOB`
+gnunet-statistics $CFGALICE -s core | grep "bytes encrypted"
+gnunet-statistics $CFGBOB -s core | grep "bytes encrypted"
+
+echo "Terminating testbed..."
+# terminate the testbed
+kill $PID
diff --git a/src/secretsharing/.gitignore b/src/secretsharing/.gitignore
new file mode 100644
index 0000000000000000000000000000000000000000..fe9db53a4acb702faf9c613a07bc895840c6f302
--- /dev/null
+++ b/src/secretsharing/.gitignore
@@ -0,0 +1,3 @@
+gnunet-service-secretsharing
+gnunet-secretsharing-profiler
+test_secretsharing_api
diff --git a/src/set/.gitignore b/src/set/.gitignore
new file mode 100644
index 0000000000000000000000000000000000000000..f1c95863950a5b8d0cee911963955531f60d9f2f
--- /dev/null
+++ b/src/set/.gitignore
@@ -0,0 +1,7 @@
+gnunet-set-profiler
+gnunet-service-set
+gnunet-set-ibf-profiler
+test_set_api
+test_set_intersection_result_full
+test_set_union_copy
+test_set_union_result_symmetric
diff --git a/src/set/gnunet-service-set_intersection.c b/src/set/gnunet-service-set_intersection.c
index 993cead1145ea57c94a37615e5c07e9bfe676bdf..9313483bb28ef560b4255a6dbb2d6c7e696fda96 100644
--- a/src/set/gnunet-service-set_intersection.c
+++ b/src/set/gnunet-service-set_intersection.c
@@ -868,7 +868,7 @@ process_bf (struct Operation *op)
                   GNUNET_CONTAINER_multihashmap_size (op->state->my_elements));
       op->state->full_result_iter
         = GNUNET_CONTAINER_multihashmap_iterator_create (
-        op->state->my_elements);
+            op->state->my_elements);
       send_remaining_elements (op);
       return;
     }
diff --git a/src/set/gnunet-service-set_union_strata_estimator.c b/src/set/gnunet-service-set_union_strata_estimator.c
index 1101a56a615f580fd5ad22add29914d594a34cee..97b4a1f98b994e21a00312131aa4fe0d167b9ee7 100644
--- a/src/set/gnunet-service-set_union_strata_estimator.c
+++ b/src/set/gnunet-service-set_union_strata_estimator.c
@@ -149,7 +149,7 @@ strata_estimator_insert (struct StrataEstimator *se,
 
   v = key.key_val;
   /* count trailing '1'-bits of v */
-  for (i = 0; v &1; v >>= 1, i++)
+  for (i = 0; v & 1; v >>= 1, i++)
     /* empty */;
   ibf_insert (se->strata[i], key);
 }
@@ -170,7 +170,7 @@ strata_estimator_remove (struct StrataEstimator *se,
 
   v = key.key_val;
   /* count trailing '1'-bits of v */
-  for (i = 0; v &1; v >>= 1, i++)
+  for (i = 0; v & 1; v >>= 1, i++)
     /* empty */;
   ibf_remove (se->strata[i], key);
 }
diff --git a/src/set/ibf_sim.c b/src/set/ibf_sim.c
new file mode 100644
index 0000000000000000000000000000000000000000..6415d00e1d665af0626ae1f2b27967c98071c6f1
--- /dev/null
+++ b/src/set/ibf_sim.c
@@ -0,0 +1,142 @@
+/*
+      This file is part of GNUnet
+      Copyright (C) 2013 GNUnet e.V.
+
+      GNUnet is free software: you can redistribute it and/or modify it
+      under the terms of the GNU Affero General Public License as published
+      by the Free Software Foundation, either version 3 of the License,
+      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
+      Affero General Public License for more details.
+
+      You should have received a copy of the GNU Affero General Public License
+      along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+     SPDX-License-Identifier: AGPL3.0-or-later
+ */
+
+/**
+ * @file set/ibf_sim.c
+ * @brief implementation of simulation for invertible bloom filter
+ * @author Florian Dold
+ *
+ * This code was used for some internal experiments, it is not
+ * build or shipped as part of the GNUnet system.
+ */
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#define MAX_IBF_DECODE 16
+
+/* report average over how many rounds? */
+#define ROUNDS 100000
+
+/* enable one of the three below */
+// simple fix
+#define FIX1 0
+// possibly slightly better fix for large IBF_DECODE values
+#define FIX2 1
+
+// SIGCOMM algorithm
+#define STRATA 0
+
+// print each value?
+#define VERBOSE 0
+// avoid assembly? (ASM is about 50% faster)
+#define SLOW 0
+
+int
+main (int argc, char **argv)
+{
+  unsigned int round;
+  unsigned int buckets[31]; // max is 2^31 as 'random' returns only between 0 and 2^31
+  unsigned int i;
+  int j;
+  unsigned int r;
+  unsigned int ret;
+  unsigned long long total;
+  unsigned int want;
+  double predict;
+
+  srandom (time (NULL));
+  total = 0;
+  want = atoi (argv[1]);
+  for (round = 0; round < ROUNDS; round++)
+  {
+    memset (buckets, 0, sizeof(buckets));
+    for (i = 0; i < want; i++)
+    {
+      /* FIXME: might want to use 'better' PRNG to avoid
+         PRNG-induced biases */
+      r = random ();
+      if (0 == r)
+        continue;
+#if SLOW
+      for (j = 0; (j < 31) && (0 == (r & (1 << j))); j++)
+        ;
+#else
+      /* use assembly / gcc */
+      j = __builtin_ffs (r) - 1;
+#endif
+      buckets[j]++;
+    }
+    ret = 0;
+    predict = 0.0;
+    for (j = 31; j >= 0; j--)
+    {
+#if FIX1
+      /* improved algorithm, for 1000 elements with IBF-DECODE 8, I
+         get 990/1000 elements on average over 1 million runs; key
+         idea being to stop short of the 'last' possible IBF as
+         otherwise a "lowball" per-chance would unduely influence the
+         result */if ((j > 0) &&
+          (buckets[j - 1] > MAX_IBF_DECODE))
+      {
+        ret *= (1 << (j + 1));
+        break;
+      }
+#endif
+#if FIX2
+      /* another improvement: don't just always cut off the last one,
+         but rather try to predict based on all previous values where
+         that "last" one is; additional prediction can only really
+         work if MAX_IBF_DECODE is sufficiently high */
+      if ((j > 0) &&
+          ((buckets[j - 1] > MAX_IBF_DECODE) ||
+           (predict > MAX_IBF_DECODE)))
+      {
+        ret *= (1 << (j + 1));
+        break;
+      }
+#endif
+#if STRATA
+      /* original algorithm, for 1000 elements with IBF-DECODE 8,
+         I get 920/1000 elements on average over 1 million runs */
+      if (buckets[j] > MAX_IBF_DECODE)
+      {
+        ret *= (1 << (j + 1));
+        break;
+      }
+#endif
+      ret += buckets[j];
+      predict = (buckets[j] + 2.0 * predict) / 2.0;
+    }
+#if VERBOSE
+    fprintf (stderr, "%u ", ret);
+#endif
+    total += ret;
+  }
+  fprintf (stderr, "\n");
+  fprintf (stdout, "average %llu\n", total / ROUNDS);
+  return 0;
+}
+
+
+/* TODO: should calculate stddev of the results to also be able to
+   say something about the stability of the results, outside of
+   large-scale averages -- gaining 8% precision at the expense of
+   50% additional variance might not be worth it... */
diff --git a/src/seti/.gitignore b/src/seti/.gitignore
new file mode 100644
index 0000000000000000000000000000000000000000..5f234a4c2164a98693374c1b2f9b37605d4374ef
--- /dev/null
+++ b/src/seti/.gitignore
@@ -0,0 +1,3 @@
+gnunet-seti-profiler
+gnunet-service-seti
+test_seti_api
diff --git a/src/seti/Makefile.am b/src/seti/Makefile.am
new file mode 100644
index 0000000000000000000000000000000000000000..522f33ece0e2904fb9ee7823fb72effb74438fa7
--- /dev/null
+++ b/src/seti/Makefile.am
@@ -0,0 +1,90 @@
+# This Makefile.am is in the public domain
+AM_CPPFLAGS = -I$(top_srcdir)/src/include
+
+pkgcfgdir= $(pkgdatadir)/config.d/
+
+libexecdir= $(pkglibdir)/libexec/
+
+plugindir = $(libdir)/gnunet
+
+pkgcfg_DATA = \
+  seti.conf
+
+if USE_COVERAGE
+  AM_CFLAGS = -fprofile-arcs -ftest-coverage
+endif
+
+if HAVE_TESTING
+bin_PROGRAMS = \
+ gnunet-seti-profiler
+endif
+
+libexec_PROGRAMS = \
+ gnunet-service-seti
+
+lib_LTLIBRARIES = \
+  libgnunetseti.la
+
+gnunet_seti_profiler_SOURCES = \
+ gnunet-seti-profiler.c
+gnunet_seti_profiler_LDADD = \
+  $(top_builddir)/src/util/libgnunetutil.la \
+  $(top_builddir)/src/statistics/libgnunetstatistics.la \
+  libgnunetseti.la \
+  $(top_builddir)/src/testing/libgnunettesting.la \
+  $(GN_LIBINTL)
+
+
+gnunet_service_seti_SOURCES = \
+ gnunet-service-seti.c \
+ gnunet-service-seti_protocol.h
+gnunet_service_seti_LDADD = \
+  $(top_builddir)/src/util/libgnunetutil.la \
+  $(top_builddir)/src/statistics/libgnunetstatistics.la \
+  $(top_builddir)/src/core/libgnunetcore.la \
+  $(top_builddir)/src/cadet/libgnunetcadet.la \
+  $(top_builddir)/src/block/libgnunetblock.la \
+  libgnunetseti.la \
+  $(GN_LIBINTL)
+
+libgnunetseti_la_SOURCES = \
+  seti_api.c seti.h
+libgnunetseti_la_LIBADD = \
+  $(top_builddir)/src/util/libgnunetutil.la \
+  $(LTLIBINTL)
+libgnunetseti_la_LDFLAGS = \
+  $(GN_LIB_LDFLAGS)
+
+if HAVE_TESTING
+check_PROGRAMS = \
+ test_seti_api
+endif
+
+if ENABLE_TEST_RUN
+AM_TESTS_ENVIRONMENT=export GNUNET_PREFIX=$${GNUNET_PREFIX:-@libdir@};export PATH=$${GNUNET_PREFIX:-@prefix@}/bin:$$PATH;unset XDG_DATA_HOME;unset XDG_CONFIG_HOME;
+TESTS = $(check_PROGRAMS)
+endif
+
+test_seti_api_SOURCES = \
+ test_seti_api.c
+test_seti_api_LDADD = \
+  $(top_builddir)/src/util/libgnunetutil.la \
+  $(top_builddir)/src/testing/libgnunettesting.la \
+  libgnunetseti.la
+
+plugin_LTLIBRARIES = \
+  libgnunet_plugin_block_seti_test.la
+
+libgnunet_plugin_block_seti_test_la_SOURCES = \
+  plugin_block_seti_test.c
+libgnunet_plugin_block_seti_test_la_LIBADD = \
+  $(top_builddir)/src/block/libgnunetblock.la \
+  $(top_builddir)/src/block/libgnunetblockgroup.la \
+  $(top_builddir)/src/util/libgnunetutil.la \
+  $(LTLIBINTL)
+libgnunet_plugin_block_seti_test_la_LDFLAGS = \
+ $(GN_PLUGIN_LDFLAGS)
+
+
+EXTRA_DIST = \
+  test_seti.conf
diff --git a/src/seti/gnunet-service-seti.c b/src/seti/gnunet-service-seti.c
new file mode 100644
index 0000000000000000000000000000000000000000..af478233b9d09a8b8dfed2678d0f742446b415a3
--- /dev/null
+++ b/src/seti/gnunet-service-seti.c
@@ -0,0 +1,2515 @@
+/*
+      This file is part of GNUnet
+      Copyright (C) 2013-2017, 2020 GNUnet e.V.
+
+      GNUnet is free software: you can redistribute it and/or modify it
+      under the terms of the GNU Affero General Public License as published
+      by the Free Software Foundation, either version 3 of the License,
+      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
+      Affero General Public License for more details.
+
+      You should have received a copy of the GNU Affero General Public License
+      along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+     SPDX-License-Identifier: AGPL3.0-or-later
+ */
+/**
+ * @file set/gnunet-service-seti.c
+ * @brief two-peer set intersection operations
+ * @author Florian Dold
+ * @author Christian Grothoff
+ */
+#include "gnunet-service-seti_protocol.h"
+#include "gnunet_statistics_service.h"
+#include "gnunet_cadet_service.h"
+#include "gnunet_seti_service.h"
+#include "gnunet_block_lib.h"
+#include "seti.h"
+
+/**
+ * How long do we hold on to an incoming channel if there is
+ * no local listener before giving up?
+ */
+#define INCOMING_CHANNEL_TIMEOUT GNUNET_TIME_UNIT_MINUTES
+
+
+/**
+ * Current phase we are in for a intersection operation.
+ */
+enum IntersectionOperationPhase
+{
+  /**
+   * We are just starting.
+   */
+  PHASE_INITIAL,
+
+  /**
+   * We have send the number of our elements to the other
+   * peer, but did not setup our element set yet.
+   */
+  PHASE_COUNT_SENT,
+
+  /**
+   * We have initialized our set and are now reducing it by exchanging
+   * Bloom filters until one party notices the their element hashes
+   * are equal.
+   */
+  PHASE_BF_EXCHANGE,
+
+  /**
+   * We must next send the P2P DONE message (after finishing mostly
+   * with the local client).  Then we will wait for the channel to close.
+   */
+  PHASE_MUST_SEND_DONE,
+
+  /**
+   * We have received the P2P DONE message, and must finish with the
+   * local client before terminating the channel.
+   */
+  PHASE_DONE_RECEIVED,
+
+  /**
+   * The protocol is over.  Results may still have to be sent to the
+   * client.
+   */
+  PHASE_FINISHED
+};
+
+
+/**
+ * A set that supports a specific operation with other peers.
+ */
+struct Set;
+
+/**
+ * Information about an element element in the set.  All elements are
+ * stored in a hash-table from their hash-code to their 'struct
+ * Element', so that the remove and add operations are reasonably
+ * fast.
+ */
+struct ElementEntry;
+
+/**
+ * Operation context used to execute a set operation.
+ */
+struct Operation;
+
+
+/**
+ * Information about an element element in the set.  All elements are
+ * stored in a hash-table from their hash-code to their `struct
+ * Element`, so that the remove and add operations are reasonably
+ * fast.
+ */
+struct ElementEntry
+{
+  /**
+   * The actual element. The data for the element
+   * should be allocated at the end of this struct.
+   */
+  struct GNUNET_SETI_Element element;
+
+  /**
+   * Hash of the element.  For set union: Will be used to derive the
+   * different IBF keys for different salts.
+   */
+  struct GNUNET_HashCode element_hash;
+
+  /**
+   * Generation in which the element was added.
+   */
+  unsigned int generation_added;
+
+  /**
+   * #GNUNET_YES if the element is a remote element, and does not belong
+   * to the operation's set.
+   */
+  int remote;
+};
+
+
+/**
+ * A listener is inhabited by a client, and waits for evaluation
+ * requests from remote peers.
+ */
+struct Listener;
+
+
+/**
+ * State we keep per client.
+ */
+struct ClientState
+{
+  /**
+   * Set, if associated with the client, otherwise NULL.
+   */
+  struct Set *set;
+
+  /**
+   * Listener, if associated with the client, otherwise NULL.
+   */
+  struct Listener *listener;
+
+  /**
+   * Client handle.
+   */
+  struct GNUNET_SERVICE_Client *client;
+
+  /**
+   * Message queue.
+   */
+  struct GNUNET_MQ_Handle *mq;
+};
+
+
+/**
+ * Operation context used to execute a set operation.
+ */
+struct Operation
+{
+  /**
+   * The identity of the requesting peer.  Needs to
+   * be stored here as the op spec might not have been created yet.
+   */
+  struct GNUNET_PeerIdentity peer;
+
+  /**
+   * XOR of the keys of all of the elements (remaining) in my set.
+   * Always updated when elements are added or removed to
+   * @e my_elements.
+   */
+  struct GNUNET_HashCode my_xor;
+
+  /**
+   * XOR of the keys of all of the elements (remaining) in
+   * the other peer's set.  Updated when we receive the
+   * other peer's Bloom filter.
+   */
+  struct GNUNET_HashCode other_xor;
+
+  /**
+   * Kept in a DLL of the listener, if @e listener is non-NULL.
+   */
+  struct Operation *next;
+
+  /**
+   * Kept in a DLL of the listener, if @e listener is non-NULL.
+   */
+  struct Operation *prev;
+
+  /**
+   * Channel to the peer.
+   */
+  struct GNUNET_CADET_Channel *channel;
+
+  /**
+   * Port this operation runs on.
+   */
+  struct Listener *listener;
+
+  /**
+   * Message queue for the channel.
+   */
+  struct GNUNET_MQ_Handle *mq;
+
+  /**
+   * Context message, may be NULL.
+   */
+  struct GNUNET_MessageHeader *context_msg;
+
+  /**
+   * Set associated with the operation, NULL until the spec has been
+   * associated with a set.
+   */
+  struct Set *set;
+
+  /**
+   * The bf we currently receive
+   */
+  struct GNUNET_CONTAINER_BloomFilter *remote_bf;
+
+  /**
+   * BF of the set's element.
+   */
+  struct GNUNET_CONTAINER_BloomFilter *local_bf;
+
+  /**
+   * Remaining elements in the intersection operation.
+   * Maps element-id-hashes to 'elements in our set'.
+   */
+  struct GNUNET_CONTAINER_MultiHashMap *my_elements;
+
+  /**
+   * Iterator for sending the final set of @e my_elements to the client.
+   */
+  struct GNUNET_CONTAINER_MultiHashMapIterator *full_result_iter;
+
+  /**
+   * For multipart BF transmissions, we have to store the
+   * bloomfilter-data until we fully received it.
+   */
+  char *bf_data;
+
+  /**
+   * Timeout task, if the incoming peer has not been accepted
+   * after the timeout, it will be disconnected.
+   */
+  struct GNUNET_SCHEDULER_Task *timeout_task;
+
+  /**
+   * How many bytes of @e bf_data are valid?
+   */
+  uint32_t bf_data_offset;
+
+  /**
+   * Current element count contained within @e my_elements.
+   * (May differ briefly during initialization.)
+   */
+  uint32_t my_element_count;
+
+  /**
+   * size of the bloomfilter in @e bf_data.
+   */
+  uint32_t bf_data_size;
+
+  /**
+   * size of the bloomfilter
+   */
+  uint32_t bf_bits_per_element;
+
+  /**
+   * Salt currently used for BF construction (by us or the other peer,
+   * depending on where we are in the code).
+   */
+  uint32_t salt;
+
+  /**
+   * Current state of the operation.
+   */
+  enum IntersectionOperationPhase phase;
+
+  /**
+   * Generation in which the operation handle was created.
+   */
+  unsigned int generation_created;
+
+  /**
+   * Did we send the client that we are done?
+   */
+  int client_done_sent;
+
+  /**
+   * Set whenever we reach the state where the death of the
+   * channel is perfectly find and should NOT result in the
+   * operation being cancelled.
+   */
+  int channel_death_expected;
+
+  /**
+   * Remote peers element count
+   */
+  uint32_t remote_element_count;
+
+  /**
+   * ID used to identify an operation between service and client
+   */
+  uint32_t client_request_id;
+
+  /**
+   * When are elements sent to the client, and which elements are sent?
+   */
+  int return_intersection;
+
+  /**
+   * Unique request id for the request from a remote peer, sent to the
+   * client, which will accept or reject the request.  Set to '0' iff
+   * the request has not been suggested yet.
+   */
+  uint32_t suggest_id;
+
+};
+
+
+/**
+ * SetContent stores the actual set elements, which may be shared by
+ * multiple generations derived from one set.
+ */
+struct SetContent
+{
+  /**
+   * Maps `struct GNUNET_HashCode *` to `struct ElementEntry *`.
+   */
+  struct GNUNET_CONTAINER_MultiHashMap *elements;
+
+  /**
+   * Number of references to the content.
+   */
+  unsigned int refcount;
+
+  /**
+   * FIXME: document!
+   */
+  unsigned int latest_generation;
+
+  /**
+   * Number of concurrently active iterators.
+   */
+  int iterator_count;
+};
+
+
+/**
+ * A set that supports a specific operation with other peers.
+ */
+struct Set
+{
+  /**
+   * Sets are held in a doubly linked list (in `sets_head` and `sets_tail`).
+   */
+  struct Set *next;
+
+  /**
+   * Sets are held in a doubly linked list.
+   */
+  struct Set *prev;
+
+  /**
+   * Client that owns the set.  Only one client may own a set,
+   * and there can only be one set per client.
+   */
+  struct ClientState *cs;
+
+  /**
+   * Content, possibly shared by multiple sets,
+   * and thus reference counted.
+   */
+  struct SetContent *content;
+
+  /**
+   * Number of currently valid elements in the set which have not been
+   * removed.
+   */
+  uint32_t current_set_element_count;
+
+  /**
+   * Evaluate operations are held in a linked list.
+   */
+  struct Operation *ops_head;
+
+  /**
+   * Evaluate operations are held in a linked list.
+   */
+  struct Operation *ops_tail;
+
+  /**
+   * Current generation, that is, number of previously executed
+   * operations and lazy copies on the underlying set content.
+   */
+  unsigned int current_generation;
+
+};
+
+
+/**
+ * A listener is inhabited by a client, and waits for evaluation
+ * requests from remote peers.
+ */
+struct Listener
+{
+  /**
+   * Listeners are held in a doubly linked list.
+   */
+  struct Listener *next;
+
+  /**
+   * Listeners are held in a doubly linked list.
+   */
+  struct Listener *prev;
+
+  /**
+   * Head of DLL of operations this listener is responsible for.
+   * Once the client has accepted/declined the operation, the
+   * operation is moved to the respective set's operation DLLS.
+   */
+  struct Operation *op_head;
+
+  /**
+   * Tail of DLL of operations this listener is responsible for.
+   * Once the client has accepted/declined the operation, the
+   * operation is moved to the respective set's operation DLLS.
+   */
+  struct Operation *op_tail;
+
+  /**
+   * Client that owns the listener.
+   * Only one client may own a listener.
+   */
+  struct ClientState *cs;
+
+  /**
+   * The port we are listening on with CADET.
+   */
+  struct GNUNET_CADET_Port *open_port;
+
+  /**
+   * Application ID for the operation, used to distinguish
+   * multiple operations of the same type with the same peer.
+   */
+  struct GNUNET_HashCode app_id;
+
+};
+
+
+/**
+ * Handle to the cadet service, used to listen for and connect to
+ * remote peers.
+ */
+static struct GNUNET_CADET_Handle *cadet;
+
+/**
+ * Statistics handle.
+ */
+static struct GNUNET_STATISTICS_Handle *_GSS_statistics;
+
+/**
+ * Listeners are held in a doubly linked list.
+ */
+static struct Listener *listener_head;
+
+/**
+ * Listeners are held in a doubly linked list.
+ */
+static struct Listener *listener_tail;
+
+/**
+ * Number of active clients.
+ */
+static unsigned int num_clients;
+
+/**
+ * Are we in shutdown? if #GNUNET_YES and the number of clients
+ * drops to zero, disconnect from CADET.
+ */
+static int in_shutdown;
+
+/**
+ * Counter for allocating unique IDs for clients, used to identify
+ * incoming operation requests from remote peers, that the client can
+ * choose to accept or refuse.  0 must not be used (reserved for
+ * uninitialized).
+ */
+static uint32_t suggest_id;
+
+
+/**
+ * If applicable in the current operation mode, send a result message
+ * to the client indicating we removed an element.
+ *
+ * @param op intersection operation
+ * @param element element to send
+ */
+static void
+send_client_removed_element (struct Operation *op,
+                             struct GNUNET_SETI_Element *element)
+{
+  struct GNUNET_MQ_Envelope *ev;
+  struct GNUNET_SETI_ResultMessage *rm;
+
+  if (GNUNET_YES == op->return_intersection)
+  {
+    GNUNET_break (0);
+    return; /* Wrong mode for transmitting removed elements */
+  }
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "Sending removed element (size %u) to client\n",
+              element->size);
+  GNUNET_STATISTICS_update (_GSS_statistics,
+                            "# Element removed messages sent",
+                            1,
+                            GNUNET_NO);
+  GNUNET_assert (0 != op->client_request_id);
+  ev = GNUNET_MQ_msg_extra (rm,
+                            element->size,
+                            GNUNET_MESSAGE_TYPE_SETI_RESULT);
+  if (NULL == ev)
+  {
+    GNUNET_break (0);
+    return;
+  }
+  rm->result_status = htons (GNUNET_SETI_STATUS_DEL_LOCAL);
+  rm->request_id = htonl (op->client_request_id);
+  rm->element_type = element->element_type;
+  GNUNET_memcpy (&rm[1],
+                 element->data,
+                 element->size);
+  GNUNET_MQ_send (op->set->cs->mq,
+                  ev);
+}
+
+
+/**
+ * Is element @a ee part of the set used by @a op?
+ *
+ * @param ee element to test
+ * @param op operation the defines the set and its generation
+ * @return #GNUNET_YES if the element is in the set, #GNUNET_NO if not
+ */
+static int
+_GSS_is_element_of_operation (struct ElementEntry *ee,
+                              struct Operation *op)
+{
+  return op->generation_created >= ee->generation_added;
+}
+
+
+/**
+ * Fills the "my_elements" hashmap with all relevant elements.
+ *
+ * @param cls the `struct Operation *` we are performing
+ * @param key current key code
+ * @param value the `struct ElementEntry *` from the hash map
+ * @return #GNUNET_YES (we should continue to iterate)
+ */
+static int
+filtered_map_initialization (void *cls,
+                             const struct GNUNET_HashCode *key,
+                             void *value)
+{
+  struct Operation *op = cls;
+  struct ElementEntry *ee = value;
+  struct GNUNET_HashCode mutated_hash;
+
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "FIMA called for %s:%u\n",
+              GNUNET_h2s (&ee->element_hash),
+              ee->element.size);
+
+  if (GNUNET_NO == _GSS_is_element_of_operation (ee, op))
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                "Reduced initialization, not starting with %s:%u (wrong generation)\n",
+                GNUNET_h2s (&ee->element_hash),
+                ee->element.size);
+    return GNUNET_YES;   /* element not valid in our operation's generation */
+  }
+
+  /* Test if element is in other peer's bloomfilter */
+  GNUNET_BLOCK_mingle_hash (&ee->element_hash,
+                            op->salt,
+                            &mutated_hash);
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "Testing mingled hash %s with salt %u\n",
+              GNUNET_h2s (&mutated_hash),
+              op->salt);
+  if (GNUNET_NO ==
+      GNUNET_CONTAINER_bloomfilter_test (op->remote_bf,
+                                         &mutated_hash))
+  {
+    /* remove this element */
+    send_client_removed_element (op,
+                                 &ee->element);
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                "Reduced initialization, not starting with %s:%u\n",
+                GNUNET_h2s (&ee->element_hash),
+                ee->element.size);
+    return GNUNET_YES;
+  }
+  op->my_element_count++;
+  GNUNET_CRYPTO_hash_xor (&op->my_xor,
+                          &ee->element_hash,
+                          &op->my_xor);
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "Filtered initialization of my_elements, adding %s:%u\n",
+              GNUNET_h2s (&ee->element_hash),
+              ee->element.size);
+  GNUNET_break (GNUNET_YES ==
+                GNUNET_CONTAINER_multihashmap_put (op->my_elements,
+                                                   &ee->element_hash,
+                                                   ee,
+                                                   GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
+
+  return GNUNET_YES;
+}
+
+
+/**
+ * Removes elements from our hashmap if they are not contained within the
+ * provided remote bloomfilter.
+ *
+ * @param cls closure with the `struct Operation *`
+ * @param key current key code
+ * @param value value in the hash map
+ * @return #GNUNET_YES (we should continue to iterate)
+ */
+static int
+iterator_bf_reduce (void *cls,
+                    const struct GNUNET_HashCode *key,
+                    void *value)
+{
+  struct Operation *op = cls;
+  struct ElementEntry *ee = value;
+  struct GNUNET_HashCode mutated_hash;
+
+  GNUNET_BLOCK_mingle_hash (&ee->element_hash,
+                            op->salt,
+                            &mutated_hash);
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "Testing mingled hash %s with salt %u\n",
+              GNUNET_h2s (&mutated_hash),
+              op->salt);
+  if (GNUNET_NO ==
+      GNUNET_CONTAINER_bloomfilter_test (op->remote_bf,
+                                         &mutated_hash))
+  {
+    GNUNET_break (0 < op->my_element_count);
+    op->my_element_count--;
+    GNUNET_CRYPTO_hash_xor (&op->my_xor,
+                            &ee->element_hash,
+                            &op->my_xor);
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                "Bloom filter reduction of my_elements, removing %s:%u\n",
+                GNUNET_h2s (&ee->element_hash),
+                ee->element.size);
+    GNUNET_assert (GNUNET_YES ==
+                   GNUNET_CONTAINER_multihashmap_remove (op->my_elements,
+                                                         &ee->element_hash,
+                                                         ee));
+    send_client_removed_element (op,
+                                 &ee->element);
+  }
+  else
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                "Bloom filter reduction of my_elements, keeping %s:%u\n",
+                GNUNET_h2s (&ee->element_hash),
+                ee->element.size);
+  }
+  return GNUNET_YES;
+}
+
+
+/**
+ * Create initial bloomfilter based on all the elements given.
+ *
+ * @param cls the `struct Operation *`
+ * @param key current key code
+ * @param value the `struct ElementEntry` to process
+ * @return #GNUNET_YES (we should continue to iterate)
+ */
+static int
+iterator_bf_create (void *cls,
+                    const struct GNUNET_HashCode *key,
+                    void *value)
+{
+  struct Operation *op = cls;
+  struct ElementEntry *ee = value;
+  struct GNUNET_HashCode mutated_hash;
+
+  GNUNET_BLOCK_mingle_hash (&ee->element_hash,
+                            op->salt,
+                            &mutated_hash);
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "Initializing BF with hash %s with salt %u\n",
+              GNUNET_h2s (&mutated_hash),
+              op->salt);
+  GNUNET_CONTAINER_bloomfilter_add (op->local_bf,
+                                    &mutated_hash);
+  return GNUNET_YES;
+}
+
+
+/**
+ * Destroy the given operation.  Used for any operation where both
+ * peers were known and that thus actually had a vt and channel.  Must
+ * not be used for operations where 'listener' is still set and we do
+ * not know the other peer.
+ *
+ * Call the implementation-specific cancel function of the operation.
+ * Disconnects from the remote peer.  Does not disconnect the client,
+ * as there may be multiple operations per set.
+ *
+ * @param op operation to destroy
+ */
+static void
+_GSS_operation_destroy (struct Operation *op)
+{
+  struct Set *set = op->set;
+  struct GNUNET_CADET_Channel *channel;
+
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Destroying operation %p\n", op);
+  GNUNET_assert (NULL == op->listener);
+  if (NULL != op->remote_bf)
+  {
+    GNUNET_CONTAINER_bloomfilter_free (op->remote_bf);
+    op->remote_bf = NULL;
+  }
+  if (NULL != op->local_bf)
+  {
+    GNUNET_CONTAINER_bloomfilter_free (op->local_bf);
+    op->local_bf = NULL;
+  }
+  if (NULL != op->my_elements)
+  {
+    GNUNET_CONTAINER_multihashmap_destroy (op->my_elements);
+    op->my_elements = NULL;
+  }
+  if (NULL != op->full_result_iter)
+  {
+    GNUNET_CONTAINER_multihashmap_iterator_destroy (
+      op->full_result_iter);
+    op->full_result_iter = NULL;
+  }
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "Destroying intersection op state done\n");
+  if (NULL != set)
+  {
+    GNUNET_CONTAINER_DLL_remove (set->ops_head,
+                                 set->ops_tail,
+                                 op);
+    op->set = NULL;
+  }
+  if (NULL != op->context_msg)
+  {
+    GNUNET_free (op->context_msg);
+    op->context_msg = NULL;
+  }
+  if (NULL != (channel = op->channel))
+  {
+    /* This will free op; called conditionally as this helper function
+       is also called from within the channel disconnect handler. */
+    op->channel = NULL;
+    GNUNET_CADET_channel_destroy (channel);
+  }
+  /* We rely on the channel end handler to free 'op'. When 'op->channel' was NULL,
+   * there was a channel end handler that will free 'op' on the call stack. */
+}
+
+
+/**
+ * This function probably should not exist
+ * and be replaced by inlining more specific
+ * logic in the various places where it is called.
+ */
+static void
+_GSS_operation_destroy2 (struct Operation *op);
+
+
+/**
+ * Destroy an incoming request from a remote peer
+ *
+ * @param op remote request to destroy
+ */
+static void
+incoming_destroy (struct Operation *op)
+{
+  struct Listener *listener;
+
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "Destroying incoming operation %p\n",
+              op);
+  if (NULL != (listener = op->listener))
+  {
+    GNUNET_CONTAINER_DLL_remove (listener->op_head,
+                                 listener->op_tail,
+                                 op);
+    op->listener = NULL;
+  }
+  if (NULL != op->timeout_task)
+  {
+    GNUNET_SCHEDULER_cancel (op->timeout_task);
+    op->timeout_task = NULL;
+  }
+  _GSS_operation_destroy2 (op);
+}
+
+
+/**
+ * Signal to the client that the operation has finished and
+ * destroy the operation.
+ *
+ * @param cls operation to destroy
+ */
+static void
+send_client_done_and_destroy (void *cls)
+{
+  struct Operation *op = cls;
+  struct GNUNET_MQ_Envelope *ev;
+  struct GNUNET_SETI_ResultMessage *rm;
+
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "Intersection succeeded, sending DONE to local client\n");
+  GNUNET_STATISTICS_update (_GSS_statistics,
+                            "# Intersection operations succeeded",
+                            1,
+                            GNUNET_NO);
+  ev = GNUNET_MQ_msg (rm,
+                      GNUNET_MESSAGE_TYPE_SETI_RESULT);
+  rm->request_id = htonl (op->client_request_id);
+  rm->result_status = htons (GNUNET_SETI_STATUS_DONE);
+  rm->element_type = htons (0);
+  GNUNET_MQ_send (op->set->cs->mq,
+                  ev);
+  _GSS_operation_destroy (op);
+}
+
+
+/**
+ * This function probably should not exist
+ * and be replaced by inlining more specific
+ * logic in the various places where it is called.
+ */
+static void
+_GSS_operation_destroy2 (struct Operation *op)
+{
+  struct GNUNET_CADET_Channel *channel;
+
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "channel_end_cb called\n");
+  if (NULL != (channel = op->channel))
+  {
+    /* This will free op; called conditionally as this helper function
+       is also called from within the channel disconnect handler. */
+    op->channel = NULL;
+    GNUNET_CADET_channel_destroy (channel);
+  }
+  if (NULL != op->listener)
+  {
+    incoming_destroy (op);
+    return;
+  }
+  if (NULL != op->set)
+  {
+    if (GNUNET_YES == op->channel_death_expected)
+    {
+      /* oh goodie, we are done! */
+      send_client_done_and_destroy (op);
+    }
+    else
+    {
+      /* sorry, channel went down early, too bad. */
+      _GSS_operation_destroy (op);
+    }
+  }
+  else
+    _GSS_operation_destroy (op);
+  GNUNET_free (op);
+}
+
+
+/**
+ * Inform the client that the intersection operation has failed,
+ * and proceed to destroy the evaluate operation.
+ *
+ * @param op the intersection operation to fail
+ */
+static void
+fail_intersection_operation (struct Operation *op)
+{
+  struct GNUNET_MQ_Envelope *ev;
+  struct GNUNET_SETI_ResultMessage *msg;
+
+  GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+              "Intersection operation failed\n");
+  GNUNET_STATISTICS_update (_GSS_statistics,
+                            "# Intersection operations failed",
+                            1,
+                            GNUNET_NO);
+  if (NULL != op->my_elements)
+  {
+    GNUNET_CONTAINER_multihashmap_destroy (op->my_elements);
+    op->my_elements = NULL;
+  }
+  ev = GNUNET_MQ_msg (msg,
+                      GNUNET_MESSAGE_TYPE_SETI_RESULT);
+  msg->result_status = htons (GNUNET_SETI_STATUS_FAILURE);
+  msg->request_id = htonl (op->client_request_id);
+  msg->element_type = htons (0);
+  GNUNET_MQ_send (op->set->cs->mq,
+                  ev);
+  _GSS_operation_destroy (op);
+}
+
+
+/**
+ * Send a bloomfilter to our peer.  After the result done message has
+ * been sent to the client, destroy the evaluate operation.
+ *
+ * @param op intersection operation
+ */
+static void
+send_bloomfilter (struct Operation *op)
+{
+  struct GNUNET_MQ_Envelope *ev;
+  struct BFMessage *msg;
+  uint32_t bf_size;
+  uint32_t bf_elementbits;
+  uint32_t chunk_size;
+  char *bf_data;
+  uint32_t offset;
+
+  /* We consider the ratio of the set sizes to determine
+     the number of bits per element, as the smaller set
+     should use more bits to maximize its set reduction
+     potential and minimize overall bandwidth consumption. */
+  bf_elementbits = 2 + ceil (log2 ((double)
+                                   (op->remote_element_count
+                                    / (double) op->my_element_count)));
+  if (bf_elementbits < 1)
+    bf_elementbits = 1; /* make sure k is not 0 */
+  /* optimize BF-size to ~50% of bits set */
+  bf_size = ceil ((double) (op->my_element_count
+                            * bf_elementbits / log (2)));
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "Sending Bloom filter (%u) of size %u bytes\n",
+              (unsigned int) bf_elementbits,
+              (unsigned int) bf_size);
+  op->local_bf = GNUNET_CONTAINER_bloomfilter_init (NULL,
+                                                    bf_size,
+                                                    bf_elementbits);
+  op->salt = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_NONCE,
+                                       UINT32_MAX);
+  GNUNET_CONTAINER_multihashmap_iterate (op->my_elements,
+                                         &iterator_bf_create,
+                                         op);
+
+  /* send our Bloom filter */
+  GNUNET_STATISTICS_update (_GSS_statistics,
+                            "# Intersection Bloom filters sent",
+                            1,
+                            GNUNET_NO);
+  chunk_size = 60 * 1024 - sizeof(struct BFMessage);
+  if (bf_size <= chunk_size)
+  {
+    /* singlepart */
+    chunk_size = bf_size;
+    ev = GNUNET_MQ_msg_extra (msg,
+                              chunk_size,
+                              GNUNET_MESSAGE_TYPE_SETI_P2P_BF);
+    GNUNET_assert (GNUNET_SYSERR !=
+                   GNUNET_CONTAINER_bloomfilter_get_raw_data (
+                     op->local_bf,
+                     (char *) &msg[1],
+                     bf_size));
+    msg->sender_element_count = htonl (op->my_element_count);
+    msg->bloomfilter_total_length = htonl (bf_size);
+    msg->bits_per_element = htonl (bf_elementbits);
+    msg->sender_mutator = htonl (op->salt);
+    msg->element_xor_hash = op->my_xor;
+    GNUNET_MQ_send (op->mq, ev);
+  }
+  else
+  {
+    /* multipart */
+    bf_data = GNUNET_malloc (bf_size);
+    GNUNET_assert (GNUNET_SYSERR !=
+                   GNUNET_CONTAINER_bloomfilter_get_raw_data (
+                     op->local_bf,
+                     bf_data,
+                     bf_size));
+    offset = 0;
+    while (offset < bf_size)
+    {
+      if (bf_size - chunk_size < offset)
+        chunk_size = bf_size - offset;
+      ev = GNUNET_MQ_msg_extra (msg,
+                                chunk_size,
+                                GNUNET_MESSAGE_TYPE_SETI_P2P_BF);
+      GNUNET_memcpy (&msg[1],
+                     &bf_data[offset],
+                     chunk_size);
+      offset += chunk_size;
+      msg->sender_element_count = htonl (op->my_element_count);
+      msg->bloomfilter_total_length = htonl (bf_size);
+      msg->bits_per_element = htonl (bf_elementbits);
+      msg->sender_mutator = htonl (op->salt);
+      msg->element_xor_hash = op->my_xor;
+      GNUNET_MQ_send (op->mq, ev);
+    }
+    GNUNET_free (bf_data);
+  }
+  GNUNET_CONTAINER_bloomfilter_free (op->local_bf);
+  op->local_bf = NULL;
+}
+
+
+/**
+ * Remember that we are done dealing with the local client
+ * AND have sent the other peer our message that we are done,
+ * so we are not just waiting for the channel to die before
+ * telling the local client that we are done as our last act.
+ *
+ * @param cls the `struct Operation`.
+ */
+static void
+finished_local_operations (void *cls)
+{
+  struct Operation *op = cls;
+
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "DONE sent to other peer, now waiting for other end to close the channel\n");
+  op->phase = PHASE_FINISHED;
+  op->channel_death_expected = GNUNET_YES;
+}
+
+
+/**
+ * Notify the other peer that we are done.  Once this message
+ * is out, we still need to notify the local client that we
+ * are done.
+ *
+ * @param op operation to notify for.
+ */
+static void
+send_p2p_done (struct Operation *op)
+{
+  struct GNUNET_MQ_Envelope *ev;
+  struct IntersectionDoneMessage *idm;
+
+  GNUNET_assert (PHASE_MUST_SEND_DONE == op->phase);
+  GNUNET_assert (GNUNET_NO == op->channel_death_expected);
+  ev = GNUNET_MQ_msg (idm,
+                      GNUNET_MESSAGE_TYPE_SETI_P2P_DONE);
+  idm->final_element_count = htonl (op->my_element_count);
+  idm->element_xor_hash = op->my_xor;
+  GNUNET_MQ_notify_sent (ev,
+                         &finished_local_operations,
+                         op);
+  GNUNET_MQ_send (op->mq,
+                  ev);
+}
+
+
+/**
+ * Send all elements in the full result iterator.
+ *
+ * @param cls the `struct Operation *`
+ */
+static void
+send_remaining_elements (void *cls)
+{
+  struct Operation *op = cls;
+  const void *nxt;
+  const struct ElementEntry *ee;
+  struct GNUNET_MQ_Envelope *ev;
+  struct GNUNET_SETI_ResultMessage *rm;
+  const struct GNUNET_SETI_Element *element;
+  int res;
+
+  if (GNUNET_NO == op->return_intersection)
+  {
+    GNUNET_break (0);
+    return; /* Wrong mode for transmitting removed elements */
+  }
+  res = GNUNET_CONTAINER_multihashmap_iterator_next (
+    op->full_result_iter,
+    NULL,
+    &nxt);
+  if (GNUNET_NO == res)
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                "Sending done and destroy because iterator ran out\n");
+    GNUNET_CONTAINER_multihashmap_iterator_destroy (
+      op->full_result_iter);
+    op->full_result_iter = NULL;
+    if (PHASE_DONE_RECEIVED == op->phase)
+    {
+      op->phase = PHASE_FINISHED;
+      send_client_done_and_destroy (op);
+    }
+    else if (PHASE_MUST_SEND_DONE == op->phase)
+    {
+      send_p2p_done (op);
+    }
+    else
+    {
+      GNUNET_assert (0);
+    }
+    return;
+  }
+  ee = nxt;
+  element = &ee->element;
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "Sending element %s:%u to client (full set)\n",
+              GNUNET_h2s (&ee->element_hash),
+              element->size);
+  GNUNET_assert (0 != op->client_request_id);
+  ev = GNUNET_MQ_msg_extra (rm,
+                            element->size,
+                            GNUNET_MESSAGE_TYPE_SETI_RESULT);
+  GNUNET_assert (NULL != ev);
+  rm->result_status = htons (GNUNET_SETI_STATUS_ADD_LOCAL);
+  rm->request_id = htonl (op->client_request_id);
+  rm->element_type = element->element_type;
+  GNUNET_memcpy (&rm[1],
+                 element->data,
+                 element->size);
+  GNUNET_MQ_notify_sent (ev,
+                         &send_remaining_elements,
+                         op);
+  GNUNET_MQ_send (op->set->cs->mq,
+                  ev);
+}
+
+
+/**
+ * Fills the "my_elements" hashmap with the initial set of
+ * (non-deleted) elements from the set of the specification.
+ *
+ * @param cls closure with the `struct Operation *`
+ * @param key current key code for the element
+ * @param value value in the hash map with the `struct ElementEntry *`
+ * @return #GNUNET_YES (we should continue to iterate)
+ */
+static int
+initialize_map_unfiltered (void *cls,
+                           const struct GNUNET_HashCode *key,
+                           void *value)
+{
+  struct ElementEntry *ee = value;
+  struct Operation *op = cls;
+
+  if (GNUNET_NO == _GSS_is_element_of_operation (ee, op))
+    return GNUNET_YES; /* element not live in operation's generation */
+  GNUNET_CRYPTO_hash_xor (&op->my_xor,
+                          &ee->element_hash,
+                          &op->my_xor);
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "Initial full initialization of my_elements, adding %s:%u\n",
+              GNUNET_h2s (&ee->element_hash),
+              ee->element.size);
+  GNUNET_break (GNUNET_YES ==
+                GNUNET_CONTAINER_multihashmap_put (op->my_elements,
+                                                   &ee->element_hash,
+                                                   ee,
+                                                   GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
+  return GNUNET_YES;
+}
+
+
+/**
+ * Send our element count to the peer, in case our element count is
+ * lower than theirs.
+ *
+ * @param op intersection operation
+ */
+static void
+send_element_count (struct Operation *op)
+{
+  struct GNUNET_MQ_Envelope *ev;
+  struct IntersectionElementInfoMessage *msg;
+
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "Sending our element count (%u)\n",
+              op->my_element_count);
+  ev = GNUNET_MQ_msg (msg,
+                      GNUNET_MESSAGE_TYPE_SETI_P2P_ELEMENT_INFO);
+  msg->sender_element_count = htonl (op->my_element_count);
+  GNUNET_MQ_send (op->mq, ev);
+}
+
+
+/**
+ * We go first, initialize our map with all elements and
+ * send the first Bloom filter.
+ *
+ * @param op operation to start exchange for
+ */
+static void
+begin_bf_exchange (struct Operation *op)
+{
+  op->phase = PHASE_BF_EXCHANGE;
+  GNUNET_CONTAINER_multihashmap_iterate (op->set->content->elements,
+                                         &initialize_map_unfiltered,
+                                         op);
+  send_bloomfilter (op);
+}
+
+
+/**
+ * Handle the initial `struct IntersectionElementInfoMessage` from a
+ * remote peer.
+ *
+ * @param cls the intersection operation
+ * @param mh the header of the message
+ */
+static void
+handle_intersection_p2p_element_info (void *cls,
+                                      const struct
+                                      IntersectionElementInfoMessage *msg)
+{
+  struct Operation *op = cls;
+
+  op->remote_element_count = ntohl (msg->sender_element_count);
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "Received remote element count (%u), I have %u\n",
+              op->remote_element_count,
+              op->my_element_count);
+  if (((PHASE_INITIAL != op->phase) &&
+       (PHASE_COUNT_SENT != op->phase)) ||
+      (op->my_element_count > op->remote_element_count) ||
+      (0 == op->my_element_count) ||
+      (0 == op->remote_element_count))
+  {
+    GNUNET_break_op (0);
+    fail_intersection_operation (op);
+    return;
+  }
+  GNUNET_break (NULL == op->remote_bf);
+  begin_bf_exchange (op);
+  GNUNET_CADET_receive_done (op->channel);
+}
+
+
+/**
+ * Process a Bloomfilter once we got all the chunks.
+ *
+ * @param op the intersection operation
+ */
+static void
+process_bf (struct Operation *op)
+{
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "Received BF in phase %u, foreign count is %u, my element count is %u/%u\n",
+              op->phase,
+              op->remote_element_count,
+              op->my_element_count,
+              GNUNET_CONTAINER_multihashmap_size (op->set->content->elements));
+  switch (op->phase)
+  {
+  case PHASE_INITIAL:
+    GNUNET_break_op (0);
+    fail_intersection_operation (op);
+    return;
+  case PHASE_COUNT_SENT:
+    /* This is the first BF being sent, build our initial map with
+       filtering in place */
+    op->my_element_count = 0;
+    GNUNET_CONTAINER_multihashmap_iterate (op->set->content->elements,
+                                           &filtered_map_initialization,
+                                           op);
+    break;
+  case PHASE_BF_EXCHANGE:
+    /* Update our set by reduction */
+    GNUNET_CONTAINER_multihashmap_iterate (op->my_elements,
+                                           &iterator_bf_reduce,
+                                           op);
+    break;
+  case PHASE_MUST_SEND_DONE:
+    GNUNET_break_op (0);
+    fail_intersection_operation (op);
+    return;
+  case PHASE_DONE_RECEIVED:
+    GNUNET_break_op (0);
+    fail_intersection_operation (op);
+    return;
+  case PHASE_FINISHED:
+    GNUNET_break_op (0);
+    fail_intersection_operation (op);
+    return;
+  }
+  GNUNET_CONTAINER_bloomfilter_free (op->remote_bf);
+  op->remote_bf = NULL;
+
+  if ((0 == op->my_element_count) ||  /* fully disjoint */
+      ((op->my_element_count == op->remote_element_count) &&
+       (0 == GNUNET_memcmp (&op->my_xor,
+                            &op->other_xor))))
+  {
+    /* we are done */
+    op->phase = PHASE_MUST_SEND_DONE;
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                "Intersection succeeded, sending DONE to other peer\n");
+    GNUNET_CONTAINER_bloomfilter_free (op->local_bf);
+    op->local_bf = NULL;
+    if (GNUNET_YES == op->return_intersection)
+    {
+      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                  "Sending full result set (%u elements)\n",
+                  GNUNET_CONTAINER_multihashmap_size (op->my_elements));
+      op->full_result_iter
+        = GNUNET_CONTAINER_multihashmap_iterator_create (
+            op->my_elements);
+      send_remaining_elements (op);
+      return;
+    }
+    send_p2p_done (op);
+    return;
+  }
+  op->phase = PHASE_BF_EXCHANGE;
+  send_bloomfilter (op);
+}
+
+
+/**
+ * Check an BF message from a remote peer.
+ *
+ * @param cls the intersection operation
+ * @param msg the header of the message
+ * @return #GNUNET_OK if @a msg is well-formed
+ */
+static int
+check_intersection_p2p_bf (void *cls,
+                           const struct BFMessage *msg)
+{
+  struct Operation *op = cls;
+
+  (void) op;
+  return GNUNET_OK;
+}
+
+
+/**
+ * Handle an BF message from a remote peer.
+ *
+ * @param cls the intersection operation
+ * @param msg the header of the message
+ */
+static void
+handle_intersection_p2p_bf (void *cls,
+                            const struct BFMessage *msg)
+{
+  struct Operation *op = cls;
+  uint32_t bf_size;
+  uint32_t chunk_size;
+  uint32_t bf_bits_per_element;
+
+  switch (op->phase)
+  {
+  case PHASE_INITIAL:
+    GNUNET_break_op (0);
+    fail_intersection_operation (op);
+    return;
+
+  case PHASE_COUNT_SENT:
+  case PHASE_BF_EXCHANGE:
+    bf_size = ntohl (msg->bloomfilter_total_length);
+    bf_bits_per_element = ntohl (msg->bits_per_element);
+    chunk_size = htons (msg->header.size) - sizeof(struct BFMessage);
+    op->other_xor = msg->element_xor_hash;
+    if (bf_size == chunk_size)
+    {
+      if (NULL != op->bf_data)
+      {
+        GNUNET_break_op (0);
+        fail_intersection_operation (op);
+        return;
+      }
+      /* single part, done here immediately */
+      op->remote_bf
+        = GNUNET_CONTAINER_bloomfilter_init ((const char *) &msg[1],
+                                             bf_size,
+                                             bf_bits_per_element);
+      op->salt = ntohl (msg->sender_mutator);
+      op->remote_element_count = ntohl (msg->sender_element_count);
+      process_bf (op);
+      break;
+    }
+    /* multipart chunk */
+    if (NULL == op->bf_data)
+    {
+      /* first chunk, initialize */
+      op->bf_data = GNUNET_malloc (bf_size);
+      op->bf_data_size = bf_size;
+      op->bf_bits_per_element = bf_bits_per_element;
+      op->bf_data_offset = 0;
+      op->salt = ntohl (msg->sender_mutator);
+      op->remote_element_count = ntohl (msg->sender_element_count);
+    }
+    else
+    {
+      /* increment */
+      if ((op->bf_data_size != bf_size) ||
+          (op->bf_bits_per_element != bf_bits_per_element) ||
+          (op->bf_data_offset + chunk_size > bf_size) ||
+          (op->salt != ntohl (msg->sender_mutator)) ||
+          (op->remote_element_count != ntohl (msg->sender_element_count)))
+      {
+        GNUNET_break_op (0);
+        fail_intersection_operation (op);
+        return;
+      }
+    }
+    GNUNET_memcpy (&op->bf_data[op->bf_data_offset],
+                   (const char *) &msg[1],
+                   chunk_size);
+    op->bf_data_offset += chunk_size;
+    if (op->bf_data_offset == bf_size)
+    {
+      /* last chunk, run! */
+      op->remote_bf
+        = GNUNET_CONTAINER_bloomfilter_init (op->bf_data,
+                                             bf_size,
+                                             bf_bits_per_element);
+      GNUNET_free (op->bf_data);
+      op->bf_data = NULL;
+      op->bf_data_size = 0;
+      process_bf (op);
+    }
+    break;
+
+  default:
+    GNUNET_break_op (0);
+    fail_intersection_operation (op);
+    return;
+  }
+  GNUNET_CADET_receive_done (op->channel);
+}
+
+
+/**
+ * Remove all elements from our hashmap.
+ *
+ * @param cls closure with the `struct Operation *`
+ * @param key current key code
+ * @param value value in the hash map
+ * @return #GNUNET_YES (we should continue to iterate)
+ */
+static int
+filter_all (void *cls,
+            const struct GNUNET_HashCode *key,
+            void *value)
+{
+  struct Operation *op = cls;
+  struct ElementEntry *ee = value;
+
+  GNUNET_break (0 < op->my_element_count);
+  op->my_element_count--;
+  GNUNET_CRYPTO_hash_xor (&op->my_xor,
+                          &ee->element_hash,
+                          &op->my_xor);
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "Final reduction of my_elements, removing %s:%u\n",
+              GNUNET_h2s (&ee->element_hash),
+              ee->element.size);
+  GNUNET_assert (GNUNET_YES ==
+                 GNUNET_CONTAINER_multihashmap_remove (op->my_elements,
+                                                       &ee->element_hash,
+                                                       ee));
+  send_client_removed_element (op,
+                               &ee->element);
+  return GNUNET_YES;
+}
+
+
+/**
+ * Handle a done message from a remote peer
+ *
+ * @param cls the intersection operation
+ * @param mh the message
+ */
+static void
+handle_intersection_p2p_done (void *cls,
+                              const struct IntersectionDoneMessage *idm)
+{
+  struct Operation *op = cls;
+
+  if (PHASE_BF_EXCHANGE != op->phase)
+  {
+    /* wrong phase to conclude? FIXME: Or should we allow this
+       if the other peer has _initially_ already an empty set? */
+    GNUNET_break_op (0);
+    fail_intersection_operation (op);
+    return;
+  }
+  if (0 == ntohl (idm->final_element_count))
+  {
+    /* other peer determined empty set is the intersection,
+       remove all elements */
+    GNUNET_CONTAINER_multihashmap_iterate (op->my_elements,
+                                           &filter_all,
+                                           op);
+  }
+  if ((op->my_element_count != ntohl (idm->final_element_count)) ||
+      (0 != GNUNET_memcmp (&op->my_xor,
+                           &idm->element_xor_hash)))
+  {
+    /* Other peer thinks we are done, but we disagree on the result! */
+    GNUNET_break_op (0);
+    fail_intersection_operation (op);
+    return;
+  }
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "Got IntersectionDoneMessage, have %u elements in intersection\n",
+              op->my_element_count);
+  op->phase = PHASE_DONE_RECEIVED;
+  GNUNET_CADET_receive_done (op->channel);
+
+  GNUNET_assert (GNUNET_NO == op->client_done_sent);
+  if (GNUNET_YES == op->return_intersection)
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                "Sending full result set to client (%u elements)\n",
+                GNUNET_CONTAINER_multihashmap_size (op->my_elements));
+    op->full_result_iter
+      = GNUNET_CONTAINER_multihashmap_iterator_create (op->my_elements);
+    send_remaining_elements (op);
+    return;
+  }
+  op->phase = PHASE_FINISHED;
+  send_client_done_and_destroy (op);
+}
+
+
+/**
+ * Get the incoming socket associated with the given id.
+ *
+ * @param listener the listener to look in
+ * @param id id to look for
+ * @return the incoming socket associated with the id,
+ *         or NULL if there is none
+ */
+static struct Operation *
+get_incoming (uint32_t id)
+{
+  for (struct Listener *listener = listener_head; NULL != listener;
+       listener = listener->next)
+  {
+    for (struct Operation *op = listener->op_head; NULL != op; op = op->next)
+      if (op->suggest_id == id)
+        return op;
+  }
+  return NULL;
+}
+
+
+/**
+ * Callback called when a client connects to the service.
+ *
+ * @param cls closure for the service
+ * @param c the new client that connected to the service
+ * @param mq the message queue used to send messages to the client
+ * @return @a `struct ClientState`
+ */
+static void *
+client_connect_cb (void *cls,
+                   struct GNUNET_SERVICE_Client *c,
+                   struct GNUNET_MQ_Handle *mq)
+{
+  struct ClientState *cs;
+
+  num_clients++;
+  cs = GNUNET_new (struct ClientState);
+  cs->client = c;
+  cs->mq = mq;
+  return cs;
+}
+
+
+/**
+ * Iterator over hash map entries to free element entries.
+ *
+ * @param cls closure
+ * @param key current key code
+ * @param value a `struct ElementEntry *` to be free'd
+ * @return #GNUNET_YES (continue to iterate)
+ */
+static int
+destroy_elements_iterator (void *cls,
+                           const struct GNUNET_HashCode *key,
+                           void *value)
+{
+  struct ElementEntry *ee = value;
+
+  GNUNET_free (ee);
+  return GNUNET_YES;
+}
+
+
+/**
+ * Clean up after a client has disconnected
+ *
+ * @param cls closure, unused
+ * @param client the client to clean up after
+ * @param internal_cls the `struct ClientState`
+ */
+static void
+client_disconnect_cb (void *cls,
+                      struct GNUNET_SERVICE_Client *client,
+                      void *internal_cls)
+{
+  struct ClientState *cs = internal_cls;
+  struct Operation *op;
+  struct Listener *listener;
+  struct Set *set;
+
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Client disconnected, cleaning up\n");
+  if (NULL != (set = cs->set))
+  {
+    struct SetContent *content = set->content;
+
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Destroying client's set\n");
+    /* Destroy pending set operations */
+    while (NULL != set->ops_head)
+      _GSS_operation_destroy (set->ops_head);
+
+    /* free set content (or at least decrement RC) */
+    set->content = NULL;
+    GNUNET_assert (0 != content->refcount);
+    content->refcount--;
+    if (0 == content->refcount)
+    {
+      GNUNET_assert (NULL != content->elements);
+      GNUNET_CONTAINER_multihashmap_iterate (content->elements,
+                                             &destroy_elements_iterator,
+                                             NULL);
+      GNUNET_CONTAINER_multihashmap_destroy (content->elements);
+      content->elements = NULL;
+      GNUNET_free (content);
+    }
+    GNUNET_free (set);
+  }
+
+  if (NULL != (listener = cs->listener))
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Destroying client's listener\n");
+    GNUNET_CADET_close_port (listener->open_port);
+    listener->open_port = NULL;
+    while (NULL != (op = listener->op_head))
+    {
+      GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+                  "Destroying incoming operation `%u' from peer `%s'\n",
+                  (unsigned int) op->client_request_id,
+                  GNUNET_i2s (&op->peer));
+      incoming_destroy (op);
+    }
+    GNUNET_CONTAINER_DLL_remove (listener_head, listener_tail, listener);
+    GNUNET_free (listener);
+  }
+  GNUNET_free (cs);
+  num_clients--;
+  if ((GNUNET_YES == in_shutdown) && (0 == num_clients))
+  {
+    if (NULL != cadet)
+    {
+      GNUNET_CADET_disconnect (cadet);
+      cadet = NULL;
+    }
+  }
+}
+
+
+/**
+ * Check a request for a set operation from another peer.
+ *
+ * @param cls the operation state
+ * @param msg the received message
+ * @return #GNUNET_OK if the channel should be kept alive,
+ *         #GNUNET_SYSERR to destroy the channel
+ */
+static int
+check_incoming_msg (void *cls,
+                    const struct OperationRequestMessage *msg)
+{
+  struct Operation *op = cls;
+  struct Listener *listener = op->listener;
+  const struct GNUNET_MessageHeader *nested_context;
+
+  /* double operation request */
+  if (0 != op->suggest_id)
+  {
+    GNUNET_break_op (0);
+    return GNUNET_SYSERR;
+  }
+  /* This should be equivalent to the previous condition, but can't hurt to check twice */
+  if (NULL == listener)
+  {
+    GNUNET_break (0);
+    return GNUNET_SYSERR;
+  }
+  nested_context = GNUNET_MQ_extract_nested_mh (msg);
+  if ((NULL != nested_context) &&
+      (ntohs (nested_context->size) > GNUNET_SETI_CONTEXT_MESSAGE_MAX_SIZE))
+  {
+    GNUNET_break_op (0);
+    return GNUNET_SYSERR;
+  }
+  return GNUNET_OK;
+}
+
+
+/**
+ * Handle a request for a set operation from another peer.  Checks if we
+ * have a listener waiting for such a request (and in that case initiates
+ * asking the listener about accepting the connection). If no listener
+ * is waiting, we queue the operation request in hope that a listener
+ * shows up soon (before timeout).
+ *
+ * This msg is expected as the first and only msg handled through the
+ * non-operation bound virtual table, acceptance of this operation replaces
+ * our virtual table and subsequent msgs would be routed differently (as
+ * we then know what type of operation this is).
+ *
+ * @param cls the operation state
+ * @param msg the received message
+ * @return #GNUNET_OK if the channel should be kept alive,
+ *         #GNUNET_SYSERR to destroy the channel
+ */
+static void
+handle_incoming_msg (void *cls,
+                     const struct OperationRequestMessage *msg)
+{
+  struct Operation *op = cls;
+  struct Listener *listener = op->listener;
+  const struct GNUNET_MessageHeader *nested_context;
+  struct GNUNET_MQ_Envelope *env;
+  struct GNUNET_SETI_RequestMessage *cmsg;
+
+  nested_context = GNUNET_MQ_extract_nested_mh (msg);
+  /* Make a copy of the nested_context (application-specific context
+     information that is opaque to set) so we can pass it to the
+     listener later on */
+  if (NULL != nested_context)
+    op->context_msg = GNUNET_copy_message (nested_context);
+  op->remote_element_count = ntohl (msg->element_count);
+  GNUNET_log (
+    GNUNET_ERROR_TYPE_DEBUG,
+    "Received P2P operation request (port %s) for active listener\n",
+    GNUNET_h2s (&op->listener->app_id));
+  GNUNET_assert (0 == op->suggest_id);
+  if (0 == suggest_id)
+    suggest_id++;
+  op->suggest_id = suggest_id++;
+  GNUNET_assert (NULL != op->timeout_task);
+  GNUNET_SCHEDULER_cancel (op->timeout_task);
+  op->timeout_task = NULL;
+  env = GNUNET_MQ_msg_nested_mh (cmsg,
+                                 GNUNET_MESSAGE_TYPE_SETI_REQUEST,
+                                 op->context_msg);
+  GNUNET_log (
+    GNUNET_ERROR_TYPE_DEBUG,
+    "Suggesting incoming request with accept id %u to listener %p of client %p\n",
+    op->suggest_id,
+    listener,
+    listener->cs);
+  cmsg->accept_id = htonl (op->suggest_id);
+  cmsg->peer_id = op->peer;
+  GNUNET_MQ_send (listener->cs->mq, env);
+  /* NOTE: GNUNET_CADET_receive_done() will be called in
+   #handle_client_accept() */
+}
+
+
+/**
+ * Called when a client wants to create a new set.  This is typically
+ * the first request from a client, and includes the type of set
+ * operation to be performed.
+ *
+ * @param cls client that sent the message
+ * @param m message sent by the client
+ */
+static void
+handle_client_create_set (void *cls,
+                          const struct GNUNET_SETI_CreateMessage *msg)
+{
+  struct ClientState *cs = cls;
+  struct Set *set;
+
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "Client created new intersection set\n");
+  if (NULL != cs->set)
+  {
+    /* There can only be one set per client */
+    GNUNET_break (0);
+    GNUNET_SERVICE_client_drop (cs->client);
+    return;
+  }
+  set = GNUNET_new (struct Set);
+  set->content = GNUNET_new (struct SetContent);
+  set->content->refcount = 1;
+  set->content->elements = GNUNET_CONTAINER_multihashmap_create (1,
+                                                                 GNUNET_YES);
+  set->cs = cs;
+  cs->set = set;
+  GNUNET_SERVICE_client_continue (cs->client);
+}
+
+
+/**
+ * Timeout happens iff:
+ *  - we suggested an operation to our listener,
+ *    but did not receive a response in time
+ *  - we got the channel from a peer but no #GNUNET_MESSAGE_TYPE_SETI_P2P_OPERATION_REQUEST
+ *
+ * @param cls channel context
+ * @param tc context information (why was this task triggered now)
+ */
+static void
+incoming_timeout_cb (void *cls)
+{
+  struct Operation *op = cls;
+
+  op->timeout_task = NULL;
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "Remote peer's incoming request timed out\n");
+  incoming_destroy (op);
+}
+
+
+/**
+ * Method called whenever another peer has added us to a channel the
+ * other peer initiated.  Only called (once) upon reception of data
+ * from a channel we listen on.
+ *
+ * The channel context represents the operation itself and gets added
+ * to a DLL, from where it gets looked up when our local listener
+ * client responds to a proposed/suggested operation or connects and
+ * associates with this operation.
+ *
+ * @param cls closure
+ * @param channel new handle to the channel
+ * @param source peer that started the channel
+ * @return initial channel context for the channel
+ *         returns NULL on error
+ */
+static void *
+channel_new_cb (void *cls,
+                struct GNUNET_CADET_Channel *channel,
+                const struct GNUNET_PeerIdentity *source)
+{
+  struct Listener *listener = cls;
+  struct Operation *op;
+
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "New incoming channel\n");
+  op = GNUNET_new (struct Operation);
+  op->listener = listener;
+  op->peer = *source;
+  op->channel = channel;
+  op->mq = GNUNET_CADET_get_mq (op->channel);
+  op->salt = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_NONCE,
+                                       UINT32_MAX);
+  op->timeout_task = GNUNET_SCHEDULER_add_delayed (INCOMING_CHANNEL_TIMEOUT,
+                                                   &incoming_timeout_cb,
+                                                   op);
+  GNUNET_CONTAINER_DLL_insert (listener->op_head,
+                               listener->op_tail,
+                               op);
+  return op;
+}
+
+
+/**
+ * Function called whenever a channel is destroyed.  Should clean up
+ * any associated state.  It must NOT call
+ * GNUNET_CADET_channel_destroy() on the channel.
+ *
+ * The peer_disconnect function is part of a a virtual table set initially either
+ * when a peer creates a new channel with us, or once we create
+ * a new channel ourselves (evaluate).
+ *
+ * Once we know the exact type of operation (union/intersection), the vt is
+ * replaced with an operation specific instance (_GSS_[op]_vt).
+ *
+ * @param channel_ctx place where local state associated
+ *                   with the channel is stored
+ * @param channel connection to the other end (henceforth invalid)
+ */
+static void
+channel_end_cb (void *channel_ctx,
+                const struct GNUNET_CADET_Channel *channel)
+{
+  struct Operation *op = channel_ctx;
+
+  op->channel = NULL;
+  _GSS_operation_destroy2 (op);
+}
+
+
+/**
+ * Function called whenever an MQ-channel's transmission window size changes.
+ *
+ * The first callback in an outgoing channel will be with a non-zero value
+ * and will mean the channel is connected to the destination.
+ *
+ * For an incoming channel it will be called immediately after the
+ * #GNUNET_CADET_ConnectEventHandler, also with a non-zero value.
+ *
+ * @param cls Channel closure.
+ * @param channel Connection to the other end (henceforth invalid).
+ * @param window_size New window size. If the is more messages than buffer size
+ *                    this value will be negative..
+ */
+static void
+channel_window_cb (void *cls,
+                   const struct GNUNET_CADET_Channel *channel,
+                   int window_size)
+{
+  /* FIXME: not implemented, we could do flow control here... */
+}
+
+
+/**
+ * Called when a client wants to create a new listener.
+ *
+ * @param cls client that sent the message
+ * @param msg message sent by the client
+ */
+static void
+handle_client_listen (void *cls,
+                      const struct GNUNET_SETI_ListenMessage *msg)
+{
+  struct ClientState *cs = cls;
+  struct GNUNET_MQ_MessageHandler cadet_handlers[] = {
+    GNUNET_MQ_hd_var_size (incoming_msg,
+                           GNUNET_MESSAGE_TYPE_SETI_P2P_OPERATION_REQUEST,
+                           struct OperationRequestMessage,
+                           NULL),
+    GNUNET_MQ_hd_fixed_size (intersection_p2p_element_info,
+                             GNUNET_MESSAGE_TYPE_SETI_P2P_ELEMENT_INFO,
+                             struct IntersectionElementInfoMessage,
+                             NULL),
+    GNUNET_MQ_hd_var_size (intersection_p2p_bf,
+                           GNUNET_MESSAGE_TYPE_SETI_P2P_BF,
+                           struct BFMessage,
+                           NULL),
+    GNUNET_MQ_hd_fixed_size (intersection_p2p_done,
+                             GNUNET_MESSAGE_TYPE_SETI_P2P_DONE,
+                             struct IntersectionDoneMessage,
+                             NULL),
+    GNUNET_MQ_handler_end ()
+  };
+  struct Listener *listener;
+
+  if (NULL != cs->listener)
+  {
+    /* max. one active listener per client! */
+    GNUNET_break (0);
+    GNUNET_SERVICE_client_drop (cs->client);
+    return;
+  }
+  listener = GNUNET_new (struct Listener);
+  listener->cs = cs;
+  cs->listener = listener;
+  listener->app_id = msg->app_id;
+  GNUNET_CONTAINER_DLL_insert (listener_head,
+                               listener_tail,
+                               listener);
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "New listener for set intersection created (port %s)\n",
+              GNUNET_h2s (&listener->app_id));
+  listener->open_port = GNUNET_CADET_open_port (cadet,
+                                                &msg->app_id,
+                                                &channel_new_cb,
+                                                listener,
+                                                &channel_window_cb,
+                                                &channel_end_cb,
+                                                cadet_handlers);
+  GNUNET_SERVICE_client_continue (cs->client);
+}
+
+
+/**
+ * Called when the listening client rejects an operation
+ * request by another peer.
+ *
+ * @param cls client that sent the message
+ * @param msg message sent by the client
+ */
+static void
+handle_client_reject (void *cls,
+                      const struct GNUNET_SETI_RejectMessage *msg)
+{
+  struct ClientState *cs = cls;
+  struct Operation *op;
+
+  op = get_incoming (ntohl (msg->accept_reject_id));
+  if (NULL == op)
+  {
+    /* no matching incoming operation for this reject;
+       could be that the other peer already disconnected... */
+    GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+                "Client rejected unknown operation %u\n",
+                (unsigned int) ntohl (msg->accept_reject_id));
+    GNUNET_SERVICE_client_continue (cs->client);
+    return;
+  }
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "Peer request (app %s) rejected by client\n",
+              GNUNET_h2s (&cs->listener->app_id));
+  _GSS_operation_destroy2 (op);
+  GNUNET_SERVICE_client_continue (cs->client);
+}
+
+
+/**
+ * Called when a client wants to add or remove an element to a set it inhabits.
+ *
+ * @param cls client that sent the message
+ * @param msg message sent by the client
+ */
+static int
+check_client_set_add (void *cls,
+                      const struct GNUNET_SETI_ElementMessage *msg)
+{
+  /* NOTE: Technically, we should probably check with the
+     block library whether the element we are given is well-formed */
+  return GNUNET_OK;
+}
+
+
+/**
+ * Called when a client wants to add an element to a set it inhabits.
+ *
+ * @param cls client that sent the message
+ * @param msg message sent by the client
+ */
+static void
+handle_client_set_add (void *cls,
+                       const struct GNUNET_SETI_ElementMessage *msg)
+{
+  struct ClientState *cs = cls;
+  struct Set *set;
+  struct GNUNET_SETI_Element el;
+  struct ElementEntry *ee;
+  struct GNUNET_HashCode hash;
+
+  if (NULL == (set = cs->set))
+  {
+    /* client without a set requested an operation */
+    GNUNET_break (0);
+    GNUNET_SERVICE_client_drop (cs->client);
+    return;
+  }
+  GNUNET_SERVICE_client_continue (cs->client);
+  el.size = ntohs (msg->header.size) - sizeof(*msg);
+  el.data = &msg[1];
+  el.element_type = ntohs (msg->element_type);
+  GNUNET_SETI_element_hash (&el,
+                            &hash);
+  ee = GNUNET_CONTAINER_multihashmap_get (set->content->elements,
+                                          &hash);
+  if (NULL == ee)
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                "Client inserts element %s of size %u\n",
+                GNUNET_h2s (&hash),
+                el.size);
+    ee = GNUNET_malloc (el.size + sizeof(*ee));
+    ee->element.size = el.size;
+    GNUNET_memcpy (&ee[1], el.data, el.size);
+    ee->element.data = &ee[1];
+    ee->element.element_type = el.element_type;
+    ee->remote = GNUNET_NO;
+    ee->element_hash = hash;
+    GNUNET_break (GNUNET_YES ==
+                  GNUNET_CONTAINER_multihashmap_put (
+                    set->content->elements,
+                    &ee->element_hash,
+                    ee,
+                    GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
+  }
+  else
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                "Client inserted element %s of size %u twice (ignored)\n",
+                GNUNET_h2s (&hash),
+                el.size);
+    /* same element inserted twice */
+    return;
+  }
+  set->current_set_element_count++;
+}
+
+
+/**
+ * Advance the current generation of a set,
+ * adding exclusion ranges if necessary.
+ *
+ * @param set the set where we want to advance the generation
+ */
+static void
+advance_generation (struct Set *set)
+{
+  if (set->current_generation == set->content->latest_generation)
+  {
+    set->content->latest_generation++;
+    set->current_generation++;
+    return;
+  }
+  GNUNET_assert (set->current_generation < set->content->latest_generation);
+}
+
+
+/**
+ * Called when a client wants to initiate a set operation with another
+ * peer.  Initiates the CADET connection to the listener and sends the
+ * request.
+ *
+ * @param cls client that sent the message
+ * @param msg message sent by the client
+ * @return #GNUNET_OK if the message is well-formed
+ */
+static int
+check_client_evaluate (void *cls,
+                       const struct GNUNET_SETI_EvaluateMessage *msg)
+{
+  /* FIXME: suboptimal, even if the context below could be NULL,
+     there are malformed messages this does not check for... */
+  return GNUNET_OK;
+}
+
+
+/**
+ * Called when a client wants to initiate a set operation with another
+ * peer.  Initiates the CADET connection to the listener and sends the
+ * request.
+ *
+ * @param cls client that sent the message
+ * @param msg message sent by the client
+ */
+static void
+handle_client_evaluate (void *cls,
+                        const struct GNUNET_SETI_EvaluateMessage *msg)
+{
+  struct ClientState *cs = cls;
+  struct Operation *op = GNUNET_new (struct Operation);
+  const struct GNUNET_MQ_MessageHandler cadet_handlers[] = {
+    GNUNET_MQ_hd_var_size (incoming_msg,
+                           GNUNET_MESSAGE_TYPE_SETI_P2P_OPERATION_REQUEST,
+                           struct OperationRequestMessage,
+                           op),
+    GNUNET_MQ_hd_fixed_size (intersection_p2p_element_info,
+                             GNUNET_MESSAGE_TYPE_SETI_P2P_ELEMENT_INFO,
+                             struct IntersectionElementInfoMessage,
+                             op),
+    GNUNET_MQ_hd_var_size (intersection_p2p_bf,
+                           GNUNET_MESSAGE_TYPE_SETI_P2P_BF,
+                           struct BFMessage,
+                           op),
+    GNUNET_MQ_hd_fixed_size (intersection_p2p_done,
+                             GNUNET_MESSAGE_TYPE_SETI_P2P_DONE,
+                             struct IntersectionDoneMessage,
+                             op),
+    GNUNET_MQ_handler_end ()
+  };
+  struct Set *set;
+  const struct GNUNET_MessageHeader *context;
+
+  if (NULL == (set = cs->set))
+  {
+    GNUNET_break (0);
+    GNUNET_free (op);
+    GNUNET_SERVICE_client_drop (cs->client);
+    return;
+  }
+  op->salt = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_NONCE,
+                                       UINT32_MAX);
+  op->peer = msg->target_peer;
+  op->return_intersection = htonl (msg->return_intersection);
+  fprintf (stderr,
+           "Return intersection for evaluate is %d\n",
+           op->return_intersection);
+  op->client_request_id = ntohl (msg->request_id);
+  context = GNUNET_MQ_extract_nested_mh (msg);
+
+  /* Advance generation values, so that
+     mutations won't interfer with the running operation. */
+  op->set = set;
+  op->generation_created = set->current_generation;
+  advance_generation (set);
+  GNUNET_CONTAINER_DLL_insert (set->ops_head,
+                               set->ops_tail,
+                               op);
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "Creating new CADET channel to port %s for set intersection\n",
+              GNUNET_h2s (&msg->app_id));
+  op->channel = GNUNET_CADET_channel_create (cadet,
+                                             op,
+                                             &msg->target_peer,
+                                             &msg->app_id,
+                                             &channel_window_cb,
+                                             &channel_end_cb,
+                                             cadet_handlers);
+  op->mq = GNUNET_CADET_get_mq (op->channel);
+  {
+    struct GNUNET_MQ_Envelope *ev;
+    struct OperationRequestMessage *msg;
+
+    ev = GNUNET_MQ_msg_nested_mh (msg,
+                                  GNUNET_MESSAGE_TYPE_SETI_P2P_OPERATION_REQUEST,
+                                  context);
+    if (NULL == ev)
+    {
+      /* the context message is too large!? */
+      GNUNET_break (0);
+      GNUNET_SERVICE_client_drop (cs->client);
+      return;
+    }
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                "Initiating intersection operation evaluation\n");
+    /* we started the operation, thus we have to send the operation request */
+    op->phase = PHASE_INITIAL;
+    op->my_element_count = op->set->current_set_element_count;
+    op->my_elements
+      = GNUNET_CONTAINER_multihashmap_create (op->my_element_count,
+                                              GNUNET_YES);
+
+    msg->element_count = htonl (op->my_element_count);
+    GNUNET_MQ_send (op->mq,
+                    ev);
+    op->phase = PHASE_COUNT_SENT;
+    if (NULL != context)
+      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                  "Sent op request with context message\n");
+    else
+      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                  "Sent op request without context message\n");
+  }
+  GNUNET_SERVICE_client_continue (cs->client);
+}
+
+
+/**
+ * Handle a request from the client to cancel a running set operation.
+ *
+ * @param cls the client
+ * @param msg the message
+ */
+static void
+handle_client_cancel (void *cls,
+                      const struct GNUNET_SETI_CancelMessage *msg)
+{
+  struct ClientState *cs = cls;
+  struct Set *set;
+  struct Operation *op;
+  int found;
+
+  if (NULL == (set = cs->set))
+  {
+    /* client without a set requested an operation */
+    GNUNET_break (0);
+    GNUNET_SERVICE_client_drop (cs->client);
+    return;
+  }
+  found = GNUNET_NO;
+  for (op = set->ops_head; NULL != op; op = op->next)
+  {
+    if (op->client_request_id == ntohl (msg->request_id))
+    {
+      found = GNUNET_YES;
+      break;
+    }
+  }
+  if (GNUNET_NO == found)
+  {
+    /* It may happen that the operation was already destroyed due to
+     * the other peer disconnecting.  The client may not know about this
+     * yet and try to cancel the (just barely non-existent) operation.
+     * So this is not a hard error.
+     *///
+    GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+                "Client canceled non-existent op %u\n",
+                (uint32_t) ntohl (msg->request_id));
+  }
+  else
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                "Client requested cancel for op %u\n",
+                (uint32_t) ntohl (msg->request_id));
+    _GSS_operation_destroy (op);
+  }
+  GNUNET_SERVICE_client_continue (cs->client);
+}
+
+
+/**
+ * Handle a request from the client to accept a set operation that
+ * came from a remote peer.  We forward the accept to the associated
+ * operation for handling
+ *
+ * @param cls the client
+ * @param msg the message
+ */
+static void
+handle_client_accept (void *cls,
+                      const struct GNUNET_SETI_AcceptMessage *msg)
+{
+  struct ClientState *cs = cls;
+  struct Set *set;
+  struct Operation *op;
+  struct GNUNET_SETI_ResultMessage *result_message;
+  struct GNUNET_MQ_Envelope *ev;
+  struct Listener *listener;
+
+  if (NULL == (set = cs->set))
+  {
+    /* client without a set requested to accept */
+    GNUNET_break (0);
+    GNUNET_SERVICE_client_drop (cs->client);
+    return;
+  }
+  op = get_incoming (ntohl (msg->accept_reject_id));
+  if (NULL == op)
+  {
+    /* It is not an error if the set op does not exist -- it may
+    * have been destroyed when the partner peer disconnected. */
+    GNUNET_log (
+      GNUNET_ERROR_TYPE_INFO,
+      "Client %p accepted request %u of listener %p that is no longer active\n",
+      cs,
+      ntohl (msg->accept_reject_id),
+      cs->listener);
+    ev = GNUNET_MQ_msg (result_message,
+                        GNUNET_MESSAGE_TYPE_SETI_RESULT);
+    result_message->request_id = msg->request_id;
+    result_message->result_status = htons (GNUNET_SETI_STATUS_FAILURE);
+    GNUNET_MQ_send (set->cs->mq, ev);
+    GNUNET_SERVICE_client_continue (cs->client);
+    return;
+  }
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "Client accepting request %u\n",
+              (uint32_t) ntohl (msg->accept_reject_id));
+  listener = op->listener;
+  op->listener = NULL;
+  op->return_intersection = htonl (msg->return_intersection);
+  fprintf (stderr,
+           "Return intersection for accept is %d\n",
+           op->return_intersection);
+  GNUNET_CONTAINER_DLL_remove (listener->op_head,
+                               listener->op_tail,
+                               op);
+  op->set = set;
+  GNUNET_CONTAINER_DLL_insert (set->ops_head,
+                               set->ops_tail,
+                               op);
+  op->client_request_id = ntohl (msg->request_id);
+
+  /* Advance generation values, so that future mutations do not
+     interfer with the running operation. */
+  op->generation_created = set->current_generation;
+  advance_generation (set);
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                "Accepting set intersection operation\n");
+    op->phase = PHASE_INITIAL;
+    op->my_element_count
+      = op->set->current_set_element_count;
+    op->my_elements
+      = GNUNET_CONTAINER_multihashmap_create (
+          GNUNET_MIN (op->my_element_count,
+                      op->remote_element_count),
+          GNUNET_YES);
+    if (op->remote_element_count < op->my_element_count)
+    {
+      /* If the other peer (Alice) has fewer elements than us (Bob),
+         we just send the count as Alice should send the first BF */
+      send_element_count (op);
+      op->phase = PHASE_COUNT_SENT;
+    }
+    else
+    {
+      /* We have fewer elements, so we start with the BF */
+      begin_bf_exchange (op);
+    }
+  }
+  /* Now allow CADET to continue, as we did not do this in
+   #handle_incoming_msg (as we wanted to first see if the
+     local client would accept the request). */
+  GNUNET_CADET_receive_done (op->channel);
+  GNUNET_SERVICE_client_continue (cs->client);
+}
+
+
+/**
+ * Called to clean up, after a shutdown has been requested.
+ *
+ * @param cls closure, NULL
+ */
+static void
+shutdown_task (void *cls)
+{
+  /* Delay actual shutdown to allow service to disconnect clients */
+  in_shutdown = GNUNET_YES;
+  if (0 == num_clients)
+  {
+    if (NULL != cadet)
+    {
+      GNUNET_CADET_disconnect (cadet);
+      cadet = NULL;
+    }
+  }
+  GNUNET_STATISTICS_destroy (_GSS_statistics,
+                             GNUNET_YES);
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "handled shutdown request\n");
+}
+
+
+/**
+ * Function called by the service's run
+ * method to run service-specific setup code.
+ *
+ * @param cls closure
+ * @param cfg configuration to use
+ * @param service the initialized service
+ */
+static void
+run (void *cls,
+     const struct GNUNET_CONFIGURATION_Handle *cfg,
+     struct GNUNET_SERVICE_Handle *service)
+{
+  /* FIXME: need to modify SERVICE (!) API to allow
+     us to run a shutdown task *after* clients were
+     forcefully disconnected! */
+  GNUNET_SCHEDULER_add_shutdown (&shutdown_task,
+                                 NULL);
+  _GSS_statistics = GNUNET_STATISTICS_create ("seti",
+                                              cfg);
+  cadet = GNUNET_CADET_connect (cfg);
+  if (NULL == cadet)
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                _ ("Could not connect to CADET service\n"));
+    GNUNET_SCHEDULER_shutdown ();
+    return;
+  }
+}
+
+
+/**
+ * Define "main" method using service macro.
+ */
+GNUNET_SERVICE_MAIN (
+  "seti",
+  GNUNET_SERVICE_OPTION_NONE,
+  &run,
+  &client_connect_cb,
+  &client_disconnect_cb,
+  NULL,
+  GNUNET_MQ_hd_fixed_size (client_accept,
+                           GNUNET_MESSAGE_TYPE_SETI_ACCEPT,
+                           struct GNUNET_SETI_AcceptMessage,
+                           NULL),
+  GNUNET_MQ_hd_var_size (client_set_add,
+                         GNUNET_MESSAGE_TYPE_SETI_ADD,
+                         struct GNUNET_SETI_ElementMessage,
+                         NULL),
+  GNUNET_MQ_hd_fixed_size (client_create_set,
+                           GNUNET_MESSAGE_TYPE_SETI_CREATE,
+                           struct GNUNET_SETI_CreateMessage,
+                           NULL),
+  GNUNET_MQ_hd_var_size (client_evaluate,
+                         GNUNET_MESSAGE_TYPE_SETI_EVALUATE,
+                         struct GNUNET_SETI_EvaluateMessage,
+                         NULL),
+  GNUNET_MQ_hd_fixed_size (client_listen,
+                           GNUNET_MESSAGE_TYPE_SETI_LISTEN,
+                           struct GNUNET_SETI_ListenMessage,
+                           NULL),
+  GNUNET_MQ_hd_fixed_size (client_reject,
+                           GNUNET_MESSAGE_TYPE_SETI_REJECT,
+                           struct GNUNET_SETI_RejectMessage,
+                           NULL),
+  GNUNET_MQ_hd_fixed_size (client_cancel,
+                           GNUNET_MESSAGE_TYPE_SETI_CANCEL,
+                           struct GNUNET_SETI_CancelMessage,
+                           NULL),
+  GNUNET_MQ_handler_end ());
+
+
+/* end of gnunet-service-seti.c */
diff --git a/src/seti/gnunet-service-seti_protocol.h b/src/seti/gnunet-service-seti_protocol.h
new file mode 100644
index 0000000000000000000000000000000000000000..51968376eb67dfa8c4dafd06d7f3097b9cc5872b
--- /dev/null
+++ b/src/seti/gnunet-service-seti_protocol.h
@@ -0,0 +1,144 @@
+/*
+     This file is part of GNUnet.
+     Copyright (C) 2013, 2014, 2020 GNUnet e.V.
+
+     GNUnet is free software: you can redistribute it and/or modify it
+     under the terms of the GNU Affero General Public License as published
+     by the Free Software Foundation, either version 3 of the License,
+     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
+     Affero General Public License for more details.
+
+     You should have received a copy of the GNU Affero General Public License
+     along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+     SPDX-License-Identifier: AGPL3.0-or-later
+ */
+/**
+ * @author Florian Dold
+ * @author Christian Grothoff
+ * @file seti/gnunet-service-seti_protocol.h
+ * @brief Peer-to-Peer messages for gnunet set
+ */
+#ifndef SETI_PROTOCOL_H
+#define SETI_PROTOCOL_H
+
+#include "platform.h"
+#include "gnunet_common.h"
+
+
+GNUNET_NETWORK_STRUCT_BEGIN
+
+struct OperationRequestMessage
+{
+  /**
+   * Type: #GNUNET_MESSAGE_TYPE_SET_P2P_OPERATION_REQUEST
+   */
+  struct GNUNET_MessageHeader header;
+
+  /**
+   * For Intersection: my element count
+   */
+  uint32_t element_count GNUNET_PACKED;
+
+  /**
+   * Application-specific identifier of the request.
+   */
+  struct GNUNET_HashCode app_idX;
+
+  /* rest: optional message */
+};
+
+
+/**
+ * During intersection, the first (and possibly second) message
+ * send it the number of elements in the set, to allow the peers
+ * to decide who should start with the Bloom filter.
+ */
+struct IntersectionElementInfoMessage
+{
+  /**
+   * Type: #GNUNET_MESSAGE_TYPE_SET_INTERSECTION_P2P_ELEMENT_INFO
+   */
+  struct GNUNET_MessageHeader header;
+
+  /**
+   * mutator used with this bloomfilter.
+   */
+  uint32_t sender_element_count GNUNET_PACKED;
+};
+
+
+/**
+ * Bloom filter messages exchanged for set intersection calculation.
+ */
+struct BFMessage
+{
+  /**
+   * Type: #GNUNET_MESSAGE_TYPE_SET_INTERSECTION_P2P_BF
+   */
+  struct GNUNET_MessageHeader header;
+
+  /**
+   * Number of elements the sender still has in the set.
+   */
+  uint32_t sender_element_count GNUNET_PACKED;
+
+  /**
+   * XOR of all hashes over all elements remaining in the set.
+   * Used to determine termination.
+   */
+  struct GNUNET_HashCode element_xor_hash;
+
+  /**
+   * Mutator used with this bloomfilter.
+   */
+  uint32_t sender_mutator GNUNET_PACKED;
+
+  /**
+   * Total length of the bloomfilter data.
+   */
+  uint32_t bloomfilter_total_length GNUNET_PACKED;
+
+  /**
+   * Number of bits (k-value) used in encoding the bloomfilter.
+   */
+  uint32_t bits_per_element GNUNET_PACKED;
+
+  /**
+   * rest: the sender's bloomfilter
+   */
+};
+
+
+/**
+ * Last message, send to confirm the final set.  Contains the element
+ * count as it is possible that the peer determined that we were done
+ * by getting the empty set, which in that case also needs to be
+ * communicated.
+ */
+struct IntersectionDoneMessage
+{
+  /**
+   * Type: #GNUNET_MESSAGE_TYPE_SET_INTERSECTION_P2P_DONE
+   */
+  struct GNUNET_MessageHeader header;
+
+  /**
+   * Final number of elements in intersection.
+   */
+  uint32_t final_element_count GNUNET_PACKED;
+
+  /**
+   * XOR of all hashes over all elements remaining in the set.
+   */
+  struct GNUNET_HashCode element_xor_hash;
+};
+
+
+GNUNET_NETWORK_STRUCT_END
+
+#endif
diff --git a/src/seti/gnunet-seti-profiler.c b/src/seti/gnunet-seti-profiler.c
new file mode 100644
index 0000000000000000000000000000000000000000..b8230bcfcd6df8a3a5ab6eda33ed2076e6bdc0a7
--- /dev/null
+++ b/src/seti/gnunet-seti-profiler.c
@@ -0,0 +1,480 @@
+/*
+      This file is part of GNUnet
+      Copyright (C) 2013, 2020 GNUnet e.V.
+
+      GNUnet is free software: you can redistribute it and/or modify it
+      under the terms of the GNU Affero General Public License as published
+      by the Free Software Foundation, either version 3 of the License,
+      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
+      Affero General Public License for more details.
+
+      You should have received a copy of the GNU Affero General Public License
+      along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+     SPDX-License-Identifier: AGPL3.0-or-later
+ */
+
+/**
+ * @file set/gnunet-seti-profiler.c
+ * @brief profiling tool for set intersection
+ * @author Florian Dold
+ */
+#include "platform.h"
+#include "gnunet_util_lib.h"
+#include "gnunet_statistics_service.h"
+#include "gnunet_seti_service.h"
+#include "gnunet_testbed_service.h"
+
+
+static int ret;
+
+static unsigned int num_a = 5;
+static unsigned int num_b = 5;
+static unsigned int num_c = 20;
+
+const static struct GNUNET_CONFIGURATION_Handle *config;
+
+struct SetInfo
+{
+  char *id;
+  struct GNUNET_SETI_Handle *set;
+  struct GNUNET_SETI_OperationHandle *oh;
+  struct GNUNET_CONTAINER_MultiHashMap *sent;
+  struct GNUNET_CONTAINER_MultiHashMap *received;
+  int done;
+} info1, info2;
+
+static struct GNUNET_CONTAINER_MultiHashMap *common_sent;
+
+static struct GNUNET_HashCode app_id;
+
+static struct GNUNET_PeerIdentity local_peer;
+
+static struct GNUNET_SETI_ListenHandle *set_listener;
+
+static unsigned int use_intersection;
+
+static unsigned int element_size = 32;
+
+/**
+ * Handle to the statistics service.
+ */
+static struct GNUNET_STATISTICS_Handle *statistics;
+
+/**
+ * The profiler will write statistics
+ * for all peers to the file with this name.
+ */
+static char *statistics_filename;
+
+/**
+ * The profiler will write statistics
+ * for all peers to this file.
+ */
+static FILE *statistics_file;
+
+
+static int
+map_remove_iterator (void *cls,
+                     const struct GNUNET_HashCode *key,
+                     void *value)
+{
+  struct GNUNET_CONTAINER_MultiHashMap *m = cls;
+  int ret;
+
+  GNUNET_assert (NULL != key);
+
+  ret = GNUNET_CONTAINER_multihashmap_remove_all (m, key);
+  if (GNUNET_OK != ret)
+    printf ("spurious element\n");
+  return GNUNET_YES;
+}
+
+
+/**
+ * Callback function to process statistic values.
+ *
+ * @param cls closure
+ * @param subsystem name of subsystem that created the statistic
+ * @param name the name of the datum
+ * @param value the current value
+ * @param is_persistent #GNUNET_YES if the value is persistent, #GNUNET_NO if not
+ * @return #GNUNET_OK to continue, #GNUNET_SYSERR to abort iteration
+ */
+static int
+statistics_result (void *cls,
+                   const char *subsystem,
+                   const char *name,
+                   uint64_t value,
+                   int is_persistent)
+{
+  if (NULL != statistics_file)
+  {
+    fprintf (statistics_file, "%s\t%s\t%lu\n", subsystem, name, (unsigned
+                                                                 long) value);
+  }
+  return GNUNET_OK;
+}
+
+
+static void
+statistics_done (void *cls,
+                 int success)
+{
+  GNUNET_assert (GNUNET_YES == success);
+  if (NULL != statistics_file)
+    fclose (statistics_file);
+  GNUNET_SCHEDULER_shutdown ();
+}
+
+
+static void
+check_all_done (void)
+{
+  if ((info1.done == GNUNET_NO) || (info2.done == GNUNET_NO))
+    return;
+
+  GNUNET_CONTAINER_multihashmap_iterate (info1.received, map_remove_iterator,
+                                         info2.sent);
+  GNUNET_CONTAINER_multihashmap_iterate (info2.received, map_remove_iterator,
+                                         info1.sent);
+
+  printf ("set a: %d missing elements\n", GNUNET_CONTAINER_multihashmap_size (
+            info1.sent));
+  printf ("set b: %d missing elements\n", GNUNET_CONTAINER_multihashmap_size (
+            info2.sent));
+
+  if (NULL == statistics_filename)
+  {
+    GNUNET_SCHEDULER_shutdown ();
+    return;
+  }
+
+  statistics_file = fopen (statistics_filename, "w");
+  GNUNET_STATISTICS_get (statistics, NULL, NULL,
+                         &statistics_done,
+                         &statistics_result, NULL);
+}
+
+
+static void
+set_result_cb (void *cls,
+               const struct GNUNET_SETI_Element *element,
+               uint64_t current_size,
+               enum GNUNET_SETI_Status status)
+{
+  struct SetInfo *info = cls;
+  struct GNUNET_HashCode hash;
+
+  GNUNET_assert (GNUNET_NO == info->done);
+  switch (status)
+  {
+  case GNUNET_SETI_STATUS_DONE:
+    info->done = GNUNET_YES;
+    GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+                "set intersection done\n");
+    check_all_done ();
+    info->oh = NULL;
+    return;
+  case GNUNET_SETI_STATUS_FAILURE:
+    info->oh = NULL;
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                "failure\n");
+    GNUNET_SCHEDULER_shutdown ();
+    return;
+  case GNUNET_SETI_STATUS_ADD_LOCAL:
+    GNUNET_CRYPTO_hash (element->data,
+                        element->size,
+                        &hash);
+    GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+                "set %s: keep element %s\n",
+                info->id,
+                GNUNET_h2s (&hash));
+    break;
+  case GNUNET_SETI_STATUS_DEL_LOCAL:
+    GNUNET_CRYPTO_hash (element->data,
+                        element->size,
+                        &hash);
+    GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+                "set %s: remove element %s\n",
+                info->id,
+                GNUNET_h2s (&hash));
+    return;
+  default:
+    GNUNET_assert (0);
+  }
+
+  if (element->size != element_size)
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+                "wrong element size: %u, expected %u\n",
+                element->size,
+                (unsigned int) sizeof(struct GNUNET_HashCode));
+    GNUNET_assert (0);
+  }
+
+  GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+              "set %s: got element (%s)\n",
+              info->id, GNUNET_h2s (element->data));
+  GNUNET_assert (NULL != element->data);
+  {
+    struct GNUNET_HashCode data_hash;
+
+    GNUNET_CRYPTO_hash (element->data,
+                        element_size,
+                        &data_hash);
+    GNUNET_CONTAINER_multihashmap_put (info->received,
+                                       &data_hash,
+                                       NULL,
+                                       GNUNET_CONTAINER_MULTIHASHMAPOPTION_REPLACE);
+  }
+}
+
+
+static void
+set_listen_cb (void *cls,
+               const struct GNUNET_PeerIdentity *other_peer,
+               const struct GNUNET_MessageHeader *context_msg,
+               struct GNUNET_SETI_Request *request)
+{
+  /* max. 1 option plus terminator */
+  struct GNUNET_SETI_Option opts[2] = { { 0 } };
+  unsigned int n_opts = 0;
+
+  if (NULL == request)
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                "listener failed\n");
+    return;
+  }
+  GNUNET_assert (NULL == info2.oh);
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "set listen cb called\n");
+  if (use_intersection)
+  {
+    opts[n_opts++] = (struct GNUNET_SETI_Option) { .type =
+                                                     GNUNET_SETI_OPTION_RETURN_INTERSECTION };
+  }
+  opts[n_opts].type = GNUNET_SETI_OPTION_END;
+  info2.oh = GNUNET_SETI_accept (request,
+                                 opts,
+                                 &set_result_cb,
+                                 &info2);
+  GNUNET_SETI_commit (info2.oh,
+                      info2.set);
+}
+
+
+static int
+set_insert_iterator (void *cls,
+                     const struct GNUNET_HashCode *key,
+                     void *value)
+{
+  struct GNUNET_SETI_Handle *set = cls;
+  struct GNUNET_SETI_Element el;
+
+  el.element_type = 0;
+  el.data = value;
+  el.size = element_size;
+  GNUNET_SETI_add_element (set, &el, NULL, NULL);
+  return GNUNET_YES;
+}
+
+
+static void
+handle_shutdown (void *cls)
+{
+  GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+              "Shutting down set profiler\n");
+  if (NULL != set_listener)
+  {
+    GNUNET_SETI_listen_cancel (set_listener);
+    set_listener = NULL;
+  }
+  if (NULL != info1.oh)
+  {
+    GNUNET_SETI_operation_cancel (info1.oh);
+    info1.oh = NULL;
+  }
+  if (NULL != info2.oh)
+  {
+    GNUNET_SETI_operation_cancel (info2.oh);
+    info2.oh = NULL;
+  }
+  if (NULL != info1.set)
+  {
+    GNUNET_SETI_destroy (info1.set);
+    info1.set = NULL;
+  }
+  if (NULL != info2.set)
+  {
+    GNUNET_SETI_destroy (info2.set);
+    info2.set = NULL;
+  }
+  GNUNET_STATISTICS_destroy (statistics, GNUNET_NO);
+}
+
+
+static void
+run (void *cls,
+     const struct GNUNET_CONFIGURATION_Handle *cfg,
+     struct GNUNET_TESTING_Peer *peer)
+{
+  unsigned int i;
+  struct GNUNET_HashCode hash;
+  /* max. 1 option plus terminator */
+  struct GNUNET_SETI_Option opts[2] = { { 0 } };
+  unsigned int n_opts = 0;
+
+  config = cfg;
+
+  GNUNET_assert (element_size > 0);
+
+  if (GNUNET_OK != GNUNET_CRYPTO_get_peer_identity (cfg, &local_peer))
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                "could not retrieve host identity\n");
+    ret = 0;
+    return;
+  }
+  statistics = GNUNET_STATISTICS_create ("set-profiler", cfg);
+  GNUNET_SCHEDULER_add_shutdown (&handle_shutdown, NULL);
+  info1.id = "a";
+  info2.id = "b";
+  info1.sent = GNUNET_CONTAINER_multihashmap_create (num_a + 1, GNUNET_NO);
+  info2.sent = GNUNET_CONTAINER_multihashmap_create (num_b + 1, GNUNET_NO);
+  common_sent = GNUNET_CONTAINER_multihashmap_create (num_c + 1, GNUNET_NO);
+  info1.received = GNUNET_CONTAINER_multihashmap_create (num_a + 1, GNUNET_NO);
+  info2.received = GNUNET_CONTAINER_multihashmap_create (num_b + 1, GNUNET_NO);
+  for (i = 0; i < num_a; i++)
+  {
+    char *data = GNUNET_malloc (element_size);
+    GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_WEAK, data, element_size);
+    GNUNET_CRYPTO_hash (data, element_size, &hash);
+    GNUNET_CONTAINER_multihashmap_put (info1.sent, &hash, data,
+                                       GNUNET_CONTAINER_MULTIHASHMAPOPTION_REPLACE);
+  }
+
+  for (i = 0; i < num_b; i++)
+  {
+    char *data = GNUNET_malloc (element_size);
+    GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_WEAK, data, element_size);
+    GNUNET_CRYPTO_hash (data, element_size, &hash);
+    GNUNET_CONTAINER_multihashmap_put (info2.sent, &hash, data,
+                                       GNUNET_CONTAINER_MULTIHASHMAPOPTION_REPLACE);
+  }
+
+  for (i = 0; i < num_c; i++)
+  {
+    char *data = GNUNET_malloc (element_size);
+    GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_WEAK, data, element_size);
+    GNUNET_CRYPTO_hash (data, element_size, &hash);
+    GNUNET_CONTAINER_multihashmap_put (common_sent, &hash, data,
+                                       GNUNET_CONTAINER_MULTIHASHMAPOPTION_REPLACE);
+  }
+
+  GNUNET_CRYPTO_hash_create_random (GNUNET_CRYPTO_QUALITY_STRONG, &app_id);
+
+  info1.set = GNUNET_SETI_create (config);
+  info2.set = GNUNET_SETI_create (config);
+  GNUNET_CONTAINER_multihashmap_iterate (info1.sent,
+                                         &set_insert_iterator,
+                                         info1.set);
+  GNUNET_CONTAINER_multihashmap_iterate (info2.sent,
+                                         &set_insert_iterator,
+                                         info2.set);
+  GNUNET_CONTAINER_multihashmap_iterate (common_sent,
+                                         &set_insert_iterator,
+                                         info1.set);
+  GNUNET_CONTAINER_multihashmap_iterate (common_sent,
+                                         &set_insert_iterator,
+                                         info2.set);
+
+  set_listener = GNUNET_SETI_listen (config,
+                                     &app_id,
+                                     &set_listen_cb,
+                                     NULL);
+  if (use_intersection)
+  {
+    opts[n_opts++] = (struct GNUNET_SETI_Option) { .type =
+                                                     GNUNET_SETI_OPTION_RETURN_INTERSECTION };
+  }
+  opts[n_opts].type = GNUNET_SETI_OPTION_END;
+
+  info1.oh = GNUNET_SETI_prepare (&local_peer,
+                                  &app_id,
+                                  NULL,
+                                  opts,
+                                  set_result_cb,
+                                  &info1);
+  GNUNET_SETI_commit (info1.oh,
+                      info1.set);
+  GNUNET_SETI_destroy (info1.set);
+  info1.set = NULL;
+}
+
+
+static void
+pre_run (void *cls,
+         char *const *args,
+         const char *cfgfile,
+         const struct GNUNET_CONFIGURATION_Handle *cfg)
+{
+  if (0 != GNUNET_TESTING_peer_run ("set-profiler",
+                                    cfgfile,
+                                    &run, NULL))
+    ret = 2;
+}
+
+
+int
+main (int argc, char **argv)
+{
+  struct GNUNET_GETOPT_CommandLineOption options[] = {
+    GNUNET_GETOPT_option_uint ('A',
+                               "num-first",
+                               NULL,
+                               gettext_noop ("number of values"),
+                               &num_a),
+    GNUNET_GETOPT_option_uint ('B',
+                               "num-second",
+                               NULL,
+                               gettext_noop ("number of values"),
+                               &num_b),
+    GNUNET_GETOPT_option_uint ('C',
+                               "num-common",
+                               NULL,
+                               gettext_noop ("number of values"),
+                               &num_c),
+    GNUNET_GETOPT_option_uint ('i',
+                               "use-intersection",
+                               NULL,
+                               gettext_noop (
+                                 "return intersection instead of delta"),
+                               &use_intersection),
+    GNUNET_GETOPT_option_uint ('w',
+                               "element-size",
+                               NULL,
+                               gettext_noop ("element size"),
+                               &element_size),
+    GNUNET_GETOPT_option_filename ('s',
+                                   "statistics",
+                                   "FILENAME",
+                                   gettext_noop ("write statistics to file"),
+                                   &statistics_filename),
+    GNUNET_GETOPT_OPTION_END
+  };
+
+  GNUNET_PROGRAM_run2 (argc, argv,
+                       "gnunet-seti-profiler",
+                       "help",
+                       options,
+                       &pre_run,
+                       NULL,
+                       GNUNET_YES);
+  return ret;
+}
diff --git a/src/seti/plugin_block_seti_test.c b/src/seti/plugin_block_seti_test.c
new file mode 100644
index 0000000000000000000000000000000000000000..55cf31beadfbdb363320883f7cf855b2fab346c6
--- /dev/null
+++ b/src/seti/plugin_block_seti_test.c
@@ -0,0 +1,123 @@
+/*
+     This file is part of GNUnet
+     Copyright (C) 2017 GNUnet e.V.
+
+     GNUnet is free software: you can redistribute it and/or modify it
+     under the terms of the GNU Affero General Public License as published
+     by the Free Software Foundation, either version 3 of the License,
+     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
+     Affero General Public License for more details.
+
+     You should have received a copy of the GNU Affero General Public License
+     along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+     SPDX-License-Identifier: AGPL3.0-or-later
+ */
+
+/**
+ * @file seti/plugin_block_seti_test.c
+ * @brief set test block, recognizes elements with non-zero first byte as invalid
+ * @author Christian Grothoff
+ */
+
+#include "platform.h"
+#include "gnunet_block_plugin.h"
+#include "gnunet_block_group_lib.h"
+
+
+/**
+ * Function called to validate a reply or a request.  For
+ * request evaluation, simply pass "NULL" for the reply_block.
+ *
+ * @param cls closure
+ * @param ctx block context
+ * @param type block type
+ * @param group block group to use
+ * @param eo control flags
+ * @param query original query (hash)
+ * @param xquery extrended query data (can be NULL, depending on type)
+ * @param xquery_size number of bytes in xquery
+ * @param reply_block response to validate
+ * @param reply_block_size number of bytes in reply block
+ * @return characterization of result
+ */
+static enum GNUNET_BLOCK_EvaluationResult
+block_plugin_seti_test_evaluate (void *cls,
+                                 struct GNUNET_BLOCK_Context *ctx,
+                                 enum GNUNET_BLOCK_Type type,
+                                 struct GNUNET_BLOCK_Group *group,
+                                 enum GNUNET_BLOCK_EvaluationOptions eo,
+                                 const struct GNUNET_HashCode *query,
+                                 const void *xquery,
+                                 size_t xquery_size,
+                                 const void *reply_block,
+                                 size_t reply_block_size)
+{
+  if ((NULL == reply_block) ||
+      (reply_block_size == 0) ||
+      (0 != ((char *) reply_block)[0]))
+    return GNUNET_BLOCK_EVALUATION_RESULT_INVALID;
+  return GNUNET_BLOCK_EVALUATION_OK_MORE;
+}
+
+
+/**
+ * Function called to obtain the key for a block.
+ *
+ * @param cls closure
+ * @param type block type
+ * @param block block to get the key for
+ * @param block_size number of bytes in block
+ * @param key set to the key (query) for the given block
+ * @return #GNUNET_OK on success, #GNUNET_SYSERR if type not supported
+ *         (or if extracting a key from a block of this type does not work)
+ */
+static int
+block_plugin_seti_test_get_key (void *cls,
+                                enum GNUNET_BLOCK_Type type,
+                                const void *block,
+                                size_t block_size,
+                                struct GNUNET_HashCode *key)
+{
+  return GNUNET_SYSERR;
+}
+
+
+/**
+ * Entry point for the plugin.
+ */
+void *
+libgnunet_plugin_block_seti_test_init (void *cls)
+{
+  static enum GNUNET_BLOCK_Type types[] = {
+    GNUNET_BLOCK_TYPE_SETI_TEST,
+    GNUNET_BLOCK_TYPE_ANY       /* end of list */
+  };
+  struct GNUNET_BLOCK_PluginFunctions *api;
+
+  api = GNUNET_new (struct GNUNET_BLOCK_PluginFunctions);
+  api->evaluate = &block_plugin_seti_test_evaluate;
+  api->get_key = &block_plugin_seti_test_get_key;
+  api->types = types;
+  return api;
+}
+
+
+/**
+ * Exit point from the plugin.
+ */
+void *
+libgnunet_plugin_block_seti_test_done (void *cls)
+{
+  struct GNUNET_BLOCK_PluginFunctions *api = cls;
+
+  GNUNET_free (api);
+  return NULL;
+}
+
+
+/* end of plugin_block_seti_test.c */
diff --git a/src/seti/seti.conf.in b/src/seti/seti.conf.in
new file mode 100644
index 0000000000000000000000000000000000000000..e4f7b60b5f49be55de5b5edc1e001b4d532a561b
--- /dev/null
+++ b/src/seti/seti.conf.in
@@ -0,0 +1,12 @@
+[seti]
+START_ON_DEMAND = @START_ON_DEMAND@
+@UNIXONLY@PORT = 2106
+HOSTNAME = localhost
+BINARY = gnunet-service-seti
+ACCEPT_FROM = 127.0.0.1;
+ACCEPT_FROM6 = ::1;
+UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-service-seti.sock
+UNIX_MATCH_UID = YES
+UNIX_MATCH_GID = YES
+
+#PREFIX = valgrind
diff --git a/src/seti/seti.h b/src/seti/seti.h
new file mode 100644
index 0000000000000000000000000000000000000000..aa7014034615dcdd4623e927dee1c762b5715243
--- /dev/null
+++ b/src/seti/seti.h
@@ -0,0 +1,267 @@
+/*
+     This file is part of GNUnet.
+     Copyright (C) 2012-2014, 2020 GNUnet e.V.
+
+     GNUnet is free software: you can redistribute it and/or modify it
+     under the terms of the GNU Affero General Public License as published
+     by the Free Software Foundation, either version 3 of the License,
+     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
+     Affero General Public License for more details.
+
+     You should have received a copy of the GNU Affero General Public License
+     along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+     SPDX-License-Identifier: AGPL3.0-or-later
+ */
+/**
+ * @file set/seti.h
+ * @brief messages used for the set intersection api
+ * @author Florian Dold
+ * @author Christian Grothoff
+ */
+#ifndef SETI_H
+#define SETI_H
+
+#include "platform.h"
+#include "gnunet_common.h"
+#include "gnunet_set_service.h"
+
+GNUNET_NETWORK_STRUCT_BEGIN
+
+/**
+ * Message sent by the client to the service to ask starting
+ * a new set to perform operations with.
+ */
+struct GNUNET_SETI_CreateMessage
+{
+  /**
+   * Type: #GNUNET_MESSAGE_TYPE_SETI_CREATE
+   */
+  struct GNUNET_MessageHeader header;
+};
+
+
+/**
+ * Message sent by the client to the service to start listening for
+ * incoming requests to perform a certain type of set operation for a
+ * certain type of application.
+ */
+struct GNUNET_SETI_ListenMessage
+{
+  /**
+   * Type: #GNUNET_MESSAGE_TYPE_SETI_LISTEN
+   */
+  struct GNUNET_MessageHeader header;
+
+  /**
+   * Operation type, values of `enum GNUNET_SETI_OperationType`
+   */
+  uint32_t operation GNUNET_PACKED;
+
+  /**
+   * application id
+   */
+  struct GNUNET_HashCode app_id;
+};
+
+
+/**
+ * Message sent by a listening client to the service to accept
+ * performing the operation with the other peer.
+ */
+struct GNUNET_SETI_AcceptMessage
+{
+  /**
+   * Type: #GNUNET_MESSAGE_TYPE_SETI_ACCEPT
+   */
+  struct GNUNET_MessageHeader header;
+
+  /**
+   * ID of the incoming request we want to accept.
+   */
+  uint32_t accept_reject_id GNUNET_PACKED;
+
+  /**
+   * Request ID to identify responses.
+   */
+  uint32_t request_id GNUNET_PACKED;
+
+  /**
+   * Return the intersection (1), instead of the elements to
+   * remove / the delta (0), in NBO.
+   */
+  uint32_t return_intersection;
+
+};
+
+
+/**
+ * Message sent by a listening client to the service to reject
+ * performing the operation with the other peer.
+ */
+struct GNUNET_SETI_RejectMessage
+{
+  /**
+   * Type: #GNUNET_MESSAGE_TYPE_SETI_REJECT
+   */
+  struct GNUNET_MessageHeader header;
+
+  /**
+   * ID of the incoming request we want to reject.
+   */
+  uint32_t accept_reject_id GNUNET_PACKED;
+};
+
+
+/**
+ * A request for an operation with another client.
+ */
+struct GNUNET_SETI_RequestMessage
+{
+  /**
+   * Type: #GNUNET_MESSAGE_TYPE_SETI_REQUEST.
+   */
+  struct GNUNET_MessageHeader header;
+
+  /**
+   * ID of the to identify the request when accepting or
+   * rejecting it.
+   */
+  uint32_t accept_id GNUNET_PACKED;
+
+  /**
+   * Identity of the requesting peer.
+   */
+  struct GNUNET_PeerIdentity peer_id;
+
+  /* rest: context message, that is, application-specific
+     message to convince listener to pick up */
+};
+
+
+/**
+ * Message sent by client to service to initiate a set operation as a
+ * client (not as listener).  A set (which determines the operation
+ * type) must already exist in association with this client.
+ */
+struct GNUNET_SETI_EvaluateMessage
+{
+  /**
+   * Type: #GNUNET_MESSAGE_TYPE_SETI_EVALUATE
+   */
+  struct GNUNET_MessageHeader header;
+
+  /**
+   * Id of our set to evaluate, chosen implicitly by the client when it
+   * calls #GNUNET_SETI_commit().
+   */
+  uint32_t request_id GNUNET_PACKED;
+
+  /**
+   * Peer to evaluate the operation with
+   */
+  struct GNUNET_PeerIdentity target_peer;
+
+  /**
+   * Application id
+   */
+  struct GNUNET_HashCode app_id;
+
+  /**
+   * Return the intersection (1), instead of the elements to
+   * remove / the delta (0), in NBO.
+   */
+  uint32_t return_intersection;
+
+  /* rest: context message, that is, application-specific
+     message to convince listener to pick up */
+};
+
+
+/**
+ * Message sent by the service to the client to indicate an
+ * element that is removed (set intersection) or added
+ * (set union) or part of the final result, depending on
+ * options specified for the operation.
+ */
+struct GNUNET_SETI_ResultMessage
+{
+  /**
+   * Type: #GNUNET_MESSAGE_TYPE_SETI_RESULT
+   */
+  struct GNUNET_MessageHeader header;
+
+  /**
+   * Current set size.
+   */
+  uint64_t current_size;
+
+  /**
+   * id the result belongs to
+   */
+  uint32_t request_id GNUNET_PACKED;
+
+  /**
+   * Was the evaluation successful? Contains
+   * an `enum GNUNET_SETI_Status` in NBO.
+   */
+  uint16_t result_status GNUNET_PACKED;
+
+  /**
+   * Type of the element attachted to the message, if any.
+   */
+  uint16_t element_type GNUNET_PACKED;
+
+  /* rest: the actual element */
+};
+
+
+/**
+ * Message sent by client to the service to add an element to the set.
+ */
+struct GNUNET_SETI_ElementMessage
+{
+  /**
+   * Type: #GNUNET_MESSAGE_TYPE_SETI_ADD.
+   */
+  struct GNUNET_MessageHeader header;
+
+  /**
+   * Type of the element to add or remove.
+   */
+  uint16_t element_type GNUNET_PACKED;
+
+  /**
+   * For alignment, always zero.
+   */
+  uint16_t reserved GNUNET_PACKED;
+
+  /* rest: the actual element */
+};
+
+
+/**
+ * Sent to the service by the client
+ * in order to cancel a set operation.
+ */
+struct GNUNET_SETI_CancelMessage
+{
+  /**
+   * Type: #GNUNET_MESSAGE_TYPE_SETI_CANCEL
+   */
+  struct GNUNET_MessageHeader header;
+
+  /**
+   * ID of the request we want to cancel.
+   */
+  uint32_t request_id GNUNET_PACKED;
+};
+
+
+GNUNET_NETWORK_STRUCT_END
+
+#endif
diff --git a/src/seti/seti_api.c b/src/seti/seti_api.c
new file mode 100644
index 0000000000000000000000000000000000000000..5b88b04698605944cfbc14ab7482a530dab52e19
--- /dev/null
+++ b/src/seti/seti_api.c
@@ -0,0 +1,896 @@
+/*
+     This file is part of GNUnet.
+     Copyright (C) 2012-2016, 2020 GNUnet e.V.
+
+     GNUnet is free software: you can redistribute it and/or modify it
+     under the terms of the GNU Affero General Public License as published
+     by the Free Software Foundation, either version 3 of the License,
+     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
+     Affero General Public License for more details.
+
+     You should have received a copy of the GNU Affero General Public License
+     along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+     SPDX-License-Identifier: AGPL3.0-or-later
+ */
+/**
+ * @file seti/seti_api.c
+ * @brief api for the set service
+ * @author Florian Dold
+ * @author Christian Grothoff
+ */
+#include "platform.h"
+#include "gnunet_util_lib.h"
+#include "gnunet_protocols.h"
+#include "gnunet_seti_service.h"
+#include "seti.h"
+
+
+#define LOG(kind, ...) GNUNET_log_from (kind, "seti-api", __VA_ARGS__)
+
+
+/**
+ * Opaque handle to a set.
+ */
+struct GNUNET_SETI_Handle
+{
+  /**
+   * Message queue for @e client.
+   */
+  struct GNUNET_MQ_Handle *mq;
+
+  /**
+   * Linked list of operations on the set.
+   */
+  struct GNUNET_SETI_OperationHandle *ops_head;
+
+  /**
+   * Linked list of operations on the set.
+   */
+  struct GNUNET_SETI_OperationHandle *ops_tail;
+
+  /**
+   * Configuration, needed when creating (lazy) copies.
+   */
+  const struct GNUNET_CONFIGURATION_Handle *cfg;
+
+  /**
+   * Should the set be destroyed once all operations are gone?
+   * #GNUNET_SYSERR if #GNUNET_SETI_destroy() must raise this flag,
+   * #GNUNET_YES if #GNUNET_SETI_destroy() did raise this flag.
+   */
+  int destroy_requested;
+
+  /**
+   * Has the set become invalid (e.g. service died)?
+   */
+  int invalid;
+
+  /**
+   * Both client and service count the number of iterators
+   * created so far to match replies with iterators.
+   */
+  uint16_t iteration_id;
+
+};
+
+
+/**
+ * Handle for a set operation request from another peer.
+ */
+struct GNUNET_SETI_Request
+{
+  /**
+   * Id of the request, used to identify the request when
+   * accepting/rejecting it.
+   */
+  uint32_t accept_id;
+
+  /**
+   * Has the request been accepted already?
+   * #GNUNET_YES/#GNUNET_NO
+   */
+  int accepted;
+};
+
+
+/**
+ * Handle to an operation.  Only known to the service after committing
+ * the handle with a set.
+ */
+struct GNUNET_SETI_OperationHandle
+{
+  /**
+   * Function to be called when we have a result,
+   * or an error.
+   */
+  GNUNET_SETI_ResultIterator result_cb;
+
+  /**
+   * Closure for @e result_cb.
+   */
+  void *result_cls;
+
+  /**
+   * Local set used for the operation,
+   * NULL if no set has been provided by conclude yet.
+   */
+  struct GNUNET_SETI_Handle *set;
+
+  /**
+   * Message sent to the server on calling conclude,
+   * NULL if conclude has been called.
+   */
+  struct GNUNET_MQ_Envelope *conclude_mqm;
+
+  /**
+   * Address of the request if in the conclude message,
+   * used to patch the request id into the message when the set is known.
+   */
+  uint32_t *request_id_addr;
+
+  /**
+   * Handles are kept in a linked list.
+   */
+  struct GNUNET_SETI_OperationHandle *prev;
+
+  /**
+   * Handles are kept in a linked list.
+   */
+  struct GNUNET_SETI_OperationHandle *next;
+
+  /**
+   * Request ID to identify the operation within the set.
+   */
+  uint32_t request_id;
+
+  /**
+   * Should we return the resulting intersection (ADD) or
+   * the elements to remove (DEL)?
+   */
+  int return_intersection;
+};
+
+
+/**
+ * Opaque handle to a listen operation.
+ */
+struct GNUNET_SETI_ListenHandle
+{
+  /**
+   * Message queue for the client.
+   */
+  struct GNUNET_MQ_Handle*mq;
+
+  /**
+   * Configuration handle for the listener, stored
+   * here to be able to reconnect transparently on
+   * connection failure.
+   */
+  const struct GNUNET_CONFIGURATION_Handle *cfg;
+
+  /**
+   * Function to call on a new incoming request,
+   * or on error.
+   */
+  GNUNET_SETI_ListenCallback listen_cb;
+
+  /**
+   * Closure for @e listen_cb.
+   */
+  void *listen_cls;
+
+  /**
+   * Task for reconnecting when the listener fails.
+   */
+  struct GNUNET_SCHEDULER_Task *reconnect_task;
+
+  /**
+   * Application ID we listen for.
+   */
+  struct GNUNET_HashCode app_id;
+
+  /**
+   * Time to wait until we try to reconnect on failure.
+   */
+  struct GNUNET_TIME_Relative reconnect_backoff;
+
+};
+
+
+/**
+ * Check that the given @a msg is well-formed.
+ *
+ * @param cls closure
+ * @param msg message to check
+ * @return #GNUNET_OK if message is well-formed
+ */
+static int
+check_result (void *cls,
+              const struct GNUNET_SETI_ResultMessage *msg)
+{
+  /* minimum size was already checked, everything else is OK! */
+  return GNUNET_OK;
+}
+
+
+/**
+ * Handle result message for a set operation.
+ *
+ * @param cls the set
+ * @param mh the message
+ */
+static void
+handle_result (void *cls,
+               const struct GNUNET_SETI_ResultMessage *msg)
+{
+  struct GNUNET_SETI_Handle *set = cls;
+  struct GNUNET_SETI_OperationHandle *oh;
+  struct GNUNET_SETI_Element e;
+  enum GNUNET_SETI_Status result_status;
+  int destroy_set;
+
+  GNUNET_assert (NULL != set->mq);
+  result_status = (enum GNUNET_SETI_Status) ntohs (msg->result_status);
+  LOG (GNUNET_ERROR_TYPE_DEBUG,
+       "Got result message with status %d\n",
+       result_status);
+  oh = GNUNET_MQ_assoc_get (set->mq,
+                            ntohl (msg->request_id));
+  if (NULL == oh)
+  {
+    /* 'oh' can be NULL if we canceled the operation, but the service
+       did not get the cancel message yet. */
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                "Ignoring result from canceled operation\n");
+    return;
+  }
+
+  switch (result_status)
+  {
+  case GNUNET_SETI_STATUS_ADD_LOCAL:
+  case GNUNET_SETI_STATUS_DEL_LOCAL:
+    e.data = &msg[1];
+    e.size = ntohs (msg->header.size)
+             - sizeof(struct GNUNET_SETI_ResultMessage);
+    e.element_type = ntohs (msg->element_type);
+    if (NULL != oh->result_cb)
+      oh->result_cb (oh->result_cls,
+                     &e,
+                     GNUNET_ntohll (msg->current_size),
+                     result_status);
+    return;
+  case GNUNET_SETI_STATUS_FAILURE:
+  case GNUNET_SETI_STATUS_DONE:
+    GNUNET_MQ_assoc_remove (set->mq,
+                            ntohl (msg->request_id));
+    GNUNET_CONTAINER_DLL_remove (set->ops_head,
+                                 set->ops_tail,
+                                 oh);
+    /* Need to do this calculation _before_ the result callback,
+       as IF the application still has a valid set handle, it
+       may trigger destruction of the set during the callback. */
+    destroy_set = (GNUNET_YES == set->destroy_requested) &&
+                  (NULL == set->ops_head);
+    if (NULL != oh->result_cb)
+    {
+      oh->result_cb (oh->result_cls,
+                     NULL,
+                     GNUNET_ntohll (msg->current_size),
+                     result_status);
+    }
+    else
+    {
+      LOG (GNUNET_ERROR_TYPE_DEBUG,
+           "No callback for final status\n");
+    }
+    if (destroy_set)
+      GNUNET_SETI_destroy (set);
+    GNUNET_free (oh);
+    return;
+  }
+}
+
+
+/**
+ * Destroy the given set operation.
+ *
+ * @param oh set operation to destroy
+ */
+static void
+set_operation_destroy (struct GNUNET_SETI_OperationHandle *oh)
+{
+  struct GNUNET_SETI_Handle *set = oh->set;
+  struct GNUNET_SETI_OperationHandle *h_assoc;
+
+  if (NULL != oh->conclude_mqm)
+    GNUNET_MQ_discard (oh->conclude_mqm);
+  /* is the operation already commited? */
+  if (NULL != set)
+  {
+    GNUNET_CONTAINER_DLL_remove (set->ops_head,
+                                 set->ops_tail,
+                                 oh);
+    h_assoc = GNUNET_MQ_assoc_remove (set->mq,
+                                      oh->request_id);
+    GNUNET_assert ((NULL == h_assoc) ||
+                   (h_assoc == oh));
+  }
+  GNUNET_free (oh);
+}
+
+
+/**
+ * Cancel the given set operation.  We need to send an explicit cancel
+ * message, as all operations one one set communicate using one
+ * handle.
+ *
+ * @param oh set operation to cancel
+ */
+void
+GNUNET_SETI_operation_cancel (struct GNUNET_SETI_OperationHandle *oh)
+{
+  struct GNUNET_SETI_Handle *set = oh->set;
+  struct GNUNET_SETI_CancelMessage *m;
+  struct GNUNET_MQ_Envelope *mqm;
+
+  LOG (GNUNET_ERROR_TYPE_DEBUG,
+       "Cancelling SET operation\n");
+  if (NULL != set)
+  {
+    mqm = GNUNET_MQ_msg (m, GNUNET_MESSAGE_TYPE_SETI_CANCEL);
+    m->request_id = htonl (oh->request_id);
+    GNUNET_MQ_send (set->mq, mqm);
+  }
+  set_operation_destroy (oh);
+  if ((NULL != set) &&
+      (GNUNET_YES == set->destroy_requested) &&
+      (NULL == set->ops_head))
+  {
+    LOG (GNUNET_ERROR_TYPE_DEBUG,
+         "Destroying set after operation cancel\n");
+    GNUNET_SETI_destroy (set);
+  }
+}
+
+
+/**
+ * We encountered an error communicating with the set service while
+ * performing a set operation. Report to the application.
+ *
+ * @param cls the `struct GNUNET_SETI_Handle`
+ * @param error error code
+ */
+static void
+handle_client_set_error (void *cls,
+                         enum GNUNET_MQ_Error error)
+{
+  struct GNUNET_SETI_Handle *set = cls;
+
+  LOG (GNUNET_ERROR_TYPE_ERROR,
+       "Handling client set error %d\n",
+       error);
+  while (NULL != set->ops_head)
+  {
+    if ((NULL != set->ops_head->result_cb) &&
+        (GNUNET_NO == set->destroy_requested))
+      set->ops_head->result_cb (set->ops_head->result_cls,
+                                NULL,
+                                0,
+                                GNUNET_SETI_STATUS_FAILURE);
+    set_operation_destroy (set->ops_head);
+  }
+  set->invalid = GNUNET_YES;
+}
+
+
+/**
+ * Create an empty set.
+ *
+ * @param cfg configuration to use for connecting to the
+ *        set service
+ * @return a handle to the set
+ */
+struct GNUNET_SETI_Handle *
+GNUNET_SETI_create (const struct GNUNET_CONFIGURATION_Handle *cfg)
+{
+  struct GNUNET_SETI_Handle *set = GNUNET_new (struct GNUNET_SETI_Handle);
+  struct GNUNET_MQ_MessageHandler mq_handlers[] = {
+    GNUNET_MQ_hd_var_size (result,
+                           GNUNET_MESSAGE_TYPE_SETI_RESULT,
+                           struct GNUNET_SETI_ResultMessage,
+                           set),
+    GNUNET_MQ_handler_end ()
+  };
+  struct GNUNET_MQ_Envelope *mqm;
+  struct GNUNET_SETI_CreateMessage *create_msg;
+
+  set->cfg = cfg;
+  set->mq = GNUNET_CLIENT_connect (cfg,
+                                   "seti",
+                                   mq_handlers,
+                                   &handle_client_set_error,
+                                   set);
+  if (NULL == set->mq)
+  {
+    GNUNET_free (set);
+    return NULL;
+  }
+  LOG (GNUNET_ERROR_TYPE_DEBUG,
+       "Creating new intersection set\n");
+  mqm = GNUNET_MQ_msg (create_msg,
+                       GNUNET_MESSAGE_TYPE_SETI_CREATE);
+  GNUNET_MQ_send (set->mq,
+                  mqm);
+  return set;
+}
+
+
+/**
+ * Add an element to the given set.  After the element has been added
+ * (in the sense of being transmitted to the set service), @a cont
+ * will be called.  Multiple calls to GNUNET_SETI_add_element() can be
+ * queued.
+ *
+ * @param set set to add element to
+ * @param element element to add to the set
+ * @param cb continuation called after the element has been added
+ * @param cb_cls closure for @a cont
+ * @return #GNUNET_OK on success, #GNUNET_SYSERR if the
+ *         set is invalid (e.g. the set service crashed)
+ */
+int
+GNUNET_SETI_add_element (struct GNUNET_SETI_Handle *set,
+                         const struct GNUNET_SETI_Element *element,
+                         GNUNET_SCHEDULER_TaskCallback cb,
+                         void *cb_cls)
+{
+  struct GNUNET_MQ_Envelope *mqm;
+  struct GNUNET_SETI_ElementMessage *msg;
+
+  LOG (GNUNET_ERROR_TYPE_DEBUG,
+       "adding element of type %u to set %p\n",
+       (unsigned int) element->element_type,
+       set);
+  if (GNUNET_YES == set->invalid)
+  {
+    if (NULL != cb)
+      cb (cb_cls);
+    return GNUNET_SYSERR;
+  }
+  mqm = GNUNET_MQ_msg_extra (msg,
+                             element->size,
+                             GNUNET_MESSAGE_TYPE_SETI_ADD);
+  msg->element_type = htons (element->element_type);
+  GNUNET_memcpy (&msg[1],
+                 element->data,
+                 element->size);
+  GNUNET_MQ_notify_sent (mqm,
+                         cb,
+                         cb_cls);
+  GNUNET_MQ_send (set->mq,
+                  mqm);
+  return GNUNET_OK;
+}
+
+
+/**
+ * Destroy the set handle if no operations are left, mark the set
+ * for destruction otherwise.
+ *
+ * @param set set handle to destroy
+ */
+void
+GNUNET_SETI_destroy (struct GNUNET_SETI_Handle *set)
+{
+  /* destroying set while iterator is active is currently
+     not supported; we should expand the API to allow
+     clients to explicitly cancel the iteration! */
+  if ((NULL != set->ops_head) ||
+      (GNUNET_SYSERR == set->destroy_requested))
+  {
+    LOG (GNUNET_ERROR_TYPE_DEBUG,
+         "Set operations are pending, delaying set destruction\n");
+    set->destroy_requested = GNUNET_YES;
+    return;
+  }
+  LOG (GNUNET_ERROR_TYPE_DEBUG,
+       "Really destroying set\n");
+  if (NULL != set->mq)
+  {
+    GNUNET_MQ_destroy (set->mq);
+    set->mq = NULL;
+  }
+  GNUNET_free (set);
+}
+
+
+/**
+ * Prepare a set operation to be evaluated with another peer.
+ * The evaluation will not start until the client provides
+ * a local set with #GNUNET_SETI_commit().
+ *
+ * @param other_peer peer with the other set
+ * @param app_id hash for the application using the set
+ * @param context_msg additional information for the request
+ * @param options options to use when processing the request
+ * @param result_cb called on error or success
+ * @param result_cls closure for @e result_cb
+ * @return a handle to cancel the operation
+ */
+struct GNUNET_SETI_OperationHandle *
+GNUNET_SETI_prepare (const struct GNUNET_PeerIdentity *other_peer,
+                     const struct GNUNET_HashCode *app_id,
+                     const struct GNUNET_MessageHeader *context_msg,
+                     const struct GNUNET_SETI_Option options[],
+                     GNUNET_SETI_ResultIterator result_cb,
+                     void *result_cls)
+{
+  struct GNUNET_MQ_Envelope *mqm;
+  struct GNUNET_SETI_OperationHandle *oh;
+  struct GNUNET_SETI_EvaluateMessage *msg;
+
+  oh = GNUNET_new (struct GNUNET_SETI_OperationHandle);
+  oh->result_cb = result_cb;
+  oh->result_cls = result_cls;
+  mqm = GNUNET_MQ_msg_nested_mh (msg,
+                                 GNUNET_MESSAGE_TYPE_SETI_EVALUATE,
+                                 context_msg);
+  msg->app_id = *app_id;
+  msg->target_peer = *other_peer;
+  for (const struct GNUNET_SETI_Option *opt = options;
+       GNUNET_SETI_OPTION_END != opt->type;
+       opt++)
+  {
+    switch (opt->type)
+    {
+    case GNUNET_SETI_OPTION_RETURN_INTERSECTION:
+      msg->return_intersection = htonl (GNUNET_YES);
+      break;
+    default:
+      LOG (GNUNET_ERROR_TYPE_ERROR,
+           "Option with type %d not recognized\n",
+           (int) opt->type);
+    }
+  }
+  oh->conclude_mqm = mqm;
+  oh->request_id_addr = &msg->request_id;
+  return oh;
+}
+
+
+/**
+ * Connect to the set service in order to listen for requests.
+ *
+ * @param cls the `struct GNUNET_SETI_ListenHandle *` to connect
+ */
+static void
+listen_connect (void *cls);
+
+
+/**
+ * Check validity of request message for a listen operation
+ *
+ * @param cls the listen handle
+ * @param msg the message
+ * @return #GNUNET_OK if the message is well-formed
+ */
+static int
+check_request (void *cls,
+               const struct GNUNET_SETI_RequestMessage *msg)
+{
+  const struct GNUNET_MessageHeader *context_msg;
+
+  if (ntohs (msg->header.size) == sizeof(*msg))
+    return GNUNET_OK; /* no context message is OK */
+  context_msg = GNUNET_MQ_extract_nested_mh (msg);
+  if (NULL == context_msg)
+  {
+    /* malformed context message is NOT ok */
+    GNUNET_break_op (0);
+    return GNUNET_SYSERR;
+  }
+  return GNUNET_OK;
+}
+
+
+/**
+ * Handle request message for a listen operation
+ *
+ * @param cls the listen handle
+ * @param msg the message
+ */
+static void
+handle_request (void *cls,
+                const struct GNUNET_SETI_RequestMessage *msg)
+{
+  struct GNUNET_SETI_ListenHandle *lh = cls;
+  struct GNUNET_SETI_Request req;
+  const struct GNUNET_MessageHeader *context_msg;
+  struct GNUNET_MQ_Envelope *mqm;
+  struct GNUNET_SETI_RejectMessage *rmsg;
+
+  LOG (GNUNET_ERROR_TYPE_DEBUG,
+       "Processing incoming operation request with id %u\n",
+       ntohl (msg->accept_id));
+  /* we got another valid request => reset the backoff */
+  lh->reconnect_backoff = GNUNET_TIME_UNIT_MILLISECONDS;
+  req.accept_id = ntohl (msg->accept_id);
+  req.accepted = GNUNET_NO;
+  context_msg = GNUNET_MQ_extract_nested_mh (msg);
+  /* calling #GNUNET_SETI_accept() in the listen cb will set req->accepted */
+  lh->listen_cb (lh->listen_cls,
+                 &msg->peer_id,
+                 context_msg,
+                 &req);
+  if (GNUNET_YES == req.accepted)
+    return; /* the accept-case is handled in #GNUNET_SETI_accept() */
+  LOG (GNUNET_ERROR_TYPE_DEBUG,
+       "Rejected request %u\n",
+       ntohl (msg->accept_id));
+  mqm = GNUNET_MQ_msg (rmsg,
+                       GNUNET_MESSAGE_TYPE_SETI_REJECT);
+  rmsg->accept_reject_id = msg->accept_id;
+  GNUNET_MQ_send (lh->mq,
+                  mqm);
+}
+
+
+/**
+ * Our connection with the set service encountered an error,
+ * re-initialize with exponential back-off.
+ *
+ * @param cls the `struct GNUNET_SETI_ListenHandle *`
+ * @param error reason for the disconnect
+ */
+static void
+handle_client_listener_error (void *cls,
+                              enum GNUNET_MQ_Error error)
+{
+  struct GNUNET_SETI_ListenHandle *lh = cls;
+
+  LOG (GNUNET_ERROR_TYPE_DEBUG,
+       "Listener broke down (%d), re-connecting\n",
+       (int) error);
+  GNUNET_MQ_destroy (lh->mq);
+  lh->mq = NULL;
+  lh->reconnect_task = GNUNET_SCHEDULER_add_delayed (lh->reconnect_backoff,
+                                                     &listen_connect,
+                                                     lh);
+  lh->reconnect_backoff = GNUNET_TIME_STD_BACKOFF (lh->reconnect_backoff);
+}
+
+
+/**
+ * Connect to the set service in order to listen for requests.
+ *
+ * @param cls the `struct GNUNET_SETI_ListenHandle *` to connect
+ */
+static void
+listen_connect (void *cls)
+{
+  struct GNUNET_SETI_ListenHandle *lh = cls;
+  struct GNUNET_MQ_MessageHandler mq_handlers[] = {
+    GNUNET_MQ_hd_var_size (request,
+                           GNUNET_MESSAGE_TYPE_SETI_REQUEST,
+                           struct GNUNET_SETI_RequestMessage,
+                           lh),
+    GNUNET_MQ_handler_end ()
+  };
+  struct GNUNET_MQ_Envelope *mqm;
+  struct GNUNET_SETI_ListenMessage *msg;
+
+  lh->reconnect_task = NULL;
+  GNUNET_assert (NULL == lh->mq);
+  lh->mq = GNUNET_CLIENT_connect (lh->cfg,
+                                  "seti",
+                                  mq_handlers,
+                                  &handle_client_listener_error,
+                                  lh);
+  if (NULL == lh->mq)
+    return;
+  mqm = GNUNET_MQ_msg (msg, GNUNET_MESSAGE_TYPE_SETI_LISTEN);
+  msg->app_id = lh->app_id;
+  GNUNET_MQ_send (lh->mq,
+                  mqm);
+}
+
+
+/**
+ * Wait for set operation requests for the given application id
+ *
+ * @param cfg configuration to use for connecting to
+ *            the set service, needs to be valid for the lifetime of the listen handle
+ * @param app_id id of the application that handles set operation requests
+ * @param listen_cb called for each incoming request matching the operation
+ *                  and application id
+ * @param listen_cls handle for @a listen_cb
+ * @return a handle that can be used to cancel the listen operation
+ */
+struct GNUNET_SETI_ListenHandle *
+GNUNET_SETI_listen (const struct GNUNET_CONFIGURATION_Handle *cfg,
+                    const struct GNUNET_HashCode *app_id,
+                    GNUNET_SETI_ListenCallback listen_cb,
+                    void *listen_cls)
+{
+  struct GNUNET_SETI_ListenHandle *lh;
+
+  LOG (GNUNET_ERROR_TYPE_DEBUG,
+       "Starting listener for app %s\n",
+       GNUNET_h2s (app_id));
+  lh = GNUNET_new (struct GNUNET_SETI_ListenHandle);
+  lh->listen_cb = listen_cb;
+  lh->listen_cls = listen_cls;
+  lh->cfg = cfg;
+  lh->app_id = *app_id;
+  lh->reconnect_backoff = GNUNET_TIME_UNIT_MILLISECONDS;
+  listen_connect (lh);
+  if (NULL == lh->mq)
+  {
+    GNUNET_free (lh);
+    return NULL;
+  }
+  return lh;
+}
+
+
+/**
+ * Cancel the given listen operation.
+ *
+ * @param lh handle for the listen operation
+ */
+void
+GNUNET_SETI_listen_cancel (struct GNUNET_SETI_ListenHandle *lh)
+{
+  LOG (GNUNET_ERROR_TYPE_DEBUG,
+       "Canceling listener %s\n",
+       GNUNET_h2s (&lh->app_id));
+  if (NULL != lh->mq)
+  {
+    GNUNET_MQ_destroy (lh->mq);
+    lh->mq = NULL;
+  }
+  if (NULL != lh->reconnect_task)
+  {
+    GNUNET_SCHEDULER_cancel (lh->reconnect_task);
+    lh->reconnect_task = NULL;
+  }
+  GNUNET_free (lh);
+}
+
+
+/**
+ * Accept a request we got via #GNUNET_SETI_listen.  Must be called during
+ * #GNUNET_SETI_listen, as the 'struct GNUNET_SETI_Request' becomes invalid
+ * afterwards.
+ * Call #GNUNET_SETI_commit to provide the local set to use for the operation,
+ * and to begin the exchange with the remote peer.
+ *
+ * @param request request to accept
+ * @param options options to use when processing the request
+ * @param result_cb callback for the results
+ * @param result_cls closure for @a result_cb
+ * @return a handle to cancel the operation
+ */
+struct GNUNET_SETI_OperationHandle *
+GNUNET_SETI_accept (struct GNUNET_SETI_Request *request,
+                    const struct GNUNET_SETI_Option options[],
+                    GNUNET_SETI_ResultIterator result_cb,
+                    void *result_cls)
+{
+  struct GNUNET_MQ_Envelope *mqm;
+  struct GNUNET_SETI_OperationHandle *oh;
+  struct GNUNET_SETI_AcceptMessage *msg;
+
+  GNUNET_assert (GNUNET_NO == request->accepted);
+  LOG (GNUNET_ERROR_TYPE_DEBUG,
+       "Client accepts set intersection operation with id %u\n",
+       request->accept_id);
+  request->accepted = GNUNET_YES;
+  mqm = GNUNET_MQ_msg (msg,
+                       GNUNET_MESSAGE_TYPE_SETI_ACCEPT);
+  msg->accept_reject_id = htonl (request->accept_id);
+  oh = GNUNET_new (struct GNUNET_SETI_OperationHandle);
+  oh->result_cb = result_cb;
+  oh->result_cls = result_cls;
+  oh->conclude_mqm = mqm;
+  oh->request_id_addr = &msg->request_id;
+  for (const struct GNUNET_SETI_Option *opt = options;
+       GNUNET_SETI_OPTION_END != opt->type;
+       opt++)
+  {
+    switch (opt->type)
+    {
+    case GNUNET_SETI_OPTION_RETURN_INTERSECTION:
+      oh->return_intersection = GNUNET_YES;
+      msg->return_intersection = htonl (GNUNET_YES);
+      break;
+    default:
+      LOG (GNUNET_ERROR_TYPE_ERROR,
+           "Option with type %d not recognized\n",
+           (int) opt->type);
+    }
+  }
+  return oh;
+}
+
+
+/**
+ * Commit a set to be used with a set operation.
+ * This function is called once we have fully constructed
+ * the set that we want to use for the operation.  At this
+ * time, the P2P protocol can then begin to exchange the
+ * set information and call the result callback with the
+ * result information.
+ *
+ * @param oh handle to the set operation
+ * @param set the set to use for the operation
+ * @return #GNUNET_OK on success, #GNUNET_SYSERR if the
+ *         set is invalid (e.g. the set service crashed)
+ */
+int
+GNUNET_SETI_commit (struct GNUNET_SETI_OperationHandle *oh,
+                    struct GNUNET_SETI_Handle *set)
+{
+  if (NULL != oh->set)
+  {
+    /* Some other set was already committed for this
+     * operation, there is a logic bug in the client of this API */
+    GNUNET_break (0);
+    return GNUNET_OK;
+  }
+  GNUNET_assert (NULL != set);
+  if (GNUNET_YES == set->invalid)
+    return GNUNET_SYSERR;
+  LOG (GNUNET_ERROR_TYPE_DEBUG,
+       "Client commits to SET\n");
+  GNUNET_assert (NULL != oh->conclude_mqm);
+  oh->set = set;
+  GNUNET_CONTAINER_DLL_insert (set->ops_head,
+                               set->ops_tail,
+                               oh);
+  oh->request_id = GNUNET_MQ_assoc_add (set->mq,
+                                        oh);
+  *oh->request_id_addr = htonl (oh->request_id);
+  GNUNET_MQ_send (set->mq,
+                  oh->conclude_mqm);
+  oh->conclude_mqm = NULL;
+  oh->request_id_addr = NULL;
+  return GNUNET_OK;
+}
+
+
+/**
+ * Hash a set element.
+ *
+ * @param element the element that should be hashed
+ * @param[out] ret_hash a pointer to where the hash of @a element
+ *        should be stored
+ */
+void
+GNUNET_SETI_element_hash (const struct GNUNET_SETI_Element *element,
+                          struct GNUNET_HashCode *ret_hash)
+{
+  struct GNUNET_HashContext *ctx = GNUNET_CRYPTO_hash_context_start ();
+
+  /* It's not guaranteed that the element data is always after the element header,
+     so we need to hash the chunks separately. */
+  GNUNET_CRYPTO_hash_context_read (ctx,
+                                   &element->size,
+                                   sizeof(uint16_t));
+  GNUNET_CRYPTO_hash_context_read (ctx,
+                                   &element->element_type,
+                                   sizeof(uint16_t));
+  GNUNET_CRYPTO_hash_context_read (ctx,
+                                   element->data,
+                                   element->size);
+  GNUNET_CRYPTO_hash_context_finish (ctx,
+                                     ret_hash);
+}
+
+
+/* end of seti_api.c */
diff --git a/src/seti/test_seti.conf b/src/seti/test_seti.conf
new file mode 100644
index 0000000000000000000000000000000000000000..c8743341926115e62f112a0fb17c6d189b78b51f
--- /dev/null
+++ b/src/seti/test_seti.conf
@@ -0,0 +1,32 @@
+@INLINE@ ../../contrib/conf/gnunet/no_forcestart.conf
+
+[PATHS]
+GNUNET_TEST_HOME = $GNUNET_TMP/test-gnunet-set/
+
+[seti]
+START_ON_DEMAND = YES
+#PREFIX = valgrind --leak-check=full
+#PREFIX = gdbserver :1234
+OPTIONS = -L INFO
+
+[transport]
+PLUGINS = unix
+OPTIONS = -LERROR
+
+[nat]
+RETURN_LOCAL_ADDRESSES = YES
+DISABLEV6 = YES
+USE_LOCALADDR = YES
+
+[peerinfo]
+NO_IO = YES
+
+[nat]
+# Use addresses from the local network interfaces (inluding loopback, but also others)
+USE_LOCALADDR = YES
+
+# Disable IPv6 support
+DISABLEV6 = NO
+
+# Do we use addresses from localhost address ranges? (::1, 127.0.0.0/8)
+RETURN_LOCAL_ADDRESSES = YES
diff --git a/src/seti/test_seti_api.c b/src/seti/test_seti_api.c
new file mode 100644
index 0000000000000000000000000000000000000000..9074fab4187e8c1e74b38fa5cfb90ee7a6ef186b
--- /dev/null
+++ b/src/seti/test_seti_api.c
@@ -0,0 +1,345 @@
+/*
+     This file is part of GNUnet.
+     Copyright (C) 2012-2014, 2020 GNUnet e.V.
+
+     GNUnet is free software: you can redistribute it and/or modify it
+     under the terms of the GNU Affero General Public License as published
+     by the Free Software Foundation, either version 3 of the License,
+     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
+     Affero General Public License for more details.
+
+     You should have received a copy of the GNU Affero General Public License
+     along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+     SPDX-License-Identifier: AGPL3.0-or-later
+ */
+
+/**
+ * @file set/test_seti_api.c
+ * @brief testcase for full result mode of the intersection set operation
+ * @author Christian Fuchs
+ * @author Christian Grothoff
+ */
+#include "platform.h"
+#include "gnunet_util_lib.h"
+#include "gnunet_testing_lib.h"
+#include "gnunet_seti_service.h"
+
+
+static int ret;
+
+static struct GNUNET_PeerIdentity local_id;
+
+static struct GNUNET_HashCode app_id;
+
+static struct GNUNET_SETI_Handle *set1;
+
+static struct GNUNET_SETI_Handle *set2;
+
+static struct GNUNET_SETI_ListenHandle *listen_handle;
+
+static const struct GNUNET_CONFIGURATION_Handle *config;
+
+static struct GNUNET_SCHEDULER_Task *tt;
+
+static struct GNUNET_SETI_OperationHandle *oh1;
+
+static struct GNUNET_SETI_OperationHandle *oh2;
+
+
+static void
+result_cb_set1 (void *cls,
+                const struct GNUNET_SETI_Element *element,
+                uint64_t current_size,
+                enum GNUNET_SETI_Status status)
+{
+  static int count;
+
+  GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+              "Processing result set 1 (%d)\n",
+              status);
+  switch (status)
+  {
+  case GNUNET_SETI_STATUS_ADD_LOCAL:
+    count++;
+    break;
+  case GNUNET_SETI_STATUS_FAILURE:
+    oh1 = NULL;
+    ret = 1;
+    break;
+  case GNUNET_SETI_STATUS_DONE:
+    oh1 = NULL;
+    GNUNET_assert (1 == count);
+    GNUNET_SETI_destroy (set1);
+    set1 = NULL;
+    if (NULL == set2)
+      GNUNET_SCHEDULER_shutdown ();
+    break;
+
+  default:
+    GNUNET_assert (0);
+  }
+}
+
+
+static void
+result_cb_set2 (void *cls,
+                const struct GNUNET_SETI_Element *element,
+                uint64_t current_size,
+                enum GNUNET_SETI_Status status)
+{
+  static int count;
+
+  GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+              "Processing result set 2 (%d)\n",
+              status);
+  switch (status)
+  {
+  case GNUNET_SETI_STATUS_ADD_LOCAL:
+    count++;
+    break;
+  case GNUNET_SETI_STATUS_FAILURE:
+    oh2 = NULL;
+    ret = 1;
+    break;
+  case GNUNET_SETI_STATUS_DONE:
+    oh2 = NULL;
+    GNUNET_break (1 == count);
+    if (1 != count)
+      ret |= 2;
+    GNUNET_SETI_destroy (set2);
+    set2 = NULL;
+    if (NULL == set1)
+      GNUNET_SCHEDULER_shutdown ();
+    break;
+  case GNUNET_SETI_STATUS_DEL_LOCAL:
+    /* unexpected! */
+    ret = 1;
+    break;
+  }
+}
+
+
+static void
+listen_cb (void *cls,
+           const struct GNUNET_PeerIdentity *other_peer,
+           const struct GNUNET_MessageHeader *context_msg,
+           struct GNUNET_SETI_Request *request)
+{
+  struct GNUNET_SETI_Option opts[] = {
+    { .type = GNUNET_SETI_OPTION_RETURN_INTERSECTION },
+    { .type = GNUNET_SETI_OPTION_END }
+  };
+
+  GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+              "starting intersection by accepting and committing\n");
+  GNUNET_assert (NULL != context_msg);
+  GNUNET_assert (ntohs (context_msg->type) == GNUNET_MESSAGE_TYPE_DUMMY);
+  oh2 = GNUNET_SETI_accept (request,
+                            opts,
+                            &result_cb_set2,
+                            NULL);
+  GNUNET_SETI_commit (oh2,
+                      set2);
+}
+
+
+/**
+ * Start the set operation.
+ *
+ * @param cls closure, unused
+ */
+static void
+start (void *cls)
+{
+  struct GNUNET_MessageHeader context_msg;
+  struct GNUNET_SETI_Option opts[] = {
+    { .type = GNUNET_SETI_OPTION_RETURN_INTERSECTION },
+    { .type = GNUNET_SETI_OPTION_END }
+  };
+
+  GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+              "starting listener\n");
+  context_msg.size = htons (sizeof (context_msg));
+  context_msg.type = htons (GNUNET_MESSAGE_TYPE_DUMMY);
+  listen_handle = GNUNET_SETI_listen (config,
+                                      &app_id,
+                                      &listen_cb,
+                                      NULL);
+  oh1 = GNUNET_SETI_prepare (&local_id,
+                             &app_id,
+                             &context_msg,
+                             opts,
+                             &result_cb_set1,
+                             NULL);
+  GNUNET_SETI_commit (oh1,
+                      set1);
+}
+
+
+/**
+ * Initialize the second set, continue
+ *
+ * @param cls closure, unused
+ */
+static void
+init_set2 (void *cls)
+{
+  struct GNUNET_SETI_Element element;
+
+  GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+              "initializing set 2\n");
+  element.element_type = 0;
+  element.data = "hello";
+  element.size = strlen (element.data);
+  GNUNET_SETI_add_element (set2,
+                           &element,
+                           NULL,
+                           NULL);
+  element.data = "quux";
+  element.size = strlen (element.data);
+  GNUNET_SETI_add_element (set2,
+                           &element,
+                           NULL,
+                           NULL);
+  element.data = "baz";
+  element.size = strlen (element.data);
+  GNUNET_SETI_add_element (set2,
+                           &element,
+                           &start,
+                           NULL);
+}
+
+
+/**
+ * Initialize the first set, continue.
+ */
+static void
+init_set1 (void)
+{
+  struct GNUNET_SETI_Element element;
+
+  GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+              "initializing set 1\n");
+  element.element_type = 0;
+  element.data = "hello";
+  element.size = strlen (element.data);
+  GNUNET_SETI_add_element (set1,
+                           &element,
+                           NULL,
+                           NULL);
+  element.data = "bar";
+  element.size = strlen (element.data);
+  GNUNET_SETI_add_element (set1,
+                           &element,
+                           &init_set2,
+                           NULL);
+}
+
+
+/**
+ * Function run on shutdown.
+ *
+ * @param cls closure
+ */
+static void
+do_shutdown (void *cls)
+{
+  if (NULL != tt)
+  {
+    GNUNET_SCHEDULER_cancel (tt);
+    tt = NULL;
+  }
+  if (NULL != oh1)
+  {
+    GNUNET_SETI_operation_cancel (oh1);
+    oh1 = NULL;
+  }
+  if (NULL != oh2)
+  {
+    GNUNET_SETI_operation_cancel (oh2);
+    oh2 = NULL;
+  }
+  if (NULL != set1)
+  {
+    GNUNET_SETI_destroy (set1);
+    set1 = NULL;
+  }
+  if (NULL != set2)
+  {
+    GNUNET_SETI_destroy (set2);
+    set2 = NULL;
+  }
+  if (NULL != listen_handle)
+  {
+    GNUNET_SETI_listen_cancel (listen_handle);
+    listen_handle = NULL;
+  }
+}
+
+
+/**
+ * Function run on timeout.
+ *
+ * @param cls closure
+ */
+static void
+timeout_fail (void *cls)
+{
+  tt = NULL;
+  GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
+              "Testcase failed with timeout\n");
+  GNUNET_SCHEDULER_shutdown ();
+  ret = 1;
+}
+
+
+/**
+ * Signature of the 'main' function for a (single-peer) testcase that
+ * is run using 'GNUNET_TESTING_peer_run'.
+ *
+ * @param cls closure
+ * @param cfg configuration of the peer that was started
+ * @param peer identity of the peer that was created
+ */
+static void
+run (void *cls,
+     const struct GNUNET_CONFIGURATION_Handle *cfg,
+     struct GNUNET_TESTING_Peer *peer)
+{
+  config = cfg;
+  GNUNET_TESTING_peer_get_identity (peer,
+                                    &local_id);
+  tt = GNUNET_SCHEDULER_add_delayed (
+    GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS,
+                                   5),
+    &timeout_fail,
+    NULL);
+  GNUNET_SCHEDULER_add_shutdown (&do_shutdown,
+                                 NULL);
+
+  set1 = GNUNET_SETI_create (cfg);
+  set2 = GNUNET_SETI_create (cfg);
+  GNUNET_CRYPTO_hash_create_random (GNUNET_CRYPTO_QUALITY_WEAK,
+                                    &app_id);
+
+  /* test the real set reconciliation */
+  init_set1 ();
+}
+
+
+int
+main (int argc,
+      char **argv)
+{
+  if (0 != GNUNET_TESTING_peer_run ("test_seti_api",
+                                    "test_seti.conf",
+                                    &run,
+                                    NULL))
+    return 1;
+  return ret;
+}
diff --git a/src/setu/.gitignore b/src/setu/.gitignore
new file mode 100644
index 0000000000000000000000000000000000000000..35295449b1e4de1d29baab31f057db5a037cbdf7
--- /dev/null
+++ b/src/setu/.gitignore
@@ -0,0 +1,6 @@
+gnunet-setu-profiler
+gnunet-service-setu
+gnunet-setu-ibf-profiler
+test_setu_api
+test_setu_copy
+test_setu_result_symmetric
diff --git a/src/setu/Makefile.am b/src/setu/Makefile.am
new file mode 100644
index 0000000000000000000000000000000000000000..cc77114625e8a1059e0d9bdb282316d14bfac568
--- /dev/null
+++ b/src/setu/Makefile.am
@@ -0,0 +1,102 @@
+# This Makefile.am is in the public domain
+AM_CPPFLAGS = -I$(top_srcdir)/src/include
+
+pkgcfgdir= $(pkgdatadir)/config.d/
+
+libexecdir= $(pkglibdir)/libexec/
+
+plugindir = $(libdir)/gnunet
+
+pkgcfg_DATA = \
+  setu.conf
+
+if USE_COVERAGE
+  AM_CFLAGS = -fprofile-arcs -ftest-coverage
+endif
+
+if HAVE_TESTING
+bin_PROGRAMS = \
+ gnunet-setu-profiler
+
+noinst_PROGRAMS = \
+ gnunet-setu-ibf-profiler
+endif
+
+libexec_PROGRAMS = \
+ gnunet-service-setu
+
+lib_LTLIBRARIES = \
+  libgnunetsetu.la
+
+gnunet_setu_profiler_SOURCES = \
+ gnunet-setu-profiler.c
+gnunet_setu_profiler_LDADD = \
+  $(top_builddir)/src/util/libgnunetutil.la \
+  $(top_builddir)/src/statistics/libgnunetstatistics.la \
+  libgnunetsetu.la \
+  $(top_builddir)/src/testing/libgnunettesting.la \
+  $(GN_LIBINTL)
+
+
+gnunet_setu_ibf_profiler_SOURCES = \
+ gnunet-setu-ibf-profiler.c \
+ ibf.c
+gnunet_setu_ibf_profiler_LDADD = \
+  $(top_builddir)/src/util/libgnunetutil.la \
+  $(GN_LIBINTL)
+
+gnunet_service_setu_SOURCES = \
+ gnunet-service-setu.c gnunet-service-setu_protocol.h \
+ ibf.c ibf.h \
+ gnunet-service-setu_strata_estimator.c gnunet-service-setu_strata_estimator.h \
+ gnunet-service-setu_protocol.h
+gnunet_service_setu_LDADD = \
+  $(top_builddir)/src/util/libgnunetutil.la \
+  $(top_builddir)/src/statistics/libgnunetstatistics.la \
+  $(top_builddir)/src/core/libgnunetcore.la \
+  $(top_builddir)/src/cadet/libgnunetcadet.la \
+  $(top_builddir)/src/block/libgnunetblock.la \
+  libgnunetsetu.la \
+  $(GN_LIBINTL)
+
+libgnunetsetu_la_SOURCES = \
+  setu_api.c setu.h
+libgnunetsetu_la_LIBADD = \
+  $(top_builddir)/src/util/libgnunetutil.la \
+  $(LTLIBINTL)
+libgnunetsetu_la_LDFLAGS = \
+  $(GN_LIB_LDFLAGS)
+
+if HAVE_TESTING
+check_PROGRAMS = \
+ test_setu_api
+endif
+
+if ENABLE_TEST_RUN
+AM_TESTS_ENVIRONMENT=export GNUNET_PREFIX=$${GNUNET_PREFIX:-@libdir@};export PATH=$${GNUNET_PREFIX:-@prefix@}/bin:$$PATH;unset XDG_DATA_HOME;unset XDG_CONFIG_HOME;
+TESTS = $(check_PROGRAMS)
+endif
+
+test_setu_api_SOURCES = \
+ test_setu_api.c
+test_setu_api_LDADD = \
+  $(top_builddir)/src/util/libgnunetutil.la \
+  $(top_builddir)/src/testing/libgnunettesting.la \
+  libgnunetsetu.la
+
+plugin_LTLIBRARIES = \
+  libgnunet_plugin_block_setu_test.la
+
+libgnunet_plugin_block_setu_test_la_SOURCES = \
+  plugin_block_setu_test.c
+libgnunet_plugin_block_setu_test_la_LIBADD = \
+  $(top_builddir)/src/block/libgnunetblock.la \
+  $(top_builddir)/src/block/libgnunetblockgroup.la \
+  $(top_builddir)/src/util/libgnunetutil.la \
+  $(LTLIBINTL)
+libgnunet_plugin_block_setu_test_la_LDFLAGS = \
+ $(GN_PLUGIN_LDFLAGS)
+
+
+EXTRA_DIST = \
+  test_setu.conf
diff --git a/src/setu/gnunet-service-setu.c b/src/setu/gnunet-service-setu.c
new file mode 100644
index 0000000000000000000000000000000000000000..326589186f6e8dc436af93a210253677527e3d67
--- /dev/null
+++ b/src/setu/gnunet-service-setu.c
@@ -0,0 +1,3683 @@
+/*
+      This file is part of GNUnet
+      Copyright (C) 2013-2017, 2020 GNUnet e.V.
+
+      GNUnet is free software: you can redistribute it and/or modify it
+      under the terms of the GNU Affero General Public License as published
+      by the Free Software Foundation, either version 3 of the License,
+      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
+      Affero General Public License for more details.
+
+      You should have received a copy of the GNU Affero General Public License
+      along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+     SPDX-License-Identifier: AGPL3.0-or-later
+ */
+/**
+ * @file setu/gnunet-service-setu.c
+ * @brief set union operation
+ * @author Florian Dold
+ * @author Christian Grothoff
+ */
+#include "platform.h"
+#include "gnunet_util_lib.h"
+#include "gnunet_statistics_service.h"
+#include "ibf.h"
+#include "gnunet_protocols.h"
+#include "gnunet_applications.h"
+#include "gnunet_cadet_service.h"
+#include "gnunet-service-setu_strata_estimator.h"
+#include "gnunet-service-setu_protocol.h"
+#include "gnunet_statistics_service.h"
+#include <gcrypt.h>
+#include "gnunet_setu_service.h"
+#include "setu.h"
+
+#define LOG(kind, ...) GNUNET_log_from (kind, "setu", __VA_ARGS__)
+
+/**
+ * How long do we hold on to an incoming channel if there is
+ * no local listener before giving up?
+ */
+#define INCOMING_CHANNEL_TIMEOUT GNUNET_TIME_UNIT_MINUTES
+
+/**
+ * Number of IBFs in a strata estimator.
+ */
+#define SE_STRATA_COUNT 32
+
+/**
+ * Size of the IBFs in the strata estimator.
+ */
+#define SE_IBF_SIZE 80
+
+/**
+ * The hash num parameter for the difference digests and strata estimators.
+ */
+#define SE_IBF_HASH_NUM 4
+
+/**
+ * Number of buckets that can be transmitted in one message.
+ */
+#define MAX_BUCKETS_PER_MESSAGE ((1 << 15) / IBF_BUCKET_SIZE)
+
+/**
+ * The maximum size of an ibf we use is 2^(MAX_IBF_ORDER).
+ * Choose this value so that computing the IBF is still cheaper
+ * than transmitting all values.
+ */
+#define MAX_IBF_ORDER (20)
+
+/**
+ * Number of buckets used in the ibf per estimated
+ * difference.
+ */
+#define IBF_ALPHA 4
+
+
+/**
+ * Current phase we are in for a union operation.
+ */
+enum UnionOperationPhase
+{
+  /**
+   * We sent the request message, and expect a strata estimator.
+   */
+  PHASE_EXPECT_SE,
+
+  /**
+   * We sent the strata estimator, and expect an IBF. This phase is entered once
+   * upon initialization and later via #PHASE_EXPECT_ELEMENTS_AND_REQUESTS.
+   *
+   * XXX: could use better wording.
+   * XXX: repurposed to also expect a "request full set" message, should be renamed
+   *
+   * After receiving the complete IBF, we enter #PHASE_EXPECT_ELEMENTS
+   */
+  PHASE_EXPECT_IBF,
+
+  /**
+   * Continuation for multi part IBFs.
+   */
+  PHASE_EXPECT_IBF_CONT,
+
+  /**
+   * We are decoding an IBF.
+   */
+  PHASE_INVENTORY_ACTIVE,
+
+  /**
+   * The other peer is decoding the IBF we just sent.
+   */
+  PHASE_INVENTORY_PASSIVE,
+
+  /**
+   * The protocol is almost finished, but we still have to flush our message
+   * queue and/or expect some elements.
+   */
+  PHASE_FINISH_CLOSING,
+
+  /**
+   * In the penultimate phase, we wait until all our demands are satisfied.
+   * Then we send a done message, and wait for another done message.
+   */
+  PHASE_FINISH_WAITING,
+
+  /**
+   * In the ultimate phase, we wait until our demands are satisfied and then
+   * quit (sending another DONE message).
+   */
+  PHASE_DONE,
+
+  /**
+   * After sending the full set, wait for responses with the elements
+   * that the local peer is missing.
+   */
+  PHASE_FULL_SENDING,
+};
+
+
+/**
+ * Information about an element element in the set.  All elements are
+ * stored in a hash-table from their hash-code to their `struct
+ * Element`, so that the remove and add operations are reasonably
+ * fast.
+ */
+struct ElementEntry
+{
+  /**
+   * The actual element. The data for the element
+   * should be allocated at the end of this struct.
+   */
+  struct GNUNET_SETU_Element element;
+
+  /**
+   * Hash of the element.  For set union: Will be used to derive the
+   * different IBF keys for different salts.
+   */
+  struct GNUNET_HashCode element_hash;
+
+  /**
+   * First generation that includes this element.
+   */
+  unsigned int generation;
+
+  /**
+   * #GNUNET_YES if the element is a remote element, and does not belong
+   * to the operation's set.
+   */
+  int remote;
+};
+
+
+/**
+ * A listener is inhabited by a client, and waits for evaluation
+ * requests from remote peers.
+ */
+struct Listener;
+
+
+/**
+ * A set that supports a specific operation with other peers.
+ */
+struct Set;
+
+
+/**
+ * State we keep per client.
+ */
+struct ClientState
+{
+  /**
+   * Set, if associated with the client, otherwise NULL.
+   */
+  struct Set *set;
+
+  /**
+   * Listener, if associated with the client, otherwise NULL.
+   */
+  struct Listener *listener;
+
+  /**
+   * Client handle.
+   */
+  struct GNUNET_SERVICE_Client *client;
+
+  /**
+   * Message queue.
+   */
+  struct GNUNET_MQ_Handle *mq;
+};
+
+
+/**
+ * Operation context used to execute a set operation.
+ */
+struct Operation
+{
+
+  /**
+   * The identity of the requesting peer.  Needs to
+   * be stored here as the op spec might not have been created yet.
+   */
+  struct GNUNET_PeerIdentity peer;
+
+  /**
+   * Initial size of our set, just before the operation started.
+   */
+  uint64_t initial_size;
+
+  /**
+   * Kept in a DLL of the listener, if @e listener is non-NULL.
+   */
+  struct Operation *next;
+
+  /**
+   * Kept in a DLL of the listener, if @e listener is non-NULL.
+   */
+  struct Operation *prev;
+
+  /**
+   * Channel to the peer.
+   */
+  struct GNUNET_CADET_Channel *channel;
+
+  /**
+   * Port this operation runs on.
+   */
+  struct Listener *listener;
+
+  /**
+   * Message queue for the channel.
+   */
+  struct GNUNET_MQ_Handle *mq;
+
+  /**
+   * Context message, may be NULL.
+   */
+  struct GNUNET_MessageHeader *context_msg;
+
+  /**
+   * Set associated with the operation, NULL until the spec has been
+   * associated with a set.
+   */
+  struct Set *set;
+
+  /**
+   * Copy of the set's strata estimator at the time of
+   * creation of this operation.
+   */
+  struct StrataEstimator *se;
+
+  /**
+   * The IBF we currently receive.
+   */
+  struct InvertibleBloomFilter *remote_ibf;
+
+  /**
+   * The IBF with the local set's element.
+   */
+  struct InvertibleBloomFilter *local_ibf;
+
+  /**
+   * Maps unsalted IBF-Keys to elements.
+   * Used as a multihashmap, the keys being the lower 32bit of the IBF-Key.
+   * Colliding IBF-Keys are linked.
+   */
+  struct GNUNET_CONTAINER_MultiHashMap32 *key_to_element;
+
+  /**
+   * Timeout task, if the incoming peer has not been accepted
+   * after the timeout, it will be disconnected.
+   */
+  struct GNUNET_SCHEDULER_Task *timeout_task;
+
+  /**
+   * Hashes for elements that we have demanded from the other peer.
+   */
+  struct GNUNET_CONTAINER_MultiHashMap *demanded_hashes;
+
+  /**
+   * Current state of the operation.
+   */
+  enum UnionOperationPhase phase;
+
+  /**
+   * Did we send the client that we are done?
+   */
+  int client_done_sent;
+
+  /**
+   * Number of ibf buckets already received into the @a remote_ibf.
+   */
+  unsigned int ibf_buckets_received;
+
+  /**
+   * Salt that we're using for sending IBFs
+   */
+  uint32_t salt_send;
+
+  /**
+   * Salt for the IBF we've received and that we're currently decoding.
+   */
+  uint32_t salt_receive;
+
+  /**
+   * Number of elements we received from the other peer
+   * that were not in the local set yet.
+   */
+  uint32_t received_fresh;
+
+  /**
+   * Total number of elements received from the other peer.
+   */
+  uint32_t received_total;
+
+  /**
+   * Salt to use for the operation.
+   */
+  uint32_t salt;
+
+  /**
+   * Remote peers element count
+   */
+  uint32_t remote_element_count;
+
+  /**
+   * ID used to identify an operation between service and client
+   */
+  uint32_t client_request_id;
+
+  /**
+   * Always use delta operation instead of sending full sets,
+   * even it it's less efficient.
+   */
+  int force_delta;
+
+  /**
+   * Always send full sets, even if delta operations would
+   * be more efficient.
+   */
+  int force_full;
+
+  /**
+   * #GNUNET_YES to fail operations where Byzantine faults
+   * are suspected
+   */
+  int byzantine;
+
+  /**
+   * #GNUNET_YES to also send back set elements we are sending to
+   * the remote peer.
+   */
+  int symmetric;
+
+  /**
+   * Lower bound for the set size, used only when
+   * byzantine mode is enabled.
+   */
+  int byzantine_lower_bound;
+
+  /**
+   * Unique request id for the request from a remote peer, sent to the
+   * client, which will accept or reject the request.  Set to '0' iff
+   * the request has not been suggested yet.
+   */
+  uint32_t suggest_id;
+
+  /**
+   * Generation in which the operation handle
+   * was created.
+   */
+  unsigned int generation_created;
+};
+
+
+/**
+ * SetContent stores the actual set elements, which may be shared by
+ * multiple generations derived from one set.
+ */
+struct SetContent
+{
+  /**
+   * Maps `struct GNUNET_HashCode *` to `struct ElementEntry *`.
+   */
+  struct GNUNET_CONTAINER_MultiHashMap *elements;
+
+  /**
+   * Number of references to the content.
+   */
+  unsigned int refcount;
+
+  /**
+   * FIXME: document!
+   */
+  unsigned int latest_generation;
+
+  /**
+   * Number of concurrently active iterators.
+   */
+  int iterator_count;
+};
+
+
+/**
+ * A set that supports a specific operation with other peers.
+ */
+struct Set
+{
+  /**
+   * Sets are held in a doubly linked list (in `sets_head` and `sets_tail`).
+   */
+  struct Set *next;
+
+  /**
+   * Sets are held in a doubly linked list.
+   */
+  struct Set *prev;
+
+  /**
+   * Client that owns the set.  Only one client may own a set,
+   * and there can only be one set per client.
+   */
+  struct ClientState *cs;
+
+  /**
+   * Content, possibly shared by multiple sets,
+   * and thus reference counted.
+   */
+  struct SetContent *content;
+
+  /**
+   * The strata estimator is only generated once for each set.  The IBF keys
+   * are derived from the element hashes with salt=0.
+   */
+  struct StrataEstimator *se;
+
+  /**
+   * Evaluate operations are held in a linked list.
+   */
+  struct Operation *ops_head;
+
+  /**
+   * Evaluate operations are held in a linked list.
+   */
+  struct Operation *ops_tail;
+
+  /**
+   * Current generation, that is, number of previously executed
+   * operations and lazy copies on the underlying set content.
+   */
+  unsigned int current_generation;
+
+};
+
+
+/**
+ * The key entry is used to associate an ibf key with an element.
+ */
+struct KeyEntry
+{
+  /**
+   * IBF key for the entry, derived from the current salt.
+   */
+  struct IBF_Key ibf_key;
+
+  /**
+   * The actual element associated with the key.
+   *
+   * Only owned by the union operation if element->operation
+   * is #GNUNET_YES.
+   */
+  struct ElementEntry *element;
+
+  /**
+   * Did we receive this element?  Even if element->is_foreign is false, we
+   * might have received the element, so this indicates that the other peer
+   * has it.
+   */
+  int received;
+};
+
+
+/**
+ * Used as a closure for sending elements
+ * with a specific IBF key.
+ */
+struct SendElementClosure
+{
+  /**
+   * The IBF key whose matching elements should be
+   * sent.
+   */
+  struct IBF_Key ibf_key;
+
+  /**
+   * Operation for which the elements
+   * should be sent.
+   */
+  struct Operation *op;
+};
+
+
+/**
+ * A listener is inhabited by a client, and waits for evaluation
+ * requests from remote peers.
+ */
+struct Listener
+{
+  /**
+   * Listeners are held in a doubly linked list.
+   */
+  struct Listener *next;
+
+  /**
+   * Listeners are held in a doubly linked list.
+   */
+  struct Listener *prev;
+
+  /**
+   * Head of DLL of operations this listener is responsible for.
+   * Once the client has accepted/declined the operation, the
+   * operation is moved to the respective set's operation DLLS.
+   */
+  struct Operation *op_head;
+
+  /**
+   * Tail of DLL of operations this listener is responsible for.
+   * Once the client has accepted/declined the operation, the
+   * operation is moved to the respective set's operation DLLS.
+   */
+  struct Operation *op_tail;
+
+  /**
+   * Client that owns the listener.
+   * Only one client may own a listener.
+   */
+  struct ClientState *cs;
+
+  /**
+   * The port we are listening on with CADET.
+   */
+  struct GNUNET_CADET_Port *open_port;
+
+  /**
+   * Application ID for the operation, used to distinguish
+   * multiple operations of the same type with the same peer.
+   */
+  struct GNUNET_HashCode app_id;
+
+};
+
+
+/**
+ * Handle to the cadet service, used to listen for and connect to
+ * remote peers.
+ */
+static struct GNUNET_CADET_Handle *cadet;
+
+/**
+ * Statistics handle.
+ */
+static struct GNUNET_STATISTICS_Handle *_GSS_statistics;
+
+/**
+ * Listeners are held in a doubly linked list.
+ */
+static struct Listener *listener_head;
+
+/**
+ * Listeners are held in a doubly linked list.
+ */
+static struct Listener *listener_tail;
+
+/**
+ * Number of active clients.
+ */
+static unsigned int num_clients;
+
+/**
+ * Are we in shutdown? if #GNUNET_YES and the number of clients
+ * drops to zero, disconnect from CADET.
+ */
+static int in_shutdown;
+
+/**
+ * Counter for allocating unique IDs for clients, used to identify incoming
+ * operation requests from remote peers, that the client can choose to accept
+ * or refuse.  0 must not be used (reserved for uninitialized).
+ */
+static uint32_t suggest_id;
+
+
+/**
+ * Iterator over hash map entries, called to
+ * destroy the linked list of colliding ibf key entries.
+ *
+ * @param cls closure
+ * @param key current key code
+ * @param value value in the hash map
+ * @return #GNUNET_YES if we should continue to iterate,
+ *         #GNUNET_NO if not.
+ */
+static int
+destroy_key_to_element_iter (void *cls,
+                             uint32_t key,
+                             void *value)
+{
+  struct KeyEntry *k = value;
+
+  GNUNET_assert (NULL != k);
+  if (GNUNET_YES == k->element->remote)
+  {
+    GNUNET_free (k->element);
+    k->element = NULL;
+  }
+  GNUNET_free (k);
+  return GNUNET_YES;
+}
+
+
+/**
+ * Signal to the client that the operation has finished and
+ * destroy the operation.
+ *
+ * @param cls operation to destroy
+ */
+static void
+send_client_done (void *cls)
+{
+  struct Operation *op = cls;
+  struct GNUNET_MQ_Envelope *ev;
+  struct GNUNET_SETU_ResultMessage *rm;
+
+  if (GNUNET_YES == op->client_done_sent)
+    return;
+  if (PHASE_DONE != op->phase)
+  {
+    LOG (GNUNET_ERROR_TYPE_WARNING,
+         "Union operation failed\n");
+    GNUNET_STATISTICS_update (_GSS_statistics,
+                              "# Union operations failed",
+                              1,
+                              GNUNET_NO);
+    ev = GNUNET_MQ_msg (rm, GNUNET_MESSAGE_TYPE_SETU_RESULT);
+    rm->result_status = htons (GNUNET_SETU_STATUS_FAILURE);
+    rm->request_id = htonl (op->client_request_id);
+    rm->element_type = htons (0);
+    GNUNET_MQ_send (op->set->cs->mq,
+                    ev);
+    return;
+  }
+
+  op->client_done_sent = GNUNET_YES;
+
+  GNUNET_STATISTICS_update (_GSS_statistics,
+                            "# Union operations succeeded",
+                            1,
+                            GNUNET_NO);
+  LOG (GNUNET_ERROR_TYPE_INFO,
+       "Signalling client that union operation is done\n");
+  ev = GNUNET_MQ_msg (rm,
+                      GNUNET_MESSAGE_TYPE_SETU_RESULT);
+  rm->request_id = htonl (op->client_request_id);
+  rm->result_status = htons (GNUNET_SETU_STATUS_DONE);
+  rm->element_type = htons (0);
+  rm->current_size = GNUNET_htonll (GNUNET_CONTAINER_multihashmap32_size (
+                                      op->key_to_element));
+  GNUNET_MQ_send (op->set->cs->mq,
+                  ev);
+}
+
+
+/* FIXME: the destroy logic is a mess and should be cleaned up! */
+
+/**
+ * Destroy the given operation.  Used for any operation where both
+ * peers were known and that thus actually had a vt and channel.  Must
+ * not be used for operations where 'listener' is still set and we do
+ * not know the other peer.
+ *
+ * Call the implementation-specific cancel function of the operation.
+ * Disconnects from the remote peer.  Does not disconnect the client,
+ * as there may be multiple operations per set.
+ *
+ * @param op operation to destroy
+ */
+static void
+_GSS_operation_destroy (struct Operation *op)
+{
+  struct Set *set = op->set;
+  struct GNUNET_CADET_Channel *channel;
+
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "Destroying union operation %p\n",
+              op);
+  GNUNET_assert (NULL == op->listener);
+  /* check if the op was canceled twice */
+  if (NULL != op->remote_ibf)
+  {
+    ibf_destroy (op->remote_ibf);
+    op->remote_ibf = NULL;
+  }
+  if (NULL != op->demanded_hashes)
+  {
+    GNUNET_CONTAINER_multihashmap_destroy (op->demanded_hashes);
+    op->demanded_hashes = NULL;
+  }
+  if (NULL != op->local_ibf)
+  {
+    ibf_destroy (op->local_ibf);
+    op->local_ibf = NULL;
+  }
+  if (NULL != op->se)
+  {
+    strata_estimator_destroy (op->se);
+    op->se = NULL;
+  }
+  if (NULL != op->key_to_element)
+  {
+    GNUNET_CONTAINER_multihashmap32_iterate (op->key_to_element,
+                                             &destroy_key_to_element_iter,
+                                             NULL);
+    GNUNET_CONTAINER_multihashmap32_destroy (op->key_to_element);
+    op->key_to_element = NULL;
+  }
+  if (NULL != set)
+  {
+    GNUNET_CONTAINER_DLL_remove (set->ops_head,
+                                 set->ops_tail,
+                                 op);
+    op->set = NULL;
+  }
+  if (NULL != op->context_msg)
+  {
+    GNUNET_free (op->context_msg);
+    op->context_msg = NULL;
+  }
+  if (NULL != (channel = op->channel))
+  {
+    /* This will free op; called conditionally as this helper function
+       is also called from within the channel disconnect handler. */
+    op->channel = NULL;
+    GNUNET_CADET_channel_destroy (channel);
+  }
+  /* We rely on the channel end handler to free 'op'. When 'op->channel' was NULL,
+   * there was a channel end handler that will free 'op' on the call stack. */
+}
+
+
+/**
+ * This function probably should not exist
+ * and be replaced by inlining more specific
+ * logic in the various places where it is called.
+ */
+static void
+_GSS_operation_destroy2 (struct Operation *op);
+
+
+/**
+ * Destroy an incoming request from a remote peer
+ *
+ * @param op remote request to destroy
+ */
+static void
+incoming_destroy (struct Operation *op)
+{
+  struct Listener *listener;
+
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "Destroying incoming operation %p\n",
+              op);
+  if (NULL != (listener = op->listener))
+  {
+    GNUNET_CONTAINER_DLL_remove (listener->op_head,
+                                 listener->op_tail,
+                                 op);
+    op->listener = NULL;
+  }
+  if (NULL != op->timeout_task)
+  {
+    GNUNET_SCHEDULER_cancel (op->timeout_task);
+    op->timeout_task = NULL;
+  }
+  _GSS_operation_destroy2 (op);
+}
+
+
+/**
+ * This function probably should not exist
+ * and be replaced by inlining more specific
+ * logic in the various places where it is called.
+ */
+static void
+_GSS_operation_destroy2 (struct Operation *op)
+{
+  struct GNUNET_CADET_Channel *channel;
+
+  if (NULL != (channel = op->channel))
+  {
+    /* This will free op; called conditionally as this helper function
+       is also called from within the channel disconnect handler. */
+    op->channel = NULL;
+    GNUNET_CADET_channel_destroy (channel);
+  }
+  if (NULL != op->listener)
+  {
+    incoming_destroy (op);
+    return;
+  }
+  if (NULL != op->set)
+    send_client_done (op);
+  _GSS_operation_destroy (op);
+  GNUNET_free (op);
+}
+
+
+/**
+ * Inform the client that the union operation has failed,
+ * and proceed to destroy the evaluate operation.
+ *
+ * @param op the union operation to fail
+ */
+static void
+fail_union_operation (struct Operation *op)
+{
+  struct GNUNET_MQ_Envelope *ev;
+  struct GNUNET_SETU_ResultMessage *msg;
+
+  LOG (GNUNET_ERROR_TYPE_WARNING,
+       "union operation failed\n");
+  ev = GNUNET_MQ_msg (msg, GNUNET_MESSAGE_TYPE_SETU_RESULT);
+  msg->result_status = htons (GNUNET_SETU_STATUS_FAILURE);
+  msg->request_id = htonl (op->client_request_id);
+  msg->element_type = htons (0);
+  GNUNET_MQ_send (op->set->cs->mq,
+                  ev);
+  _GSS_operation_destroy (op);
+}
+
+
+/**
+ * Derive the IBF key from a hash code and
+ * a salt.
+ *
+ * @param src the hash code
+ * @return the derived IBF key
+ */
+static struct IBF_Key
+get_ibf_key (const struct GNUNET_HashCode *src)
+{
+  struct IBF_Key key;
+  uint16_t salt = 0;
+
+  GNUNET_assert (GNUNET_OK ==
+                 GNUNET_CRYPTO_kdf (&key, sizeof(key),
+                                    src, sizeof *src,
+                                    &salt, sizeof(salt),
+                                    NULL, 0));
+  return key;
+}
+
+
+/**
+ * Context for #op_get_element_iterator
+ */
+struct GetElementContext
+{
+  /**
+   * FIXME.
+   */
+  struct GNUNET_HashCode hash;
+
+  /**
+   * FIXME.
+   */
+  struct KeyEntry *k;
+};
+
+
+/**
+ * Iterator over the mapping from IBF keys to element entries.  Checks if we
+ * have an element with a given GNUNET_HashCode.
+ *
+ * @param cls closure
+ * @param key current key code
+ * @param value value in the hash map
+ * @return #GNUNET_YES if we should search further,
+ *         #GNUNET_NO if we've found the element.
+ */
+static int
+op_get_element_iterator (void *cls,
+                         uint32_t key,
+                         void *value)
+{
+  struct GetElementContext *ctx = cls;
+  struct KeyEntry *k = value;
+
+  GNUNET_assert (NULL != k);
+  if (0 == GNUNET_CRYPTO_hash_cmp (&k->element->element_hash,
+                                   &ctx->hash))
+  {
+    ctx->k = k;
+    return GNUNET_NO;
+  }
+  return GNUNET_YES;
+}
+
+
+/**
+ * Determine whether the given element is already in the operation's element
+ * set.
+ *
+ * @param op operation that should be tested for 'element_hash'
+ * @param element_hash hash of the element to look for
+ * @return #GNUNET_YES if the element has been found, #GNUNET_NO otherwise
+ */
+static struct KeyEntry *
+op_get_element (struct Operation *op,
+                const struct GNUNET_HashCode *element_hash)
+{
+  int ret;
+  struct IBF_Key ibf_key;
+  struct GetElementContext ctx = { { { 0 } }, 0 };
+
+  ctx.hash = *element_hash;
+
+  ibf_key = get_ibf_key (element_hash);
+  ret = GNUNET_CONTAINER_multihashmap32_get_multiple (op->key_to_element,
+                                                      (uint32_t) ibf_key.key_val,
+                                                      &op_get_element_iterator,
+                                                      &ctx);
+
+  /* was the iteration aborted because we found the element? */
+  if (GNUNET_SYSERR == ret)
+  {
+    GNUNET_assert (NULL != ctx.k);
+    return ctx.k;
+  }
+  return NULL;
+}
+
+
+/**
+ * Insert an element into the union operation's
+ * key-to-element mapping. Takes ownership of 'ee'.
+ * Note that this does not insert the element in the set,
+ * only in the operation's key-element mapping.
+ * This is done to speed up re-tried operations, if some elements
+ * were transmitted, and then the IBF fails to decode.
+ *
+ * XXX: clarify ownership, doesn't sound right.
+ *
+ * @param op the union operation
+ * @param ee the element entry
+ * @parem received was this element received from the remote peer?
+ */
+static void
+op_register_element (struct Operation *op,
+                     struct ElementEntry *ee,
+                     int received)
+{
+  struct IBF_Key ibf_key;
+  struct KeyEntry *k;
+
+  ibf_key = get_ibf_key (&ee->element_hash);
+  k = GNUNET_new (struct KeyEntry);
+  k->element = ee;
+  k->ibf_key = ibf_key;
+  k->received = received;
+  GNUNET_assert (GNUNET_OK ==
+                 GNUNET_CONTAINER_multihashmap32_put (op->key_to_element,
+                                                      (uint32_t) ibf_key.key_val,
+                                                      k,
+                                                      GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE));
+}
+
+
+/**
+ * FIXME.
+ */
+static void
+salt_key (const struct IBF_Key *k_in,
+          uint32_t salt,
+          struct IBF_Key *k_out)
+{
+  int s = salt % 64;
+  uint64_t x = k_in->key_val;
+
+  /* rotate ibf key */
+  x = (x >> s) | (x << (64 - s));
+  k_out->key_val = x;
+}
+
+
+/**
+ * FIXME.
+ */
+static void
+unsalt_key (const struct IBF_Key *k_in,
+            uint32_t salt,
+            struct IBF_Key *k_out)
+{
+  int s = salt % 64;
+  uint64_t x = k_in->key_val;
+
+  x = (x << s) | (x >> (64 - s));
+  k_out->key_val = x;
+}
+
+
+/**
+ * Insert a key into an ibf.
+ *
+ * @param cls the ibf
+ * @param key unused
+ * @param value the key entry to get the key from
+ */
+static int
+prepare_ibf_iterator (void *cls,
+                      uint32_t key,
+                      void *value)
+{
+  struct Operation *op = cls;
+  struct KeyEntry *ke = value;
+  struct IBF_Key salted_key;
+
+  LOG (GNUNET_ERROR_TYPE_DEBUG,
+       "[OP %x] inserting %lx (hash %s) into ibf\n",
+       (void *) op,
+       (unsigned long) ke->ibf_key.key_val,
+       GNUNET_h2s (&ke->element->element_hash));
+  salt_key (&ke->ibf_key,
+            op->salt_send,
+            &salted_key);
+  ibf_insert (op->local_ibf, salted_key);
+  return GNUNET_YES;
+}
+
+
+/**
+ * Is element @a ee part of the set used by @a op?
+ *
+ * @param ee element to test
+ * @param op operation the defines the set and its generation
+ * @return #GNUNET_YES if the element is in the set, #GNUNET_NO if not
+ */
+static int
+_GSS_is_element_of_operation (struct ElementEntry *ee,
+                              struct Operation *op)
+{
+  return ee->generation >= op->generation_created;
+}
+
+
+/**
+ * Iterator for initializing the
+ * key-to-element mapping of a union operation
+ *
+ * @param cls the union operation `struct Operation *`
+ * @param key unused
+ * @param value the `struct ElementEntry *` to insert
+ *        into the key-to-element mapping
+ * @return #GNUNET_YES (to continue iterating)
+ */
+static int
+init_key_to_element_iterator (void *cls,
+                              const struct GNUNET_HashCode *key,
+                              void *value)
+{
+  struct Operation *op = cls;
+  struct ElementEntry *ee = value;
+
+  /* make sure that the element belongs to the set at the time
+   * of creating the operation */
+  if (GNUNET_NO ==
+      _GSS_is_element_of_operation (ee,
+                                    op))
+    return GNUNET_YES;
+  GNUNET_assert (GNUNET_NO == ee->remote);
+  op_register_element (op,
+                       ee,
+                       GNUNET_NO);
+  return GNUNET_YES;
+}
+
+
+/**
+ * Initialize the IBF key to element mapping local to this set operation.
+ *
+ * @param op the set union operation
+ */
+static void
+initialize_key_to_element (struct Operation *op)
+{
+  unsigned int len;
+
+  GNUNET_assert (NULL == op->key_to_element);
+  len = GNUNET_CONTAINER_multihashmap_size (op->set->content->elements);
+  op->key_to_element = GNUNET_CONTAINER_multihashmap32_create (len + 1);
+  GNUNET_CONTAINER_multihashmap_iterate (op->set->content->elements,
+                                         &init_key_to_element_iterator,
+                                         op);
+}
+
+
+/**
+ * Create an ibf with the operation's elements
+ * of the specified size
+ *
+ * @param op the union operation
+ * @param size size of the ibf to create
+ * @return #GNUNET_OK on success, #GNUNET_SYSERR on failure
+ */
+static int
+prepare_ibf (struct Operation *op,
+             uint32_t size)
+{
+  GNUNET_assert (NULL != op->key_to_element);
+
+  if (NULL != op->local_ibf)
+    ibf_destroy (op->local_ibf);
+  op->local_ibf = ibf_create (size, SE_IBF_HASH_NUM);
+  if (NULL == op->local_ibf)
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                "Failed to allocate local IBF\n");
+    return GNUNET_SYSERR;
+  }
+  GNUNET_CONTAINER_multihashmap32_iterate (op->key_to_element,
+                                           &prepare_ibf_iterator,
+                                           op);
+  return GNUNET_OK;
+}
+
+
+/**
+ * Send an ibf of appropriate size.
+ *
+ * Fragments the IBF into multiple messages if necessary.
+ *
+ * @param op the union operation
+ * @param ibf_order order of the ibf to send, size=2^order
+ * @return #GNUNET_OK on success, #GNUNET_SYSERR on failure
+ */
+static int
+send_ibf (struct Operation *op,
+          uint16_t ibf_order)
+{
+  unsigned int buckets_sent = 0;
+  struct InvertibleBloomFilter *ibf;
+
+  if (GNUNET_OK !=
+      prepare_ibf (op, 1 << ibf_order))
+  {
+    /* allocation failed */
+    return GNUNET_SYSERR;
+  }
+
+  LOG (GNUNET_ERROR_TYPE_DEBUG,
+       "sending ibf of size %u\n",
+       1 << ibf_order);
+
+  {
+    char name[64] = { 0 };
+    snprintf (name, sizeof(name), "# sent IBF (order %u)", ibf_order);
+    GNUNET_STATISTICS_update (_GSS_statistics, name, 1, GNUNET_NO);
+  }
+
+  ibf = op->local_ibf;
+
+  while (buckets_sent < (1 << ibf_order))
+  {
+    unsigned int buckets_in_message;
+    struct GNUNET_MQ_Envelope *ev;
+    struct IBFMessage *msg;
+
+    buckets_in_message = (1 << ibf_order) - buckets_sent;
+    /* limit to maximum */
+    if (buckets_in_message > MAX_BUCKETS_PER_MESSAGE)
+      buckets_in_message = MAX_BUCKETS_PER_MESSAGE;
+
+    ev = GNUNET_MQ_msg_extra (msg,
+                              buckets_in_message * IBF_BUCKET_SIZE,
+                              GNUNET_MESSAGE_TYPE_SETU_P2P_IBF);
+    msg->reserved1 = 0;
+    msg->reserved2 = 0;
+    msg->order = ibf_order;
+    msg->offset = htonl (buckets_sent);
+    msg->salt = htonl (op->salt_send);
+    ibf_write_slice (ibf, buckets_sent,
+                     buckets_in_message, &msg[1]);
+    buckets_sent += buckets_in_message;
+    LOG (GNUNET_ERROR_TYPE_DEBUG,
+         "ibf chunk size %u, %u/%u sent\n",
+         buckets_in_message,
+         buckets_sent,
+         1 << ibf_order);
+    GNUNET_MQ_send (op->mq, ev);
+  }
+
+  /* The other peer must decode the IBF, so
+   * we're passive. */
+  op->phase = PHASE_INVENTORY_PASSIVE;
+  return GNUNET_OK;
+}
+
+
+/**
+ * Compute the necessary order of an ibf
+ * from the size of the symmetric set difference.
+ *
+ * @param diff the difference
+ * @return the required size of the ibf
+ */
+static unsigned int
+get_order_from_difference (unsigned int diff)
+{
+  unsigned int ibf_order;
+
+  ibf_order = 2;
+  while (((1 << ibf_order) < (IBF_ALPHA * diff) ||
+          ((1 << ibf_order) < SE_IBF_HASH_NUM)) &&
+         (ibf_order < MAX_IBF_ORDER))
+    ibf_order++;
+  // add one for correction
+  return ibf_order + 1;
+}
+
+
+/**
+ * Send a set element.
+ *
+ * @param cls the union operation `struct Operation *`
+ * @param key unused
+ * @param value the `struct ElementEntry *` to insert
+ *        into the key-to-element mapping
+ * @return #GNUNET_YES (to continue iterating)
+ */
+static int
+send_full_element_iterator (void *cls,
+                            const struct GNUNET_HashCode *key,
+                            void *value)
+{
+  struct Operation *op = cls;
+  struct GNUNET_SETU_ElementMessage *emsg;
+  struct ElementEntry *ee = value;
+  struct GNUNET_SETU_Element *el = &ee->element;
+  struct GNUNET_MQ_Envelope *ev;
+
+  LOG (GNUNET_ERROR_TYPE_DEBUG,
+       "Sending element %s\n",
+       GNUNET_h2s (key));
+  ev = GNUNET_MQ_msg_extra (emsg,
+                            el->size,
+                            GNUNET_MESSAGE_TYPE_SETU_P2P_FULL_ELEMENT);
+  emsg->element_type = htons (el->element_type);
+  GNUNET_memcpy (&emsg[1],
+                 el->data,
+                 el->size);
+  GNUNET_MQ_send (op->mq,
+                  ev);
+  return GNUNET_YES;
+}
+
+
+/**
+ * Switch to full set transmission for @a op.
+ *
+ * @param op operation to switch to full set transmission.
+ */
+static void
+send_full_set (struct Operation *op)
+{
+  struct GNUNET_MQ_Envelope *ev;
+
+  op->phase = PHASE_FULL_SENDING;
+  LOG (GNUNET_ERROR_TYPE_DEBUG,
+       "Dedicing to transmit the full set\n");
+  /* FIXME: use a more memory-friendly way of doing this with an
+     iterator, just as we do in the non-full case! */
+  (void) GNUNET_CONTAINER_multihashmap_iterate (op->set->content->elements,
+                                                &send_full_element_iterator,
+                                                op);
+  ev = GNUNET_MQ_msg_header (GNUNET_MESSAGE_TYPE_SETU_P2P_FULL_DONE);
+  GNUNET_MQ_send (op->mq,
+                  ev);
+}
+
+
+/**
+ * Handle a strata estimator from a remote peer
+ *
+ * @param cls the union operation
+ * @param msg the message
+ */
+static int
+check_union_p2p_strata_estimator (void *cls,
+                                  const struct StrataEstimatorMessage *msg)
+{
+  struct Operation *op = cls;
+  int is_compressed;
+  size_t len;
+
+  if (op->phase != PHASE_EXPECT_SE)
+  {
+    GNUNET_break (0);
+    return GNUNET_SYSERR;
+  }
+  is_compressed = (GNUNET_MESSAGE_TYPE_SETU_P2P_SEC == htons (
+                     msg->header.type));
+  len = ntohs (msg->header.size) - sizeof(struct StrataEstimatorMessage);
+  if ((GNUNET_NO == is_compressed) &&
+      (len != SE_STRATA_COUNT * SE_IBF_SIZE * IBF_BUCKET_SIZE))
+  {
+    GNUNET_break (0);
+    return GNUNET_SYSERR;
+  }
+  return GNUNET_OK;
+}
+
+
+/**
+ * Handle a strata estimator from a remote peer
+ *
+ * @param cls the union operation
+ * @param msg the message
+ */
+static void
+handle_union_p2p_strata_estimator (void *cls,
+                                   const struct StrataEstimatorMessage *msg)
+{
+  struct Operation *op = cls;
+  struct StrataEstimator *remote_se;
+  unsigned int diff;
+  uint64_t other_size;
+  size_t len;
+  int is_compressed;
+
+  is_compressed = (GNUNET_MESSAGE_TYPE_SETU_P2P_SEC == htons (
+                     msg->header.type));
+  GNUNET_STATISTICS_update (_GSS_statistics,
+                            "# bytes of SE received",
+                            ntohs (msg->header.size),
+                            GNUNET_NO);
+  len = ntohs (msg->header.size) - sizeof(struct StrataEstimatorMessage);
+  other_size = GNUNET_ntohll (msg->set_size);
+  remote_se = strata_estimator_create (SE_STRATA_COUNT,
+                                       SE_IBF_SIZE,
+                                       SE_IBF_HASH_NUM);
+  if (NULL == remote_se)
+  {
+    /* insufficient resources, fail */
+    fail_union_operation (op);
+    return;
+  }
+  if (GNUNET_OK !=
+      strata_estimator_read (&msg[1],
+                             len,
+                             is_compressed,
+                             remote_se))
+  {
+    /* decompression failed */
+    strata_estimator_destroy (remote_se);
+    fail_union_operation (op);
+    return;
+  }
+  GNUNET_assert (NULL != op->se);
+  diff = strata_estimator_difference (remote_se,
+                                      op->se);
+
+  if (diff > 200)
+    diff = diff * 3 / 2;
+
+  strata_estimator_destroy (remote_se);
+  strata_estimator_destroy (op->se);
+  op->se = NULL;
+  LOG (GNUNET_ERROR_TYPE_DEBUG,
+       "got se diff=%d, using ibf size %d\n",
+       diff,
+       1U << get_order_from_difference (diff));
+
+  {
+    char *set_debug;
+
+    set_debug = getenv ("GNUNET_SETU_BENCHMARK");
+    if ((NULL != set_debug) &&
+        (0 == strcmp (set_debug, "1")))
+    {
+      FILE *f = fopen ("set.log", "a");
+      fprintf (f, "%llu\n", (unsigned long long) diff);
+      fclose (f);
+    }
+  }
+
+  if ((GNUNET_YES == op->byzantine) &&
+      (other_size < op->byzantine_lower_bound))
+  {
+    GNUNET_break (0);
+    fail_union_operation (op);
+    return;
+  }
+
+  if ((GNUNET_YES == op->force_full) ||
+      (diff > op->initial_size / 4) ||
+      (0 == other_size))
+  {
+    LOG (GNUNET_ERROR_TYPE_DEBUG,
+         "Deciding to go for full set transmission (diff=%d, own set=%u)\n",
+         diff,
+         op->initial_size);
+    GNUNET_STATISTICS_update (_GSS_statistics,
+                              "# of full sends",
+                              1,
+                              GNUNET_NO);
+    if ((op->initial_size <= other_size) ||
+        (0 == other_size))
+    {
+      send_full_set (op);
+    }
+    else
+    {
+      struct GNUNET_MQ_Envelope *ev;
+
+      LOG (GNUNET_ERROR_TYPE_DEBUG,
+           "Telling other peer that we expect its full set\n");
+      op->phase = PHASE_EXPECT_IBF;
+      ev = GNUNET_MQ_msg_header (
+        GNUNET_MESSAGE_TYPE_SETU_P2P_REQUEST_FULL);
+      GNUNET_MQ_send (op->mq,
+                      ev);
+    }
+  }
+  else
+  {
+    GNUNET_STATISTICS_update (_GSS_statistics,
+                              "# of ibf sends",
+                              1,
+                              GNUNET_NO);
+    if (GNUNET_OK !=
+        send_ibf (op,
+                  get_order_from_difference (diff)))
+    {
+      /* Internal error, best we can do is shut the connection */
+      GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                  "Failed to send IBF, closing connection\n");
+      fail_union_operation (op);
+      return;
+    }
+  }
+  GNUNET_CADET_receive_done (op->channel);
+}
+
+
+/**
+ * Iterator to send elements to a remote peer
+ *
+ * @param cls closure with the element key and the union operation
+ * @param key ignored
+ * @param value the key entry
+ */
+static int
+send_offers_iterator (void *cls,
+                      uint32_t key,
+                      void *value)
+{
+  struct SendElementClosure *sec = cls;
+  struct Operation *op = sec->op;
+  struct KeyEntry *ke = value;
+  struct GNUNET_MQ_Envelope *ev;
+  struct GNUNET_MessageHeader *mh;
+
+  /* Detect 32-bit key collision for the 64-bit IBF keys. */
+  if (ke->ibf_key.key_val != sec->ibf_key.key_val)
+    return GNUNET_YES;
+
+  ev = GNUNET_MQ_msg_header_extra (mh,
+                                   sizeof(struct GNUNET_HashCode),
+                                   GNUNET_MESSAGE_TYPE_SETU_P2P_OFFER);
+
+  GNUNET_assert (NULL != ev);
+  *(struct GNUNET_HashCode *) &mh[1] = ke->element->element_hash;
+  LOG (GNUNET_ERROR_TYPE_DEBUG,
+       "[OP %x] sending element offer (%s) to peer\n",
+       (void *) op,
+       GNUNET_h2s (&ke->element->element_hash));
+  GNUNET_MQ_send (op->mq, ev);
+  return GNUNET_YES;
+}
+
+
+/**
+ * Send offers (in the form of GNUNET_Hash-es) to the remote peer for the given IBF key.
+ *
+ * @param op union operation
+ * @param ibf_key IBF key of interest
+ */
+static void
+send_offers_for_key (struct Operation *op,
+                     struct IBF_Key ibf_key)
+{
+  struct SendElementClosure send_cls;
+
+  send_cls.ibf_key = ibf_key;
+  send_cls.op = op;
+  (void) GNUNET_CONTAINER_multihashmap32_get_multiple (
+    op->key_to_element,
+    (uint32_t) ibf_key.
+    key_val,
+    &send_offers_iterator,
+    &send_cls);
+}
+
+
+/**
+ * Decode which elements are missing on each side, and
+ * send the appropriate offers and inquiries.
+ *
+ * @param op union operation
+ * @return #GNUNET_OK on success, #GNUNET_SYSERR on failure
+ */
+static int
+decode_and_send (struct Operation *op)
+{
+  struct IBF_Key key;
+  struct IBF_Key last_key;
+  int side;
+  unsigned int num_decoded;
+  struct InvertibleBloomFilter *diff_ibf;
+
+  GNUNET_assert (PHASE_INVENTORY_ACTIVE == op->phase);
+
+  if (GNUNET_OK !=
+      prepare_ibf (op,
+                   op->remote_ibf->size))
+  {
+    GNUNET_break (0);
+    /* allocation failed */
+    return GNUNET_SYSERR;
+  }
+  diff_ibf = ibf_dup (op->local_ibf);
+  ibf_subtract (diff_ibf,
+                op->remote_ibf);
+
+  ibf_destroy (op->remote_ibf);
+  op->remote_ibf = NULL;
+
+  LOG (GNUNET_ERROR_TYPE_DEBUG,
+       "decoding IBF (size=%u)\n",
+       diff_ibf->size);
+
+  num_decoded = 0;
+  key.key_val = 0; /* just to avoid compiler thinking we use undef'ed variable */
+
+  while (1)
+  {
+    int res;
+    int cycle_detected = GNUNET_NO;
+
+    last_key = key;
+
+    res = ibf_decode (diff_ibf,
+                      &side,
+                      &key);
+    if (res == GNUNET_OK)
+    {
+      LOG (GNUNET_ERROR_TYPE_DEBUG,
+           "decoded ibf key %lx\n",
+           (unsigned long) key.key_val);
+      num_decoded += 1;
+      if ((num_decoded > diff_ibf->size) ||
+          ((num_decoded > 1) &&
+           (last_key.key_val == key.key_val)))
+      {
+        LOG (GNUNET_ERROR_TYPE_DEBUG,
+             "detected cyclic ibf (decoded %u/%u)\n",
+             num_decoded,
+             diff_ibf->size);
+        cycle_detected = GNUNET_YES;
+      }
+    }
+    if ((GNUNET_SYSERR == res) ||
+        (GNUNET_YES == cycle_detected))
+    {
+      int next_order;
+      next_order = 0;
+      while (1 << next_order < diff_ibf->size)
+        next_order++;
+      next_order++;
+      if (next_order <= MAX_IBF_ORDER)
+      {
+        LOG (GNUNET_ERROR_TYPE_DEBUG,
+             "decoding failed, sending larger ibf (size %u)\n",
+             1 << next_order);
+        GNUNET_STATISTICS_update (_GSS_statistics,
+                                  "# of IBF retries",
+                                  1,
+                                  GNUNET_NO);
+        op->salt_send++;
+        if (GNUNET_OK !=
+            send_ibf (op, next_order))
+        {
+          /* Internal error, best we can do is shut the connection */
+          GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                      "Failed to send IBF, closing connection\n");
+          fail_union_operation (op);
+          ibf_destroy (diff_ibf);
+          return GNUNET_SYSERR;
+        }
+      }
+      else
+      {
+        GNUNET_STATISTICS_update (_GSS_statistics,
+                                  "# of failed union operations (too large)",
+                                  1,
+                                  GNUNET_NO);
+        // XXX: Send the whole set, element-by-element
+        LOG (GNUNET_ERROR_TYPE_ERROR,
+             "set union failed: reached ibf limit\n");
+        fail_union_operation (op);
+        ibf_destroy (diff_ibf);
+        return GNUNET_SYSERR;
+      }
+      break;
+    }
+    if (GNUNET_NO == res)
+    {
+      struct GNUNET_MQ_Envelope *ev;
+
+      LOG (GNUNET_ERROR_TYPE_DEBUG,
+           "transmitted all values, sending DONE\n");
+      ev = GNUNET_MQ_msg_header (GNUNET_MESSAGE_TYPE_SETU_P2P_DONE);
+      GNUNET_MQ_send (op->mq, ev);
+      /* We now wait until we get a DONE message back
+       * and then wait for our MQ to be flushed and all our
+       * demands be delivered. */
+      break;
+    }
+    if (1 == side)
+    {
+      struct IBF_Key unsalted_key;
+
+      unsalt_key (&key,
+                  op->salt_receive,
+                  &unsalted_key);
+      send_offers_for_key (op,
+                           unsalted_key);
+    }
+    else if (-1 == side)
+    {
+      struct GNUNET_MQ_Envelope *ev;
+      struct InquiryMessage *msg;
+
+      /* It may be nice to merge multiple requests, but with CADET's corking it is not worth
+       * the effort additional complexity. */
+      ev = GNUNET_MQ_msg_extra (msg,
+                                sizeof(struct IBF_Key),
+                                GNUNET_MESSAGE_TYPE_SETU_P2P_INQUIRY);
+      msg->salt = htonl (op->salt_receive);
+      GNUNET_memcpy (&msg[1],
+                     &key,
+                     sizeof(struct IBF_Key));
+      LOG (GNUNET_ERROR_TYPE_DEBUG,
+           "sending element inquiry for IBF key %lx\n",
+           (unsigned long) key.key_val);
+      GNUNET_MQ_send (op->mq, ev);
+    }
+    else
+    {
+      GNUNET_assert (0);
+    }
+  }
+  ibf_destroy (diff_ibf);
+  return GNUNET_OK;
+}
+
+
+/**
+ * Check an IBF message from a remote peer.
+ *
+ * Reassemble the IBF from multiple pieces, and
+ * process the whole IBF once possible.
+ *
+ * @param cls the union operation
+ * @param msg the header of the message
+ * @return #GNUNET_OK if @a msg is well-formed
+ */
+static int
+check_union_p2p_ibf (void *cls,
+                     const struct IBFMessage *msg)
+{
+  struct Operation *op = cls;
+  unsigned int buckets_in_message;
+
+  buckets_in_message = (ntohs (msg->header.size) - sizeof *msg)
+                       / IBF_BUCKET_SIZE;
+  if (0 == buckets_in_message)
+  {
+    GNUNET_break_op (0);
+    return GNUNET_SYSERR;
+  }
+  if ((ntohs (msg->header.size) - sizeof *msg) != buckets_in_message
+      * IBF_BUCKET_SIZE)
+  {
+    GNUNET_break_op (0);
+    return GNUNET_SYSERR;
+  }
+  if (op->phase == PHASE_EXPECT_IBF_CONT)
+  {
+    if (ntohl (msg->offset) != op->ibf_buckets_received)
+    {
+      GNUNET_break_op (0);
+      return GNUNET_SYSERR;
+    }
+    if (1 << msg->order != op->remote_ibf->size)
+    {
+      GNUNET_break_op (0);
+      return GNUNET_SYSERR;
+    }
+    if (ntohl (msg->salt) != op->salt_receive)
+    {
+      GNUNET_break_op (0);
+      return GNUNET_SYSERR;
+    }
+  }
+  else if ((op->phase != PHASE_INVENTORY_PASSIVE) &&
+           (op->phase != PHASE_EXPECT_IBF))
+  {
+    GNUNET_break_op (0);
+    return GNUNET_SYSERR;
+  }
+
+  return GNUNET_OK;
+}
+
+
+/**
+ * Handle an IBF message from a remote peer.
+ *
+ * Reassemble the IBF from multiple pieces, and
+ * process the whole IBF once possible.
+ *
+ * @param cls the union operation
+ * @param msg the header of the message
+ */
+static void
+handle_union_p2p_ibf (void *cls,
+                      const struct IBFMessage *msg)
+{
+  struct Operation *op = cls;
+  unsigned int buckets_in_message;
+
+  buckets_in_message = (ntohs (msg->header.size) - sizeof *msg)
+                       / IBF_BUCKET_SIZE;
+  if ((op->phase == PHASE_INVENTORY_PASSIVE) ||
+      (op->phase == PHASE_EXPECT_IBF))
+  {
+    op->phase = PHASE_EXPECT_IBF_CONT;
+    GNUNET_assert (NULL == op->remote_ibf);
+    LOG (GNUNET_ERROR_TYPE_DEBUG,
+         "Creating new ibf of size %u\n",
+         1 << msg->order);
+    op->remote_ibf = ibf_create (1 << msg->order, SE_IBF_HASH_NUM);
+    op->salt_receive = ntohl (msg->salt);
+    LOG (GNUNET_ERROR_TYPE_DEBUG,
+         "Receiving new IBF with salt %u\n",
+         op->salt_receive);
+    if (NULL == op->remote_ibf)
+    {
+      GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                  "Failed to parse remote IBF, closing connection\n");
+      fail_union_operation (op);
+      return;
+    }
+    op->ibf_buckets_received = 0;
+    if (0 != ntohl (msg->offset))
+    {
+      GNUNET_break_op (0);
+      fail_union_operation (op);
+      return;
+    }
+  }
+  else
+  {
+    GNUNET_assert (op->phase == PHASE_EXPECT_IBF_CONT);
+    LOG (GNUNET_ERROR_TYPE_DEBUG,
+         "Received more of IBF\n");
+  }
+  GNUNET_assert (NULL != op->remote_ibf);
+
+  ibf_read_slice (&msg[1],
+                  op->ibf_buckets_received,
+                  buckets_in_message,
+                  op->remote_ibf);
+  op->ibf_buckets_received += buckets_in_message;
+
+  if (op->ibf_buckets_received == op->remote_ibf->size)
+  {
+    LOG (GNUNET_ERROR_TYPE_DEBUG,
+         "received full ibf\n");
+    op->phase = PHASE_INVENTORY_ACTIVE;
+    if (GNUNET_OK !=
+        decode_and_send (op))
+    {
+      /* Internal error, best we can do is shut down */
+      GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                  "Failed to decode IBF, closing connection\n");
+      fail_union_operation (op);
+      return;
+    }
+  }
+  GNUNET_CADET_receive_done (op->channel);
+}
+
+
+/**
+ * Send a result message to the client indicating
+ * that there is a new element.
+ *
+ * @param op union operation
+ * @param element element to send
+ * @param status status to send with the new element
+ */
+static void
+send_client_element (struct Operation *op,
+                     const struct GNUNET_SETU_Element *element,
+                     enum GNUNET_SETU_Status status)
+{
+  struct GNUNET_MQ_Envelope *ev;
+  struct GNUNET_SETU_ResultMessage *rm;
+
+  LOG (GNUNET_ERROR_TYPE_DEBUG,
+       "sending element (size %u) to client\n",
+       element->size);
+  GNUNET_assert (0 != op->client_request_id);
+  ev = GNUNET_MQ_msg_extra (rm,
+                            element->size,
+                            GNUNET_MESSAGE_TYPE_SETU_RESULT);
+  if (NULL == ev)
+  {
+    GNUNET_MQ_discard (ev);
+    GNUNET_break (0);
+    return;
+  }
+  rm->result_status = htons (status);
+  rm->request_id = htonl (op->client_request_id);
+  rm->element_type = htons (element->element_type);
+  rm->current_size = GNUNET_htonll (GNUNET_CONTAINER_multihashmap32_size (
+                                      op->key_to_element));
+  GNUNET_memcpy (&rm[1],
+                 element->data,
+                 element->size);
+  GNUNET_MQ_send (op->set->cs->mq,
+                  ev);
+}
+
+
+/**
+ * Tests if the operation is finished, and if so notify.
+ *
+ * @param op operation to check
+ */
+static void
+maybe_finish (struct Operation *op)
+{
+  unsigned int num_demanded;
+
+  num_demanded = GNUNET_CONTAINER_multihashmap_size (
+    op->demanded_hashes);
+
+  if (PHASE_FINISH_WAITING == op->phase)
+  {
+    LOG (GNUNET_ERROR_TYPE_DEBUG,
+         "In PHASE_FINISH_WAITING, pending %u demands\n",
+         num_demanded);
+    if (0 == num_demanded)
+    {
+      struct GNUNET_MQ_Envelope *ev;
+
+      op->phase = PHASE_DONE;
+      ev = GNUNET_MQ_msg_header (GNUNET_MESSAGE_TYPE_SETU_P2P_DONE);
+      GNUNET_MQ_send (op->mq,
+                      ev);
+      /* We now wait until the other peer sends P2P_OVER
+       * after it got all elements from us. */
+    }
+  }
+  if (PHASE_FINISH_CLOSING == op->phase)
+  {
+    LOG (GNUNET_ERROR_TYPE_DEBUG,
+         "In PHASE_FINISH_CLOSING, pending %u demands\n",
+         num_demanded);
+    if (0 == num_demanded)
+    {
+      op->phase = PHASE_DONE;
+      send_client_done (op);
+      _GSS_operation_destroy2 (op);
+    }
+  }
+}
+
+
+/**
+ * Check an element message from a remote peer.
+ *
+ * @param cls the union operation
+ * @param emsg the message
+ */
+static int
+check_union_p2p_elements (void *cls,
+                          const struct GNUNET_SETU_ElementMessage *emsg)
+{
+  struct Operation *op = cls;
+
+  if (0 == GNUNET_CONTAINER_multihashmap_size (op->demanded_hashes))
+  {
+    GNUNET_break_op (0);
+    return GNUNET_SYSERR;
+  }
+  return GNUNET_OK;
+}
+
+
+/**
+ * Handle an element message from a remote peer.
+ * Sent by the other peer either because we decoded an IBF and placed a demand,
+ * or because the other peer switched to full set transmission.
+ *
+ * @param cls the union operation
+ * @param emsg the message
+ */
+static void
+handle_union_p2p_elements (void *cls,
+                           const struct GNUNET_SETU_ElementMessage *emsg)
+{
+  struct Operation *op = cls;
+  struct ElementEntry *ee;
+  struct KeyEntry *ke;
+  uint16_t element_size;
+
+  element_size = ntohs (emsg->header.size) - sizeof(struct
+                                                    GNUNET_SETU_ElementMessage);
+  ee = GNUNET_malloc (sizeof(struct ElementEntry) + element_size);
+  GNUNET_memcpy (&ee[1],
+                 &emsg[1],
+                 element_size);
+  ee->element.size = element_size;
+  ee->element.data = &ee[1];
+  ee->element.element_type = ntohs (emsg->element_type);
+  ee->remote = GNUNET_YES;
+  GNUNET_SETU_element_hash (&ee->element,
+                            &ee->element_hash);
+  if (GNUNET_NO ==
+      GNUNET_CONTAINER_multihashmap_remove (op->demanded_hashes,
+                                            &ee->element_hash,
+                                            NULL))
+  {
+    /* We got something we didn't demand, since it's not in our map. */
+    GNUNET_break_op (0);
+    fail_union_operation (op);
+    return;
+  }
+
+  LOG (GNUNET_ERROR_TYPE_DEBUG,
+       "Got element (size %u, hash %s) from peer\n",
+       (unsigned int) element_size,
+       GNUNET_h2s (&ee->element_hash));
+
+  GNUNET_STATISTICS_update (_GSS_statistics,
+                            "# received elements",
+                            1,
+                            GNUNET_NO);
+  GNUNET_STATISTICS_update (_GSS_statistics,
+                            "# exchanged elements",
+                            1,
+                            GNUNET_NO);
+
+  op->received_total++;
+
+  ke = op_get_element (op,
+                       &ee->element_hash);
+  if (NULL != ke)
+  {
+    /* Got repeated element.  Should not happen since
+     * we track demands. */
+    GNUNET_STATISTICS_update (_GSS_statistics,
+                              "# repeated elements",
+                              1,
+                              GNUNET_NO);
+    ke->received = GNUNET_YES;
+    GNUNET_free (ee);
+  }
+  else
+  {
+    LOG (GNUNET_ERROR_TYPE_DEBUG,
+         "Registering new element from remote peer\n");
+    op->received_fresh++;
+    op_register_element (op, ee, GNUNET_YES);
+    /* only send results immediately if the client wants it */
+    send_client_element (op,
+                         &ee->element,
+                         GNUNET_SETU_STATUS_ADD_LOCAL);
+  }
+
+  if ((op->received_total > 8) &&
+      (op->received_fresh < op->received_total / 3))
+  {
+    /* The other peer gave us lots of old elements, there's something wrong. */
+    GNUNET_break_op (0);
+    fail_union_operation (op);
+    return;
+  }
+  GNUNET_CADET_receive_done (op->channel);
+  maybe_finish (op);
+}
+
+
+/**
+ * Check a full element message from a remote peer.
+ *
+ * @param cls the union operation
+ * @param emsg the message
+ */
+static int
+check_union_p2p_full_element (void *cls,
+                              const struct GNUNET_SETU_ElementMessage *emsg)
+{
+  struct Operation *op = cls;
+
+  (void) op;
+  // FIXME: check that we expect full elements here?
+  return GNUNET_OK;
+}
+
+
+/**
+ * Handle an element message from a remote peer.
+ *
+ * @param cls the union operation
+ * @param emsg the message
+ */
+static void
+handle_union_p2p_full_element (void *cls,
+                               const struct GNUNET_SETU_ElementMessage *emsg)
+{
+  struct Operation *op = cls;
+  struct ElementEntry *ee;
+  struct KeyEntry *ke;
+  uint16_t element_size;
+
+  element_size = ntohs (emsg->header.size)
+                 - sizeof(struct GNUNET_SETU_ElementMessage);
+  ee = GNUNET_malloc (sizeof(struct ElementEntry) + element_size);
+  GNUNET_memcpy (&ee[1], &emsg[1], element_size);
+  ee->element.size = element_size;
+  ee->element.data = &ee[1];
+  ee->element.element_type = ntohs (emsg->element_type);
+  ee->remote = GNUNET_YES;
+  GNUNET_SETU_element_hash (&ee->element,
+                            &ee->element_hash);
+  LOG (GNUNET_ERROR_TYPE_DEBUG,
+       "Got element (full diff, size %u, hash %s) from peer\n",
+       (unsigned int) element_size,
+       GNUNET_h2s (&ee->element_hash));
+
+  GNUNET_STATISTICS_update (_GSS_statistics,
+                            "# received elements",
+                            1,
+                            GNUNET_NO);
+  GNUNET_STATISTICS_update (_GSS_statistics,
+                            "# exchanged elements",
+                            1,
+                            GNUNET_NO);
+
+  op->received_total++;
+
+  ke = op_get_element (op,
+                       &ee->element_hash);
+  if (NULL != ke)
+  {
+    /* Got repeated element.  Should not happen since
+     * we track demands. */
+    GNUNET_STATISTICS_update (_GSS_statistics,
+                              "# repeated elements",
+                              1,
+                              GNUNET_NO);
+    ke->received = GNUNET_YES;
+    GNUNET_free (ee);
+  }
+  else
+  {
+    LOG (GNUNET_ERROR_TYPE_DEBUG,
+         "Registering new element from remote peer\n");
+    op->received_fresh++;
+    op_register_element (op, ee, GNUNET_YES);
+    /* only send results immediately if the client wants it */
+    send_client_element (op,
+                         &ee->element,
+                         GNUNET_SETU_STATUS_ADD_LOCAL);
+  }
+
+  if ((GNUNET_YES == op->byzantine) &&
+      (op->received_total > 384 + op->received_fresh * 4) &&
+      (op->received_fresh < op->received_total / 6))
+  {
+    /* The other peer gave us lots of old elements, there's something wrong. */
+    LOG (GNUNET_ERROR_TYPE_ERROR,
+         "Other peer sent only %llu/%llu fresh elements, failing operation\n",
+         (unsigned long long) op->received_fresh,
+         (unsigned long long) op->received_total);
+    GNUNET_break_op (0);
+    fail_union_operation (op);
+    return;
+  }
+  GNUNET_CADET_receive_done (op->channel);
+}
+
+
+/**
+ * Send offers (for GNUNET_Hash-es) in response
+ * to inquiries (for IBF_Key-s).
+ *
+ * @param cls the union operation
+ * @param msg the message
+ */
+static int
+check_union_p2p_inquiry (void *cls,
+                         const struct InquiryMessage *msg)
+{
+  struct Operation *op = cls;
+  unsigned int num_keys;
+
+  if (op->phase != PHASE_INVENTORY_PASSIVE)
+  {
+    GNUNET_break_op (0);
+    return GNUNET_SYSERR;
+  }
+  num_keys = (ntohs (msg->header.size) - sizeof(struct InquiryMessage))
+             / sizeof(struct IBF_Key);
+  if ((ntohs (msg->header.size) - sizeof(struct InquiryMessage))
+      != num_keys * sizeof(struct IBF_Key))
+  {
+    GNUNET_break_op (0);
+    return GNUNET_SYSERR;
+  }
+  return GNUNET_OK;
+}
+
+
+/**
+ * Send offers (for GNUNET_Hash-es) in response to inquiries (for IBF_Key-s).
+ *
+ * @param cls the union operation
+ * @param msg the message
+ */
+static void
+handle_union_p2p_inquiry (void *cls,
+                          const struct InquiryMessage *msg)
+{
+  struct Operation *op = cls;
+  const struct IBF_Key *ibf_key;
+  unsigned int num_keys;
+
+  LOG (GNUNET_ERROR_TYPE_DEBUG,
+       "Received union inquiry\n");
+  num_keys = (ntohs (msg->header.size) - sizeof(struct InquiryMessage))
+             / sizeof(struct IBF_Key);
+  ibf_key = (const struct IBF_Key *) &msg[1];
+  while (0 != num_keys--)
+  {
+    struct IBF_Key unsalted_key;
+
+    unsalt_key (ibf_key,
+                ntohl (msg->salt),
+                &unsalted_key);
+    send_offers_for_key (op,
+                         unsalted_key);
+    ibf_key++;
+  }
+  GNUNET_CADET_receive_done (op->channel);
+}
+
+
+/**
+ * Iterator over hash map entries, called to destroy the linked list of
+ * colliding ibf key entries.
+ *
+ * @param cls closure
+ * @param key current key code
+ * @param value value in the hash map
+ * @return #GNUNET_YES if we should continue to iterate,
+ *         #GNUNET_NO if not.
+ */
+static int
+send_missing_full_elements_iter (void *cls,
+                                 uint32_t key,
+                                 void *value)
+{
+  struct Operation *op = cls;
+  struct KeyEntry *ke = value;
+  struct GNUNET_MQ_Envelope *ev;
+  struct GNUNET_SETU_ElementMessage *emsg;
+  struct ElementEntry *ee = ke->element;
+
+  if (GNUNET_YES == ke->received)
+    return GNUNET_YES;
+  ev = GNUNET_MQ_msg_extra (emsg,
+                            ee->element.size,
+                            GNUNET_MESSAGE_TYPE_SETU_P2P_FULL_ELEMENT);
+  GNUNET_memcpy (&emsg[1],
+                 ee->element.data,
+                 ee->element.size);
+  emsg->element_type = htons (ee->element.element_type);
+  GNUNET_MQ_send (op->mq,
+                  ev);
+  return GNUNET_YES;
+}
+
+
+/**
+ * Handle a request for full set transmission.
+ *
+ * @parem cls closure, a set union operation
+ * @param mh the demand message
+ */
+static void
+handle_union_p2p_request_full (void *cls,
+                               const struct GNUNET_MessageHeader *mh)
+{
+  struct Operation *op = cls;
+
+  LOG (GNUNET_ERROR_TYPE_DEBUG,
+       "Received request for full set transmission\n");
+  if (PHASE_EXPECT_IBF != op->phase)
+  {
+    GNUNET_break_op (0);
+    fail_union_operation (op);
+    return;
+  }
+
+  // FIXME: we need to check that our set is larger than the
+  // byzantine_lower_bound by some threshold
+  send_full_set (op);
+  GNUNET_CADET_receive_done (op->channel);
+}
+
+
+/**
+ * Handle a "full done" message.
+ *
+ * @parem cls closure, a set union operation
+ * @param mh the demand message
+ */
+static void
+handle_union_p2p_full_done (void *cls,
+                            const struct GNUNET_MessageHeader *mh)
+{
+  struct Operation *op = cls;
+
+  switch (op->phase)
+  {
+  case PHASE_EXPECT_IBF:
+    {
+      struct GNUNET_MQ_Envelope *ev;
+
+      LOG (GNUNET_ERROR_TYPE_DEBUG,
+           "got FULL DONE, sending elements that other peer is missing\n");
+
+      /* send all the elements that did not come from the remote peer */
+      GNUNET_CONTAINER_multihashmap32_iterate (op->key_to_element,
+                                               &send_missing_full_elements_iter,
+                                               op);
+      ev = GNUNET_MQ_msg_header (GNUNET_MESSAGE_TYPE_SETU_P2P_FULL_DONE);
+      GNUNET_MQ_send (op->mq,
+                      ev);
+      op->phase = PHASE_DONE;
+      /* we now wait until the other peer sends us the OVER message*/
+    }
+    break;
+
+  case PHASE_FULL_SENDING:
+    {
+      LOG (GNUNET_ERROR_TYPE_DEBUG,
+           "got FULL DONE, finishing\n");
+      /* We sent the full set, and got the response for that.  We're done. */
+      op->phase = PHASE_DONE;
+      GNUNET_CADET_receive_done (op->channel);
+      send_client_done (op);
+      _GSS_operation_destroy2 (op);
+      return;
+    }
+    break;
+
+  default:
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                "Handle full done phase is %u\n",
+                (unsigned) op->phase);
+    GNUNET_break_op (0);
+    fail_union_operation (op);
+    return;
+  }
+  GNUNET_CADET_receive_done (op->channel);
+}
+
+
+/**
+ * Check a demand by the other peer for elements based on a list
+ * of `struct GNUNET_HashCode`s.
+ *
+ * @parem cls closure, a set union operation
+ * @param mh the demand message
+ * @return #GNUNET_OK if @a mh is well-formed
+ */
+static int
+check_union_p2p_demand (void *cls,
+                        const struct GNUNET_MessageHeader *mh)
+{
+  struct Operation *op = cls;
+  unsigned int num_hashes;
+
+  (void) op;
+  num_hashes = (ntohs (mh->size) - sizeof(struct GNUNET_MessageHeader))
+               / sizeof(struct GNUNET_HashCode);
+  if ((ntohs (mh->size) - sizeof(struct GNUNET_MessageHeader))
+      != num_hashes * sizeof(struct GNUNET_HashCode))
+  {
+    GNUNET_break_op (0);
+    return GNUNET_SYSERR;
+  }
+  return GNUNET_OK;
+}
+
+
+/**
+ * Handle a demand by the other peer for elements based on a list
+ * of `struct GNUNET_HashCode`s.
+ *
+ * @parem cls closure, a set union operation
+ * @param mh the demand message
+ */
+static void
+handle_union_p2p_demand (void *cls,
+                         const struct GNUNET_MessageHeader *mh)
+{
+  struct Operation *op = cls;
+  struct ElementEntry *ee;
+  struct GNUNET_SETU_ElementMessage *emsg;
+  const struct GNUNET_HashCode *hash;
+  unsigned int num_hashes;
+  struct GNUNET_MQ_Envelope *ev;
+
+  num_hashes = (ntohs (mh->size) - sizeof(struct GNUNET_MessageHeader))
+               / sizeof(struct GNUNET_HashCode);
+  for (hash = (const struct GNUNET_HashCode *) &mh[1];
+       num_hashes > 0;
+       hash++, num_hashes--)
+  {
+    ee = GNUNET_CONTAINER_multihashmap_get (op->set->content->elements,
+                                            hash);
+    if (NULL == ee)
+    {
+      /* Demand for non-existing element. */
+      GNUNET_break_op (0);
+      fail_union_operation (op);
+      return;
+    }
+    if (GNUNET_NO == _GSS_is_element_of_operation (ee, op))
+    {
+      /* Probably confused lazily copied sets. */
+      GNUNET_break_op (0);
+      fail_union_operation (op);
+      return;
+    }
+    ev = GNUNET_MQ_msg_extra (emsg,
+                              ee->element.size,
+                              GNUNET_MESSAGE_TYPE_SETU_P2P_ELEMENTS);
+    GNUNET_memcpy (&emsg[1],
+                   ee->element.data,
+                   ee->element.size);
+    emsg->reserved = htons (0);
+    emsg->element_type = htons (ee->element.element_type);
+    LOG (GNUNET_ERROR_TYPE_DEBUG,
+         "[OP %x] Sending demanded element (size %u, hash %s) to peer\n",
+         (void *) op,
+         (unsigned int) ee->element.size,
+         GNUNET_h2s (&ee->element_hash));
+    GNUNET_MQ_send (op->mq, ev);
+    GNUNET_STATISTICS_update (_GSS_statistics,
+                              "# exchanged elements",
+                              1,
+                              GNUNET_NO);
+    if (op->symmetric)
+      send_client_element (op,
+                           &ee->element,
+                           GNUNET_SET_STATUS_ADD_REMOTE);
+  }
+  GNUNET_CADET_receive_done (op->channel);
+}
+
+
+/**
+ * Check offer (of `struct GNUNET_HashCode`s).
+ *
+ * @param cls the union operation
+ * @param mh the message
+ * @return #GNUNET_OK if @a mh is well-formed
+ */
+static int
+check_union_p2p_offer (void *cls,
+                       const struct GNUNET_MessageHeader *mh)
+{
+  struct Operation *op = cls;
+  unsigned int num_hashes;
+
+  /* look up elements and send them */
+  if ((op->phase != PHASE_INVENTORY_PASSIVE) &&
+      (op->phase != PHASE_INVENTORY_ACTIVE))
+  {
+    GNUNET_break_op (0);
+    return GNUNET_SYSERR;
+  }
+  num_hashes = (ntohs (mh->size) - sizeof(struct GNUNET_MessageHeader))
+               / sizeof(struct GNUNET_HashCode);
+  if ((ntohs (mh->size) - sizeof(struct GNUNET_MessageHeader)) !=
+      num_hashes * sizeof(struct GNUNET_HashCode))
+  {
+    GNUNET_break_op (0);
+    return GNUNET_SYSERR;
+  }
+  return GNUNET_OK;
+}
+
+
+/**
+ * Handle offers (of `struct GNUNET_HashCode`s) and
+ * respond with demands (of `struct GNUNET_HashCode`s).
+ *
+ * @param cls the union operation
+ * @param mh the message
+ */
+static void
+handle_union_p2p_offer (void *cls,
+                        const struct GNUNET_MessageHeader *mh)
+{
+  struct Operation *op = cls;
+  const struct GNUNET_HashCode *hash;
+  unsigned int num_hashes;
+
+  num_hashes = (ntohs (mh->size) - sizeof(struct GNUNET_MessageHeader))
+               / sizeof(struct GNUNET_HashCode);
+  for (hash = (const struct GNUNET_HashCode *) &mh[1];
+       num_hashes > 0;
+       hash++, num_hashes--)
+  {
+    struct ElementEntry *ee;
+    struct GNUNET_MessageHeader *demands;
+    struct GNUNET_MQ_Envelope *ev;
+
+    ee = GNUNET_CONTAINER_multihashmap_get (op->set->content->elements,
+                                            hash);
+    if (NULL != ee)
+      if (GNUNET_YES == _GSS_is_element_of_operation (ee, op))
+        continue;
+
+    if (GNUNET_YES ==
+        GNUNET_CONTAINER_multihashmap_contains (op->demanded_hashes,
+                                                hash))
+    {
+      LOG (GNUNET_ERROR_TYPE_DEBUG,
+           "Skipped sending duplicate demand\n");
+      continue;
+    }
+
+    GNUNET_assert (GNUNET_OK ==
+                   GNUNET_CONTAINER_multihashmap_put (
+                     op->demanded_hashes,
+                     hash,
+                     NULL,
+                     GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST));
+
+    LOG (GNUNET_ERROR_TYPE_DEBUG,
+         "[OP %x] Requesting element (hash %s)\n",
+         (void *) op, GNUNET_h2s (hash));
+    ev = GNUNET_MQ_msg_header_extra (demands,
+                                     sizeof(struct GNUNET_HashCode),
+                                     GNUNET_MESSAGE_TYPE_SETU_P2P_DEMAND);
+    GNUNET_memcpy (&demands[1],
+                   hash,
+                   sizeof(struct GNUNET_HashCode));
+    GNUNET_MQ_send (op->mq, ev);
+  }
+  GNUNET_CADET_receive_done (op->channel);
+}
+
+
+/**
+ * Handle a done message from a remote peer
+ *
+ * @param cls the union operation
+ * @param mh the message
+ */
+static void
+handle_union_p2p_done (void *cls,
+                       const struct GNUNET_MessageHeader *mh)
+{
+  struct Operation *op = cls;
+
+  switch (op->phase)
+  {
+  case PHASE_INVENTORY_PASSIVE:
+    /* We got all requests, but still have to send our elements in response. */
+    op->phase = PHASE_FINISH_WAITING;
+    LOG (GNUNET_ERROR_TYPE_DEBUG,
+         "got DONE (as passive partner), waiting for our demands to be satisfied\n");
+    /* The active peer is done sending offers
+     * and inquiries.  This means that all
+     * our responses to that (demands and offers)
+     * must be in flight (queued or in mesh).
+     *
+     * We should notify the active peer once
+     * all our demands are satisfied, so that the active
+     * peer can quit if we gave it everything.
+     */GNUNET_CADET_receive_done (op->channel);
+    maybe_finish (op);
+    return;
+  case PHASE_INVENTORY_ACTIVE:
+    LOG (GNUNET_ERROR_TYPE_DEBUG,
+         "got DONE (as active partner), waiting to finish\n");
+    /* All demands of the other peer are satisfied,
+     * and we processed all offers, thus we know
+     * exactly what our demands must be.
+     *
+     * We'll close the channel
+     * to the other peer once our demands are met.
+     */op->phase = PHASE_FINISH_CLOSING;
+    GNUNET_CADET_receive_done (op->channel);
+    maybe_finish (op);
+    return;
+  default:
+    GNUNET_break_op (0);
+    fail_union_operation (op);
+    return;
+  }
+}
+
+
+/**
+ * Handle a over message from a remote peer
+ *
+ * @param cls the union operation
+ * @param mh the message
+ */
+static void
+handle_union_p2p_over (void *cls,
+                       const struct GNUNET_MessageHeader *mh)
+{
+  send_client_done (cls);
+}
+
+
+/**
+ * Get the incoming socket associated with the given id.
+ *
+ * @param listener the listener to look in
+ * @param id id to look for
+ * @return the incoming socket associated with the id,
+ *         or NULL if there is none
+ */
+static struct Operation *
+get_incoming (uint32_t id)
+{
+  for (struct Listener *listener = listener_head;
+       NULL != listener;
+       listener = listener->next)
+  {
+    for (struct Operation *op = listener->op_head;
+         NULL != op;
+         op = op->next)
+      if (op->suggest_id == id)
+        return op;
+  }
+  return NULL;
+}
+
+
+/**
+ * Callback called when a client connects to the service.
+ *
+ * @param cls closure for the service
+ * @param c the new client that connected to the service
+ * @param mq the message queue used to send messages to the client
+ * @return @a `struct ClientState`
+ */
+static void *
+client_connect_cb (void *cls,
+                   struct GNUNET_SERVICE_Client *c,
+                   struct GNUNET_MQ_Handle *mq)
+{
+  struct ClientState *cs;
+
+  num_clients++;
+  cs = GNUNET_new (struct ClientState);
+  cs->client = c;
+  cs->mq = mq;
+  return cs;
+}
+
+
+/**
+ * Iterator over hash map entries to free element entries.
+ *
+ * @param cls closure
+ * @param key current key code
+ * @param value a `struct ElementEntry *` to be free'd
+ * @return #GNUNET_YES (continue to iterate)
+ */
+static int
+destroy_elements_iterator (void *cls,
+                           const struct GNUNET_HashCode *key,
+                           void *value)
+{
+  struct ElementEntry *ee = value;
+
+  GNUNET_free (ee);
+  return GNUNET_YES;
+}
+
+
+/**
+ * Clean up after a client has disconnected
+ *
+ * @param cls closure, unused
+ * @param client the client to clean up after
+ * @param internal_cls the `struct ClientState`
+ */
+static void
+client_disconnect_cb (void *cls,
+                      struct GNUNET_SERVICE_Client *client,
+                      void *internal_cls)
+{
+  struct ClientState *cs = internal_cls;
+  struct Operation *op;
+  struct Listener *listener;
+  struct Set *set;
+
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "Client disconnected, cleaning up\n");
+  if (NULL != (set = cs->set))
+  {
+    struct SetContent *content = set->content;
+
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                "Destroying client's set\n");
+    /* Destroy pending set operations */
+    while (NULL != set->ops_head)
+      _GSS_operation_destroy (set->ops_head);
+
+    /* Destroy operation-specific state */
+    if (NULL != set->se)
+    {
+      strata_estimator_destroy (set->se);
+      set->se = NULL;
+    }
+    /* free set content (or at least decrement RC) */
+    set->content = NULL;
+    GNUNET_assert (0 != content->refcount);
+    content->refcount--;
+    if (0 == content->refcount)
+    {
+      GNUNET_assert (NULL != content->elements);
+      GNUNET_CONTAINER_multihashmap_iterate (content->elements,
+                                             &destroy_elements_iterator,
+                                             NULL);
+      GNUNET_CONTAINER_multihashmap_destroy (content->elements);
+      content->elements = NULL;
+      GNUNET_free (content);
+    }
+    GNUNET_free (set);
+  }
+
+  if (NULL != (listener = cs->listener))
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                "Destroying client's listener\n");
+    GNUNET_CADET_close_port (listener->open_port);
+    listener->open_port = NULL;
+    while (NULL != (op = listener->op_head))
+    {
+      GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+                  "Destroying incoming operation `%u' from peer `%s'\n",
+                  (unsigned int) op->client_request_id,
+                  GNUNET_i2s (&op->peer));
+      incoming_destroy (op);
+    }
+    GNUNET_CONTAINER_DLL_remove (listener_head,
+                                 listener_tail,
+                                 listener);
+    GNUNET_free (listener);
+  }
+  GNUNET_free (cs);
+  num_clients--;
+  if ( (GNUNET_YES == in_shutdown) &&
+       (0 == num_clients) )
+  {
+    if (NULL != cadet)
+    {
+      GNUNET_CADET_disconnect (cadet);
+      cadet = NULL;
+    }
+  }
+}
+
+
+/**
+ * Check a request for a set operation from another peer.
+ *
+ * @param cls the operation state
+ * @param msg the received message
+ * @return #GNUNET_OK if the channel should be kept alive,
+ *         #GNUNET_SYSERR to destroy the channel
+ */
+static int
+check_incoming_msg (void *cls,
+                    const struct OperationRequestMessage *msg)
+{
+  struct Operation *op = cls;
+  struct Listener *listener = op->listener;
+  const struct GNUNET_MessageHeader *nested_context;
+
+  /* double operation request */
+  if (0 != op->suggest_id)
+  {
+    GNUNET_break_op (0);
+    return GNUNET_SYSERR;
+  }
+  /* This should be equivalent to the previous condition, but can't hurt to check twice */
+  if (NULL == listener)
+  {
+    GNUNET_break (0);
+    return GNUNET_SYSERR;
+  }
+  nested_context = GNUNET_MQ_extract_nested_mh (msg);
+  if ((NULL != nested_context) &&
+      (ntohs (nested_context->size) > GNUNET_SETU_CONTEXT_MESSAGE_MAX_SIZE))
+  {
+    GNUNET_break_op (0);
+    return GNUNET_SYSERR;
+  }
+  return GNUNET_OK;
+}
+
+
+/**
+ * Handle a request for a set operation from another peer.  Checks if we
+ * have a listener waiting for such a request (and in that case initiates
+ * asking the listener about accepting the connection). If no listener
+ * is waiting, we queue the operation request in hope that a listener
+ * shows up soon (before timeout).
+ *
+ * This msg is expected as the first and only msg handled through the
+ * non-operation bound virtual table, acceptance of this operation replaces
+ * our virtual table and subsequent msgs would be routed differently (as
+ * we then know what type of operation this is).
+ *
+ * @param cls the operation state
+ * @param msg the received message
+ * @return #GNUNET_OK if the channel should be kept alive,
+ *         #GNUNET_SYSERR to destroy the channel
+ */
+static void
+handle_incoming_msg (void *cls,
+                     const struct OperationRequestMessage *msg)
+{
+  struct Operation *op = cls;
+  struct Listener *listener = op->listener;
+  const struct GNUNET_MessageHeader *nested_context;
+  struct GNUNET_MQ_Envelope *env;
+  struct GNUNET_SETU_RequestMessage *cmsg;
+
+  nested_context = GNUNET_MQ_extract_nested_mh (msg);
+  /* Make a copy of the nested_context (application-specific context
+     information that is opaque to set) so we can pass it to the
+     listener later on */
+  if (NULL != nested_context)
+    op->context_msg = GNUNET_copy_message (nested_context);
+  op->remote_element_count = ntohl (msg->element_count);
+  GNUNET_log (
+    GNUNET_ERROR_TYPE_DEBUG,
+    "Received P2P operation request (port %s) for active listener\n",
+    GNUNET_h2s (&op->listener->app_id));
+  GNUNET_assert (0 == op->suggest_id);
+  if (0 == suggest_id)
+    suggest_id++;
+  op->suggest_id = suggest_id++;
+  GNUNET_assert (NULL != op->timeout_task);
+  GNUNET_SCHEDULER_cancel (op->timeout_task);
+  op->timeout_task = NULL;
+  env = GNUNET_MQ_msg_nested_mh (cmsg,
+                                 GNUNET_MESSAGE_TYPE_SETU_REQUEST,
+                                 op->context_msg);
+  GNUNET_log (
+    GNUNET_ERROR_TYPE_DEBUG,
+    "Suggesting incoming request with accept id %u to listener %p of client %p\n",
+    op->suggest_id,
+    listener,
+    listener->cs);
+  cmsg->accept_id = htonl (op->suggest_id);
+  cmsg->peer_id = op->peer;
+  GNUNET_MQ_send (listener->cs->mq,
+                  env);
+  /* NOTE: GNUNET_CADET_receive_done() will be called in
+   #handle_client_accept() */
+}
+
+
+/**
+ * Called when a client wants to create a new set.  This is typically
+ * the first request from a client, and includes the type of set
+ * operation to be performed.
+ *
+ * @param cls client that sent the message
+ * @param m message sent by the client
+ */
+static void
+handle_client_create_set (void *cls,
+                          const struct GNUNET_SETU_CreateMessage *msg)
+{
+  struct ClientState *cs = cls;
+  struct Set *set;
+
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "Client created new set for union operation\n");
+  if (NULL != cs->set)
+  {
+    /* There can only be one set per client */
+    GNUNET_break (0);
+    GNUNET_SERVICE_client_drop (cs->client);
+    return;
+  }
+  set = GNUNET_new (struct Set);
+  {
+    struct StrataEstimator *se;
+
+    se = strata_estimator_create (SE_STRATA_COUNT,
+                                  SE_IBF_SIZE,
+                                  SE_IBF_HASH_NUM);
+    if (NULL == se)
+    {
+      GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                  "Failed to allocate strata estimator\n");
+      GNUNET_free (set);
+      GNUNET_SERVICE_client_drop (cs->client);
+      return;
+    }
+    set->se = se;
+  }
+  set->content = GNUNET_new (struct SetContent);
+  set->content->refcount = 1;
+  set->content->elements = GNUNET_CONTAINER_multihashmap_create (1,
+                                                                 GNUNET_YES);
+  set->cs = cs;
+  cs->set = set;
+  GNUNET_SERVICE_client_continue (cs->client);
+}
+
+
+/**
+ * Timeout happens iff:
+ *  - we suggested an operation to our listener,
+ *    but did not receive a response in time
+ *  - we got the channel from a peer but no #GNUNET_MESSAGE_TYPE_SETU_P2P_OPERATION_REQUEST
+ *
+ * @param cls channel context
+ * @param tc context information (why was this task triggered now)
+ */
+static void
+incoming_timeout_cb (void *cls)
+{
+  struct Operation *op = cls;
+
+  op->timeout_task = NULL;
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "Remote peer's incoming request timed out\n");
+  incoming_destroy (op);
+}
+
+
+/**
+ * Method called whenever another peer has added us to a channel the
+ * other peer initiated.  Only called (once) upon reception of data
+ * from a channel we listen on.
+ *
+ * The channel context represents the operation itself and gets added
+ * to a DLL, from where it gets looked up when our local listener
+ * client responds to a proposed/suggested operation or connects and
+ * associates with this operation.
+ *
+ * @param cls closure
+ * @param channel new handle to the channel
+ * @param source peer that started the channel
+ * @return initial channel context for the channel
+ *         returns NULL on error
+ */
+static void *
+channel_new_cb (void *cls,
+                struct GNUNET_CADET_Channel *channel,
+                const struct GNUNET_PeerIdentity *source)
+{
+  struct Listener *listener = cls;
+  struct Operation *op;
+
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "New incoming channel\n");
+  op = GNUNET_new (struct Operation);
+  op->listener = listener;
+  op->peer = *source;
+  op->channel = channel;
+  op->mq = GNUNET_CADET_get_mq (op->channel);
+  op->salt = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_NONCE,
+                                       UINT32_MAX);
+  op->timeout_task = GNUNET_SCHEDULER_add_delayed (INCOMING_CHANNEL_TIMEOUT,
+                                                   &incoming_timeout_cb,
+                                                   op);
+  GNUNET_CONTAINER_DLL_insert (listener->op_head,
+                               listener->op_tail,
+                               op);
+  return op;
+}
+
+
+/**
+ * Function called whenever a channel is destroyed.  Should clean up
+ * any associated state.  It must NOT call
+ * GNUNET_CADET_channel_destroy() on the channel.
+ *
+ * The peer_disconnect function is part of a a virtual table set initially either
+ * when a peer creates a new channel with us, or once we create
+ * a new channel ourselves (evaluate).
+ *
+ * Once we know the exact type of operation (union/intersection), the vt is
+ * replaced with an operation specific instance (_GSS_[op]_vt).
+ *
+ * @param channel_ctx place where local state associated
+ *                   with the channel is stored
+ * @param channel connection to the other end (henceforth invalid)
+ */
+static void
+channel_end_cb (void *channel_ctx,
+                const struct GNUNET_CADET_Channel *channel)
+{
+  struct Operation *op = channel_ctx;
+
+  op->channel = NULL;
+  _GSS_operation_destroy2 (op);
+}
+
+
+/**
+ * Function called whenever an MQ-channel's transmission window size changes.
+ *
+ * The first callback in an outgoing channel will be with a non-zero value
+ * and will mean the channel is connected to the destination.
+ *
+ * For an incoming channel it will be called immediately after the
+ * #GNUNET_CADET_ConnectEventHandler, also with a non-zero value.
+ *
+ * @param cls Channel closure.
+ * @param channel Connection to the other end (henceforth invalid).
+ * @param window_size New window size. If the is more messages than buffer size
+ *                    this value will be negative..
+ */
+static void
+channel_window_cb (void *cls,
+                   const struct GNUNET_CADET_Channel *channel,
+                   int window_size)
+{
+  /* FIXME: not implemented, we could do flow control here... */
+}
+
+
+/**
+ * Called when a client wants to create a new listener.
+ *
+ * @param cls client that sent the message
+ * @param msg message sent by the client
+ */
+static void
+handle_client_listen (void *cls,
+                      const struct GNUNET_SETU_ListenMessage *msg)
+{
+  struct ClientState *cs = cls;
+  struct GNUNET_MQ_MessageHandler cadet_handlers[] = {
+    GNUNET_MQ_hd_var_size (incoming_msg,
+                           GNUNET_MESSAGE_TYPE_SETU_P2P_OPERATION_REQUEST,
+                           struct OperationRequestMessage,
+                           NULL),
+    GNUNET_MQ_hd_var_size (union_p2p_ibf,
+                           GNUNET_MESSAGE_TYPE_SETU_P2P_IBF,
+                           struct IBFMessage,
+                           NULL),
+    GNUNET_MQ_hd_var_size (union_p2p_elements,
+                           GNUNET_MESSAGE_TYPE_SETU_P2P_ELEMENTS,
+                           struct GNUNET_SETU_ElementMessage,
+                           NULL),
+    GNUNET_MQ_hd_var_size (union_p2p_offer,
+                           GNUNET_MESSAGE_TYPE_SETU_P2P_OFFER,
+                           struct GNUNET_MessageHeader,
+                           NULL),
+    GNUNET_MQ_hd_var_size (union_p2p_inquiry,
+                           GNUNET_MESSAGE_TYPE_SETU_P2P_INQUIRY,
+                           struct InquiryMessage,
+                           NULL),
+    GNUNET_MQ_hd_var_size (union_p2p_demand,
+                           GNUNET_MESSAGE_TYPE_SETU_P2P_DEMAND,
+                           struct GNUNET_MessageHeader,
+                           NULL),
+    GNUNET_MQ_hd_fixed_size (union_p2p_done,
+                             GNUNET_MESSAGE_TYPE_SETU_P2P_DONE,
+                             struct GNUNET_MessageHeader,
+                             NULL),
+    GNUNET_MQ_hd_fixed_size (union_p2p_over,
+                             GNUNET_MESSAGE_TYPE_SETU_P2P_OVER,
+                             struct GNUNET_MessageHeader,
+                             NULL),
+    GNUNET_MQ_hd_fixed_size (union_p2p_full_done,
+                             GNUNET_MESSAGE_TYPE_SETU_P2P_FULL_DONE,
+                             struct GNUNET_MessageHeader,
+                             NULL),
+    GNUNET_MQ_hd_fixed_size (union_p2p_request_full,
+                             GNUNET_MESSAGE_TYPE_SETU_P2P_REQUEST_FULL,
+                             struct GNUNET_MessageHeader,
+                             NULL),
+    GNUNET_MQ_hd_var_size (union_p2p_strata_estimator,
+                           GNUNET_MESSAGE_TYPE_SETU_P2P_SE,
+                           struct StrataEstimatorMessage,
+                           NULL),
+    GNUNET_MQ_hd_var_size (union_p2p_strata_estimator,
+                           GNUNET_MESSAGE_TYPE_SETU_P2P_SEC,
+                           struct StrataEstimatorMessage,
+                           NULL),
+    GNUNET_MQ_hd_var_size (union_p2p_full_element,
+                           GNUNET_MESSAGE_TYPE_SETU_P2P_FULL_ELEMENT,
+                           struct GNUNET_SETU_ElementMessage,
+                           NULL),
+    GNUNET_MQ_handler_end ()
+  };
+  struct Listener *listener;
+
+  if (NULL != cs->listener)
+  {
+    /* max. one active listener per client! */
+    GNUNET_break (0);
+    GNUNET_SERVICE_client_drop (cs->client);
+    return;
+  }
+  listener = GNUNET_new (struct Listener);
+  listener->cs = cs;
+  cs->listener = listener;
+  listener->app_id = msg->app_id;
+  GNUNET_CONTAINER_DLL_insert (listener_head,
+                               listener_tail,
+                               listener);
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "New listener created (port %s)\n",
+              GNUNET_h2s (&listener->app_id));
+  listener->open_port = GNUNET_CADET_open_port (cadet,
+                                                &msg->app_id,
+                                                &channel_new_cb,
+                                                listener,
+                                                &channel_window_cb,
+                                                &channel_end_cb,
+                                                cadet_handlers);
+  GNUNET_SERVICE_client_continue (cs->client);
+}
+
+
+/**
+ * Called when the listening client rejects an operation
+ * request by another peer.
+ *
+ * @param cls client that sent the message
+ * @param msg message sent by the client
+ */
+static void
+handle_client_reject (void *cls,
+                      const struct GNUNET_SETU_RejectMessage *msg)
+{
+  struct ClientState *cs = cls;
+  struct Operation *op;
+
+  op = get_incoming (ntohl (msg->accept_reject_id));
+  if (NULL == op)
+  {
+    /* no matching incoming operation for this reject;
+       could be that the other peer already disconnected... */
+    GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+                "Client rejected unknown operation %u\n",
+                (unsigned int) ntohl (msg->accept_reject_id));
+    GNUNET_SERVICE_client_continue (cs->client);
+    return;
+  }
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "Peer request (app %s) rejected by client\n",
+              GNUNET_h2s (&cs->listener->app_id));
+  _GSS_operation_destroy2 (op);
+  GNUNET_SERVICE_client_continue (cs->client);
+}
+
+
+/**
+ * Called when a client wants to add or remove an element to a set it inhabits.
+ *
+ * @param cls client that sent the message
+ * @param msg message sent by the client
+ */
+static int
+check_client_set_add (void *cls,
+                      const struct GNUNET_SETU_ElementMessage *msg)
+{
+  /* NOTE: Technically, we should probably check with the
+     block library whether the element we are given is well-formed */
+  return GNUNET_OK;
+}
+
+
+/**
+ * Called when a client wants to add or remove an element to a set it inhabits.
+ *
+ * @param cls client that sent the message
+ * @param msg message sent by the client
+ */
+static void
+handle_client_set_add (void *cls,
+                       const struct GNUNET_SETU_ElementMessage *msg)
+{
+  struct ClientState *cs = cls;
+  struct Set *set;
+  struct GNUNET_SETU_Element el;
+  struct ElementEntry *ee;
+  struct GNUNET_HashCode hash;
+
+  if (NULL == (set = cs->set))
+  {
+    /* client without a set requested an operation */
+    GNUNET_break (0);
+    GNUNET_SERVICE_client_drop (cs->client);
+    return;
+  }
+  GNUNET_SERVICE_client_continue (cs->client);
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Executing mutation on set\n");
+  el.size = ntohs (msg->header.size) - sizeof(*msg);
+  el.data = &msg[1];
+  el.element_type = ntohs (msg->element_type);
+  GNUNET_SETU_element_hash (&el,
+                            &hash);
+  ee = GNUNET_CONTAINER_multihashmap_get (set->content->elements,
+                                          &hash);
+  if (NULL == ee)
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                "Client inserts element %s of size %u\n",
+                GNUNET_h2s (&hash),
+                el.size);
+    ee = GNUNET_malloc (el.size + sizeof(*ee));
+    ee->element.size = el.size;
+    GNUNET_memcpy (&ee[1], el.data, el.size);
+    ee->element.data = &ee[1];
+    ee->element.element_type = el.element_type;
+    ee->remote = GNUNET_NO;
+    ee->generation = set->current_generation;
+    ee->element_hash = hash;
+    GNUNET_break (GNUNET_YES ==
+                  GNUNET_CONTAINER_multihashmap_put (
+                    set->content->elements,
+                    &ee->element_hash,
+                    ee,
+                    GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
+  }
+  else
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                "Client inserted element %s of size %u twice (ignored)\n",
+                GNUNET_h2s (&hash),
+                el.size);
+    /* same element inserted twice */
+    return;
+  }
+  strata_estimator_insert (set->se,
+                           get_ibf_key (&ee->element_hash));
+}
+
+
+/**
+ * Advance the current generation of a set,
+ * adding exclusion ranges if necessary.
+ *
+ * @param set the set where we want to advance the generation
+ */
+static void
+advance_generation (struct Set *set)
+{
+  set->content->latest_generation++;
+  set->current_generation++;
+}
+
+
+/**
+ * Called when a client wants to initiate a set operation with another
+ * peer.  Initiates the CADET connection to the listener and sends the
+ * request.
+ *
+ * @param cls client that sent the message
+ * @param msg message sent by the client
+ * @return #GNUNET_OK if the message is well-formed
+ */
+static int
+check_client_evaluate (void *cls,
+                       const struct GNUNET_SETU_EvaluateMessage *msg)
+{
+  /* FIXME: suboptimal, even if the context below could be NULL,
+     there are malformed messages this does not check for... */
+  return GNUNET_OK;
+}
+
+
+/**
+ * Called when a client wants to initiate a set operation with another
+ * peer.  Initiates the CADET connection to the listener and sends the
+ * request.
+ *
+ * @param cls client that sent the message
+ * @param msg message sent by the client
+ */
+static void
+handle_client_evaluate (void *cls,
+                        const struct GNUNET_SETU_EvaluateMessage *msg)
+{
+  struct ClientState *cs = cls;
+  struct Operation *op = GNUNET_new (struct Operation);
+  const struct GNUNET_MQ_MessageHandler cadet_handlers[] = {
+    GNUNET_MQ_hd_var_size (incoming_msg,
+                           GNUNET_MESSAGE_TYPE_SETU_P2P_OPERATION_REQUEST,
+                           struct OperationRequestMessage,
+                           op),
+    GNUNET_MQ_hd_var_size (union_p2p_ibf,
+                           GNUNET_MESSAGE_TYPE_SETU_P2P_IBF,
+                           struct IBFMessage,
+                           op),
+    GNUNET_MQ_hd_var_size (union_p2p_elements,
+                           GNUNET_MESSAGE_TYPE_SETU_P2P_ELEMENTS,
+                           struct GNUNET_SETU_ElementMessage,
+                           op),
+    GNUNET_MQ_hd_var_size (union_p2p_offer,
+                           GNUNET_MESSAGE_TYPE_SETU_P2P_OFFER,
+                           struct GNUNET_MessageHeader,
+                           op),
+    GNUNET_MQ_hd_var_size (union_p2p_inquiry,
+                           GNUNET_MESSAGE_TYPE_SETU_P2P_INQUIRY,
+                           struct InquiryMessage,
+                           op),
+    GNUNET_MQ_hd_var_size (union_p2p_demand,
+                           GNUNET_MESSAGE_TYPE_SETU_P2P_DEMAND,
+                           struct GNUNET_MessageHeader,
+                           op),
+    GNUNET_MQ_hd_fixed_size (union_p2p_done,
+                             GNUNET_MESSAGE_TYPE_SETU_P2P_DONE,
+                             struct GNUNET_MessageHeader,
+                             op),
+    GNUNET_MQ_hd_fixed_size (union_p2p_over,
+                             GNUNET_MESSAGE_TYPE_SETU_P2P_OVER,
+                             struct GNUNET_MessageHeader,
+                             op),
+    GNUNET_MQ_hd_fixed_size (union_p2p_full_done,
+                             GNUNET_MESSAGE_TYPE_SETU_P2P_FULL_DONE,
+                             struct GNUNET_MessageHeader,
+                             op),
+    GNUNET_MQ_hd_fixed_size (union_p2p_request_full,
+                             GNUNET_MESSAGE_TYPE_SETU_P2P_REQUEST_FULL,
+                             struct GNUNET_MessageHeader,
+                             op),
+    GNUNET_MQ_hd_var_size (union_p2p_strata_estimator,
+                           GNUNET_MESSAGE_TYPE_SETU_P2P_SE,
+                           struct StrataEstimatorMessage,
+                           op),
+    GNUNET_MQ_hd_var_size (union_p2p_strata_estimator,
+                           GNUNET_MESSAGE_TYPE_SETU_P2P_SEC,
+                           struct StrataEstimatorMessage,
+                           op),
+    GNUNET_MQ_hd_var_size (union_p2p_full_element,
+                           GNUNET_MESSAGE_TYPE_SETU_P2P_FULL_ELEMENT,
+                           struct GNUNET_SETU_ElementMessage,
+                           op),
+    GNUNET_MQ_handler_end ()
+  };
+  struct Set *set;
+  const struct GNUNET_MessageHeader *context;
+
+  if (NULL == (set = cs->set))
+  {
+    GNUNET_break (0);
+    GNUNET_free (op);
+    GNUNET_SERVICE_client_drop (cs->client);
+    return;
+  }
+  op->salt = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_NONCE,
+                                       UINT32_MAX);
+  op->peer = msg->target_peer;
+  op->client_request_id = ntohl (msg->request_id);
+  op->byzantine = msg->byzantine;
+  op->byzantine_lower_bound = ntohl (msg->byzantine_lower_bound);
+  op->force_full = msg->force_full;
+  op->force_delta = msg->force_delta;
+  op->symmetric = msg->symmetric;
+  context = GNUNET_MQ_extract_nested_mh (msg);
+
+  /* Advance generation values, so that
+     mutations won't interfer with the running operation. */
+  op->set = set;
+  op->generation_created = set->current_generation;
+  advance_generation (set);
+  GNUNET_CONTAINER_DLL_insert (set->ops_head,
+                               set->ops_tail,
+                               op);
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "Creating new CADET channel to port %s for set union\n",
+              GNUNET_h2s (&msg->app_id));
+  op->channel = GNUNET_CADET_channel_create (cadet,
+                                             op,
+                                             &msg->target_peer,
+                                             &msg->app_id,
+                                             &channel_window_cb,
+                                             &channel_end_cb,
+                                             cadet_handlers);
+  op->mq = GNUNET_CADET_get_mq (op->channel);
+  {
+    struct GNUNET_MQ_Envelope *ev;
+    struct OperationRequestMessage *msg;
+
+    ev = GNUNET_MQ_msg_nested_mh (msg,
+                                  GNUNET_MESSAGE_TYPE_SETU_P2P_OPERATION_REQUEST,
+                                  context);
+    if (NULL == ev)
+    {
+      /* the context message is too large */
+      GNUNET_break (0);
+      GNUNET_SERVICE_client_drop (cs->client);
+      return;
+    }
+    op->demanded_hashes = GNUNET_CONTAINER_multihashmap_create (32,
+                                                                GNUNET_NO);
+    /* copy the current generation's strata estimator for this operation */
+    op->se = strata_estimator_dup (op->set->se);
+    /* we started the operation, thus we have to send the operation request */
+    op->phase = PHASE_EXPECT_SE;
+    op->salt_receive = op->salt_send = 42; // FIXME?????
+    LOG (GNUNET_ERROR_TYPE_DEBUG,
+         "Initiating union operation evaluation\n");
+    GNUNET_STATISTICS_update (_GSS_statistics,
+                              "# of total union operations",
+                              1,
+                              GNUNET_NO);
+    GNUNET_STATISTICS_update (_GSS_statistics,
+                              "# of initiated union operations",
+                              1,
+                              GNUNET_NO);
+    GNUNET_MQ_send (op->mq,
+                    ev);
+    if (NULL != context)
+      LOG (GNUNET_ERROR_TYPE_DEBUG,
+           "sent op request with context message\n");
+    else
+      LOG (GNUNET_ERROR_TYPE_DEBUG,
+           "sent op request without context message\n");
+    initialize_key_to_element (op);
+    op->initial_size = GNUNET_CONTAINER_multihashmap32_size (
+      op->key_to_element);
+
+  }
+  GNUNET_SERVICE_client_continue (cs->client);
+}
+
+
+/**
+ * Handle a request from the client to cancel a running set operation.
+ *
+ * @param cls the client
+ * @param msg the message
+ */
+static void
+handle_client_cancel (void *cls,
+                      const struct GNUNET_SETU_CancelMessage *msg)
+{
+  struct ClientState *cs = cls;
+  struct Set *set;
+  struct Operation *op;
+  int found;
+
+  if (NULL == (set = cs->set))
+  {
+    /* client without a set requested an operation */
+    GNUNET_break (0);
+    GNUNET_SERVICE_client_drop (cs->client);
+    return;
+  }
+  found = GNUNET_NO;
+  for (op = set->ops_head; NULL != op; op = op->next)
+  {
+    if (op->client_request_id == ntohl (msg->request_id))
+    {
+      found = GNUNET_YES;
+      break;
+    }
+  }
+  if (GNUNET_NO == found)
+  {
+    /* It may happen that the operation was already destroyed due to
+     * the other peer disconnecting.  The client may not know about this
+     * yet and try to cancel the (just barely non-existent) operation.
+     * So this is not a hard error.
+     *///
+    GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+                "Client canceled non-existent op %u\n",
+                (uint32_t) ntohl (msg->request_id));
+  }
+  else
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                "Client requested cancel for op %u\n",
+                (uint32_t) ntohl (msg->request_id));
+    _GSS_operation_destroy (op);
+  }
+  GNUNET_SERVICE_client_continue (cs->client);
+}
+
+
+/**
+ * Handle a request from the client to accept a set operation that
+ * came from a remote peer.  We forward the accept to the associated
+ * operation for handling
+ *
+ * @param cls the client
+ * @param msg the message
+ */
+static void
+handle_client_accept (void *cls,
+                      const struct GNUNET_SETU_AcceptMessage *msg)
+{
+  struct ClientState *cs = cls;
+  struct Set *set;
+  struct Operation *op;
+  struct GNUNET_SETU_ResultMessage *result_message;
+  struct GNUNET_MQ_Envelope *ev;
+  struct Listener *listener;
+
+  if (NULL == (set = cs->set))
+  {
+    /* client without a set requested to accept */
+    GNUNET_break (0);
+    GNUNET_SERVICE_client_drop (cs->client);
+    return;
+  }
+  op = get_incoming (ntohl (msg->accept_reject_id));
+  if (NULL == op)
+  {
+    /* It is not an error if the set op does not exist -- it may
+    * have been destroyed when the partner peer disconnected. */
+    GNUNET_log (
+      GNUNET_ERROR_TYPE_INFO,
+      "Client %p accepted request %u of listener %p that is no longer active\n",
+      cs,
+      ntohl (msg->accept_reject_id),
+      cs->listener);
+    ev = GNUNET_MQ_msg (result_message,
+                        GNUNET_MESSAGE_TYPE_SETU_RESULT);
+    result_message->request_id = msg->request_id;
+    result_message->result_status = htons (GNUNET_SETU_STATUS_FAILURE);
+    GNUNET_MQ_send (set->cs->mq, ev);
+    GNUNET_SERVICE_client_continue (cs->client);
+    return;
+  }
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "Client accepting request %u\n",
+              (uint32_t) ntohl (msg->accept_reject_id));
+  listener = op->listener;
+  op->listener = NULL;
+  GNUNET_CONTAINER_DLL_remove (listener->op_head,
+                               listener->op_tail,
+                               op);
+  op->set = set;
+  GNUNET_CONTAINER_DLL_insert (set->ops_head,
+                               set->ops_tail,
+                               op);
+  op->client_request_id = ntohl (msg->request_id);
+  op->byzantine = msg->byzantine;
+  op->byzantine_lower_bound = ntohl (msg->byzantine_lower_bound);
+  op->force_full = msg->force_full;
+  op->force_delta = msg->force_delta;
+  op->symmetric = msg->symmetric;
+
+  /* Advance generation values, so that future mutations do not
+     interfer with the running operation. */
+  op->generation_created = set->current_generation;
+  advance_generation (set);
+  GNUNET_assert (NULL == op->se);
+
+  LOG (GNUNET_ERROR_TYPE_DEBUG,
+       "accepting set union operation\n");
+  GNUNET_STATISTICS_update (_GSS_statistics,
+                            "# of accepted union operations",
+                            1,
+                            GNUNET_NO);
+  GNUNET_STATISTICS_update (_GSS_statistics,
+                            "# of total union operations",
+                            1,
+                            GNUNET_NO);
+  {
+    const struct StrataEstimator *se;
+    struct GNUNET_MQ_Envelope *ev;
+    struct StrataEstimatorMessage *strata_msg;
+    char *buf;
+    size_t len;
+    uint16_t type;
+
+    op->se = strata_estimator_dup (op->set->se);
+    op->demanded_hashes = GNUNET_CONTAINER_multihashmap_create (32,
+                                                                GNUNET_NO);
+    op->salt_receive = op->salt_send = 42; // FIXME?????
+    initialize_key_to_element (op);
+    op->initial_size = GNUNET_CONTAINER_multihashmap32_size (
+      op->key_to_element);
+
+    /* kick off the operation */
+    se = op->se;
+    buf = GNUNET_malloc (se->strata_count * IBF_BUCKET_SIZE * se->ibf_size);
+    len = strata_estimator_write (se,
+                                  buf);
+    if (len < se->strata_count * IBF_BUCKET_SIZE * se->ibf_size)
+      type = GNUNET_MESSAGE_TYPE_SETU_P2P_SEC;
+    else
+      type = GNUNET_MESSAGE_TYPE_SETU_P2P_SE;
+    ev = GNUNET_MQ_msg_extra (strata_msg,
+                              len,
+                              type);
+    GNUNET_memcpy (&strata_msg[1],
+                   buf,
+                   len);
+    GNUNET_free (buf);
+    strata_msg->set_size
+      = GNUNET_htonll (GNUNET_CONTAINER_multihashmap_size (
+                         op->set->content->elements));
+    GNUNET_MQ_send (op->mq,
+                    ev);
+    op->phase = PHASE_EXPECT_IBF;
+  }
+  /* Now allow CADET to continue, as we did not do this in
+   #handle_incoming_msg (as we wanted to first see if the
+     local client would accept the request). */
+  GNUNET_CADET_receive_done (op->channel);
+  GNUNET_SERVICE_client_continue (cs->client);
+}
+
+
+/**
+ * Called to clean up, after a shutdown has been requested.
+ *
+ * @param cls closure, NULL
+ */
+static void
+shutdown_task (void *cls)
+{
+  /* Delay actual shutdown to allow service to disconnect clients */
+  in_shutdown = GNUNET_YES;
+  if (0 == num_clients)
+  {
+    if (NULL != cadet)
+    {
+      GNUNET_CADET_disconnect (cadet);
+      cadet = NULL;
+    }
+  }
+  GNUNET_STATISTICS_destroy (_GSS_statistics,
+                             GNUNET_YES);
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "handled shutdown request\n");
+}
+
+
+/**
+ * Function called by the service's run
+ * method to run service-specific setup code.
+ *
+ * @param cls closure
+ * @param cfg configuration to use
+ * @param service the initialized service
+ */
+static void
+run (void *cls,
+     const struct GNUNET_CONFIGURATION_Handle *cfg,
+     struct GNUNET_SERVICE_Handle *service)
+{
+  /* FIXME: need to modify SERVICE (!) API to allow
+     us to run a shutdown task *after* clients were
+     forcefully disconnected! */
+  GNUNET_SCHEDULER_add_shutdown (&shutdown_task,
+                                 NULL);
+  _GSS_statistics = GNUNET_STATISTICS_create ("setu",
+                                              cfg);
+  cadet = GNUNET_CADET_connect (cfg);
+  if (NULL == cadet)
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                _ ("Could not connect to CADET service\n"));
+    GNUNET_SCHEDULER_shutdown ();
+    return;
+  }
+}
+
+
+/**
+ * Define "main" method using service macro.
+ */
+GNUNET_SERVICE_MAIN (
+  "set",
+  GNUNET_SERVICE_OPTION_NONE,
+  &run,
+  &client_connect_cb,
+  &client_disconnect_cb,
+  NULL,
+  GNUNET_MQ_hd_fixed_size (client_accept,
+                           GNUNET_MESSAGE_TYPE_SETU_ACCEPT,
+                           struct GNUNET_SETU_AcceptMessage,
+                           NULL),
+  GNUNET_MQ_hd_var_size (client_set_add,
+                         GNUNET_MESSAGE_TYPE_SETU_ADD,
+                         struct GNUNET_SETU_ElementMessage,
+                         NULL),
+  GNUNET_MQ_hd_fixed_size (client_create_set,
+                           GNUNET_MESSAGE_TYPE_SETU_CREATE,
+                           struct GNUNET_SETU_CreateMessage,
+                           NULL),
+  GNUNET_MQ_hd_var_size (client_evaluate,
+                         GNUNET_MESSAGE_TYPE_SETU_EVALUATE,
+                         struct GNUNET_SETU_EvaluateMessage,
+                         NULL),
+  GNUNET_MQ_hd_fixed_size (client_listen,
+                           GNUNET_MESSAGE_TYPE_SETU_LISTEN,
+                           struct GNUNET_SETU_ListenMessage,
+                           NULL),
+  GNUNET_MQ_hd_fixed_size (client_reject,
+                           GNUNET_MESSAGE_TYPE_SETU_REJECT,
+                           struct GNUNET_SETU_RejectMessage,
+                           NULL),
+  GNUNET_MQ_hd_fixed_size (client_cancel,
+                           GNUNET_MESSAGE_TYPE_SETU_CANCEL,
+                           struct GNUNET_SETU_CancelMessage,
+                           NULL),
+  GNUNET_MQ_handler_end ());
+
+
+/* end of gnunet-service-setu.c */
diff --git a/src/setu/gnunet-service-setu_protocol.h b/src/setu/gnunet-service-setu_protocol.h
new file mode 100644
index 0000000000000000000000000000000000000000..a2803ee47fc6015ae0c27dcd968916ff8b99a320
--- /dev/null
+++ b/src/setu/gnunet-service-setu_protocol.h
@@ -0,0 +1,226 @@
+/*
+     This file is part of GNUnet.
+     Copyright (C) 2013, 2014 GNUnet e.V.
+
+     GNUnet is free software: you can redistribute it and/or modify it
+     under the terms of the GNU Affero General Public License as published
+     by the Free Software Foundation, either version 3 of the License,
+     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
+     Affero General Public License for more details.
+
+     You should have received a copy of the GNU Affero General Public License
+     along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+     SPDX-License-Identifier: AGPL3.0-or-later
+ */
+/**
+ * @author Florian Dold
+ * @author Christian Grothoff
+ * @file set/gnunet-service-set_protocol.h
+ * @brief Peer-to-Peer messages for gnunet set
+ */
+#ifndef SET_PROTOCOL_H
+#define SET_PROTOCOL_H
+
+#include "platform.h"
+#include "gnunet_common.h"
+
+
+GNUNET_NETWORK_STRUCT_BEGIN
+
+struct OperationRequestMessage
+{
+  /**
+   * Type: #GNUNET_MESSAGE_TYPE_SET_P2P_OPERATION_REQUEST
+   */
+  struct GNUNET_MessageHeader header;
+
+  /**
+   * Operation to request, values from `enum GNUNET_SET_OperationType`
+   */
+  uint32_t operation GNUNET_PACKED;
+
+  /**
+   * For Intersection: my element count
+   */
+  uint32_t element_count GNUNET_PACKED;
+
+  /**
+   * Application-specific identifier of the request.
+   */
+  struct GNUNET_HashCode app_idX;
+
+  /* rest: optional message */
+};
+
+
+/**
+ * Message containing buckets of an invertible bloom filter.
+ *
+ * If an IBF has too many buckets for an IBF message,
+ * it is split into multiple messages.
+ */
+struct IBFMessage
+{
+  /**
+   * Type: #GNUNET_MESSAGE_TYPE_SET_UNION_P2P_IBF
+   */
+  struct GNUNET_MessageHeader header;
+
+  /**
+   * Order of the whole ibf, where
+   * num_buckets = 2^order
+   */
+  uint8_t order;
+
+  /**
+   * Padding, must be 0.
+   */
+  uint8_t reserved1;
+
+  /**
+   * Padding, must be 0.
+   */
+  uint16_t reserved2 GNUNET_PACKED;
+
+  /**
+   * Offset of the strata in the rest of the message
+   */
+  uint32_t offset GNUNET_PACKED;
+
+  /**
+   * Salt used when hashing elements for this IBF.
+   */
+  uint32_t salt GNUNET_PACKED;
+
+  /* rest: buckets */
+};
+
+
+struct InquiryMessage
+{
+  /**
+   * Type: #GNUNET_MESSAGE_TYPE_SET_UNION_P2P_IBF
+   */
+  struct GNUNET_MessageHeader header;
+
+  /**
+   * Salt used when hashing elements for this inquiry.
+   */
+  uint32_t salt GNUNET_PACKED;
+
+  /**
+   * Reserved, set to 0.
+   */
+  uint32_t reserved GNUNET_PACKED;
+
+  /* rest: inquiry IBF keys */
+};
+
+
+/**
+ * During intersection, the first (and possibly second) message
+ * send it the number of elements in the set, to allow the peers
+ * to decide who should start with the Bloom filter.
+ */
+struct IntersectionElementInfoMessage
+{
+  /**
+   * Type: #GNUNET_MESSAGE_TYPE_SET_INTERSECTION_P2P_ELEMENT_INFO
+   */
+  struct GNUNET_MessageHeader header;
+
+  /**
+   * mutator used with this bloomfilter.
+   */
+  uint32_t sender_element_count GNUNET_PACKED;
+};
+
+
+/**
+ * Bloom filter messages exchanged for set intersection calculation.
+ */
+struct BFMessage
+{
+  /**
+   * Type: #GNUNET_MESSAGE_TYPE_SET_INTERSECTION_P2P_BF
+   */
+  struct GNUNET_MessageHeader header;
+
+  /**
+   * Number of elements the sender still has in the set.
+   */
+  uint32_t sender_element_count GNUNET_PACKED;
+
+  /**
+   * XOR of all hashes over all elements remaining in the set.
+   * Used to determine termination.
+   */
+  struct GNUNET_HashCode element_xor_hash;
+
+  /**
+   * Mutator used with this bloomfilter.
+   */
+  uint32_t sender_mutator GNUNET_PACKED;
+
+  /**
+   * Total length of the bloomfilter data.
+   */
+  uint32_t bloomfilter_total_length GNUNET_PACKED;
+
+  /**
+   * Number of bits (k-value) used in encoding the bloomfilter.
+   */
+  uint32_t bits_per_element GNUNET_PACKED;
+
+  /**
+   * rest: the sender's bloomfilter
+   */
+};
+
+
+/**
+ * Last message, send to confirm the final set.  Contains the element
+ * count as it is possible that the peer determined that we were done
+ * by getting the empty set, which in that case also needs to be
+ * communicated.
+ */
+struct IntersectionDoneMessage
+{
+  /**
+   * Type: #GNUNET_MESSAGE_TYPE_SET_INTERSECTION_P2P_DONE
+   */
+  struct GNUNET_MessageHeader header;
+
+  /**
+   * Final number of elements in intersection.
+   */
+  uint32_t final_element_count GNUNET_PACKED;
+
+  /**
+   * XOR of all hashes over all elements remaining in the set.
+   */
+  struct GNUNET_HashCode element_xor_hash;
+};
+
+
+/**
+ * Strata estimator together with the peer's overall set size.
+ */
+struct StrataEstimatorMessage
+{
+  /**
+   * Type: #GNUNET_MESSAGE_TYPE_SET_UNION_P2P_SE(C)
+   */
+  struct GNUNET_MessageHeader header;
+
+  uint64_t set_size;
+};
+
+GNUNET_NETWORK_STRUCT_END
+
+#endif
diff --git a/src/setu/gnunet-service-setu_strata_estimator.c b/src/setu/gnunet-service-setu_strata_estimator.c
new file mode 100644
index 0000000000000000000000000000000000000000..0fa6a6f177636c562a0d34529b2c49438289a6cd
--- /dev/null
+++ b/src/setu/gnunet-service-setu_strata_estimator.c
@@ -0,0 +1,303 @@
+/*
+      This file is part of GNUnet
+      Copyright (C) 2012 GNUnet e.V.
+
+      GNUnet is free software: you can redistribute it and/or modify it
+      under the terms of the GNU Affero General Public License as published
+      by the Free Software Foundation, either version 3 of the License,
+      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
+      Affero General Public License for more details.
+
+      You should have received a copy of the GNU Affero General Public License
+      along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+     SPDX-License-Identifier: AGPL3.0-or-later
+ */
+/**
+ * @file set/gnunet-service-setu_strata_estimator.c
+ * @brief invertible bloom filter
+ * @author Florian Dold
+ * @author Christian Grothoff
+ */
+#include "platform.h"
+#include "gnunet_util_lib.h"
+#include "ibf.h"
+#include "gnunet-service-setu_strata_estimator.h"
+
+
+/**
+ * Should we try compressing the strata estimator? This will
+ * break compatibility with the 0.10.1-network.
+ */
+#define FAIL_10_1_COMPATIBILTIY 1
+
+
+/**
+ * Write the given strata estimator to the buffer.
+ *
+ * @param se strata estimator to serialize
+ * @param[out] buf buffer to write to, must be of appropriate size
+ * @return number of bytes written to @a buf
+ */
+size_t
+strata_estimator_write (const struct StrataEstimator *se,
+                        void *buf)
+{
+  char *sbuf = buf;
+  unsigned int i;
+  size_t osize;
+
+  GNUNET_assert (NULL != se);
+  for (i = 0; i < se->strata_count; i++)
+  {
+    ibf_write_slice (se->strata[i],
+                     0,
+                     se->ibf_size,
+                     &sbuf[se->ibf_size * IBF_BUCKET_SIZE * i]);
+  }
+  osize = se->ibf_size * IBF_BUCKET_SIZE * se->strata_count;
+#if FAIL_10_1_COMPATIBILTIY
+  {
+    char *cbuf;
+    size_t nsize;
+
+    if (GNUNET_YES ==
+        GNUNET_try_compression (buf,
+                                osize,
+                                &cbuf,
+                                &nsize))
+    {
+      GNUNET_memcpy (buf, cbuf, nsize);
+      osize = nsize;
+      GNUNET_free (cbuf);
+    }
+  }
+#endif
+  return osize;
+}
+
+
+/**
+ * Read strata from the buffer into the given strata
+ * estimator.  The strata estimator must already be allocated.
+ *
+ * @param buf buffer to read from
+ * @param buf_len number of bytes in @a buf
+ * @param is_compressed is the data compressed?
+ * @param[out] se strata estimator to write to
+ * @return #GNUNET_OK on success
+ */
+int
+strata_estimator_read (const void *buf,
+                       size_t buf_len,
+                       int is_compressed,
+                       struct StrataEstimator *se)
+{
+  unsigned int i;
+  size_t osize;
+  char *dbuf;
+
+  dbuf = NULL;
+  if (GNUNET_YES == is_compressed)
+  {
+    osize = se->ibf_size * IBF_BUCKET_SIZE * se->strata_count;
+    dbuf = GNUNET_decompress (buf,
+                              buf_len,
+                              osize);
+    if (NULL == dbuf)
+    {
+      GNUNET_break_op (0);    /* bad compressed input data */
+      return GNUNET_SYSERR;
+    }
+    buf = dbuf;
+    buf_len = osize;
+  }
+
+  if (buf_len != se->strata_count * se->ibf_size * IBF_BUCKET_SIZE)
+  {
+    GNUNET_break (0);  /* very odd error */
+    GNUNET_free (dbuf);
+    return GNUNET_SYSERR;
+  }
+
+  for (i = 0; i < se->strata_count; i++)
+  {
+    ibf_read_slice (buf, 0, se->ibf_size, se->strata[i]);
+    buf += se->ibf_size * IBF_BUCKET_SIZE;
+  }
+  GNUNET_free (dbuf);
+  return GNUNET_OK;
+}
+
+
+/**
+ * Add a key to the strata estimator.
+ *
+ * @param se strata estimator to add the key to
+ * @param key key to add
+ */
+void
+strata_estimator_insert (struct StrataEstimator *se,
+                         struct IBF_Key key)
+{
+  uint64_t v;
+  unsigned int i;
+
+  v = key.key_val;
+  /* count trailing '1'-bits of v */
+  for (i = 0; v & 1; v >>= 1, i++)
+    /* empty */;
+  ibf_insert (se->strata[i], key);
+}
+
+
+/**
+ * Remove a key from the strata estimator.
+ *
+ * @param se strata estimator to remove the key from
+ * @param key key to remove
+ */
+void
+strata_estimator_remove (struct StrataEstimator *se,
+                         struct IBF_Key key)
+{
+  uint64_t v;
+  unsigned int i;
+
+  v = key.key_val;
+  /* count trailing '1'-bits of v */
+  for (i = 0; v & 1; v >>= 1, i++)
+    /* empty */;
+  ibf_remove (se->strata[i], key);
+}
+
+
+/**
+ * Create a new strata estimator with the given parameters.
+ *
+ * @param strata_count number of stratas, that is, number of ibfs in the estimator
+ * @param ibf_size size of each ibf stratum
+ * @param ibf_hashnum hashnum parameter of each ibf
+ * @return a freshly allocated, empty strata estimator, NULL on error
+ */
+struct StrataEstimator *
+strata_estimator_create (unsigned int strata_count,
+                         uint32_t ibf_size,
+                         uint8_t ibf_hashnum)
+{
+  struct StrataEstimator *se;
+  unsigned int i;
+  unsigned int j;
+
+  se = GNUNET_new (struct StrataEstimator);
+  se->strata_count = strata_count;
+  se->ibf_size = ibf_size;
+  se->strata = GNUNET_new_array (strata_count,
+                                 struct InvertibleBloomFilter *);
+  for (i = 0; i < strata_count; i++)
+  {
+    se->strata[i] = ibf_create (ibf_size, ibf_hashnum);
+    if (NULL == se->strata[i])
+    {
+      GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                  "Failed to allocate memory for strata estimator\n");
+      for (j = 0; j < i; j++)
+        ibf_destroy (se->strata[i]);
+      GNUNET_free (se);
+      return NULL;
+    }
+  }
+  return se;
+}
+
+
+/**
+ * Estimate set difference with two strata estimators,
+ * i.e. arrays of IBFs.
+ * Does not not modify its arguments.
+ *
+ * @param se1 first strata estimator
+ * @param se2 second strata estimator
+ * @return the estimated difference
+ */
+unsigned int
+strata_estimator_difference (const struct StrataEstimator *se1,
+                             const struct StrataEstimator *se2)
+{
+  unsigned int count;
+
+  GNUNET_assert (se1->strata_count == se2->strata_count);
+  count = 0;
+  for (int i = se1->strata_count - 1; i >= 0; i--)
+  {
+    struct InvertibleBloomFilter *diff;
+    /* number of keys decoded from the ibf */
+
+    /* FIXME: implement this without always allocating new IBFs */
+    diff = ibf_dup (se1->strata[i]);
+    ibf_subtract (diff, se2->strata[i]);
+    for (int ibf_count = 0; GNUNET_YES; ibf_count++)
+    {
+      int more;
+
+      more = ibf_decode (diff, NULL, NULL);
+      if (GNUNET_NO == more)
+      {
+        count += ibf_count;
+        break;
+      }
+      /* Estimate if decoding fails or would not terminate */
+      if ((GNUNET_SYSERR == more) || (ibf_count > diff->size))
+      {
+        ibf_destroy (diff);
+        return count * (1 << (i + 1));
+      }
+    }
+    ibf_destroy (diff);
+  }
+  return count;
+}
+
+
+/**
+ * Make a copy of a strata estimator.
+ *
+ * @param se the strata estimator to copy
+ * @return the copy
+ */
+struct StrataEstimator *
+strata_estimator_dup (struct StrataEstimator *se)
+{
+  struct StrataEstimator *c;
+  unsigned int i;
+
+  c = GNUNET_new (struct StrataEstimator);
+  c->strata_count = se->strata_count;
+  c->ibf_size = se->ibf_size;
+  c->strata = GNUNET_new_array (se->strata_count,
+                                struct InvertibleBloomFilter *);
+  for (i = 0; i < se->strata_count; i++)
+    c->strata[i] = ibf_dup (se->strata[i]);
+  return c;
+}
+
+
+/**
+ * Destroy a strata estimator, free all of its resources.
+ *
+ * @param se strata estimator to destroy.
+ */
+void
+strata_estimator_destroy (struct StrataEstimator *se)
+{
+  unsigned int i;
+
+  for (i = 0; i < se->strata_count; i++)
+    ibf_destroy (se->strata[i]);
+  GNUNET_free (se->strata);
+  GNUNET_free (se);
+}
diff --git a/src/setu/gnunet-service-setu_strata_estimator.h b/src/setu/gnunet-service-setu_strata_estimator.h
new file mode 100644
index 0000000000000000000000000000000000000000..afdbcdbbf6c1556db8df0e560dcb5c9e38fa1c38
--- /dev/null
+++ b/src/setu/gnunet-service-setu_strata_estimator.h
@@ -0,0 +1,169 @@
+/*
+      This file is part of GNUnet
+      Copyright (C) 2012 GNUnet e.V.
+
+      GNUnet is free software: you can redistribute it and/or modify it
+      under the terms of the GNU Affero General Public License as published
+      by the Free Software Foundation, either version 3 of the License,
+      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
+      Affero General Public License for more details.
+
+      You should have received a copy of the GNU Affero General Public License
+      along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+     SPDX-License-Identifier: AGPL3.0-or-later
+ */
+
+/**
+ * @file set/gnunet-service-setu_strata_estimator.h
+ * @brief estimator of set difference
+ * @author Florian Dold
+ */
+
+#ifndef GNUNET_SERVICE_SETU_STRATA_ESTIMATOR_H
+#define GNUNET_SERVICE_SETU_STRATA_ESTIMATOR_H
+
+#include "platform.h"
+#include "gnunet_common.h"
+#include "gnunet_util_lib.h"
+
+#ifdef __cplusplus
+extern "C"
+{
+#if 0                           /* keep Emacsens' auto-indent happy */
+}
+#endif
+#endif
+
+
+/**
+ * A handle to a strata estimator.
+ */
+struct StrataEstimator
+{
+  /**
+   * The IBFs of this strata estimator.
+   */
+  struct InvertibleBloomFilter **strata;
+
+  /**
+   * Size of the IBF array in @e strata
+   */
+  unsigned int strata_count;
+
+  /**
+   * Size of each IBF stratum (in bytes)
+   */
+  unsigned int ibf_size;
+};
+
+
+/**
+ * Write the given strata estimator to the buffer.
+ *
+ * @param se strata estimator to serialize
+ * @param[out] buf buffer to write to, must be of appropriate size
+ * @return number of bytes written to @a buf
+ */
+size_t
+strata_estimator_write (const struct StrataEstimator *se,
+                        void *buf);
+
+
+/**
+ * Read strata from the buffer into the given strata
+ * estimator.  The strata estimator must already be allocated.
+ *
+ * @param buf buffer to read from
+ * @param buf_len number of bytes in @a buf
+ * @param is_compressed is the data compressed?
+ * @param[out] se strata estimator to write to
+ * @return #GNUNET_OK on success
+ */
+int
+strata_estimator_read (const void *buf,
+                       size_t buf_len,
+                       int is_compressed,
+                       struct StrataEstimator *se);
+
+
+/**
+ * Create a new strata estimator with the given parameters.
+ *
+ * @param strata_count number of stratas, that is, number of ibfs in the estimator
+ * @param ibf_size size of each ibf stratum
+ * @param ibf_hashnum hashnum parameter of each ibf
+ * @return a freshly allocated, empty strata estimator, NULL on error
+ */
+struct StrataEstimator *
+strata_estimator_create (unsigned int strata_count,
+                         uint32_t ibf_size,
+                         uint8_t ibf_hashnum);
+
+
+/**
+ * Get an estimation of the symmetric difference of the elements
+ * contained in both strata estimators.
+ *
+ * @param se1 first strata estimator
+ * @param se2 second strata estimator
+ * @return abs(|se1| - |se2|)
+ */
+unsigned int
+strata_estimator_difference (const struct StrataEstimator *se1,
+                             const struct StrataEstimator *se2);
+
+
+/**
+ * Add a key to the strata estimator.
+ *
+ * @param se strata estimator to add the key to
+ * @param key key to add
+ */
+void
+strata_estimator_insert (struct StrataEstimator *se,
+                         struct IBF_Key key);
+
+
+/**
+ * Remove a key from the strata estimator.
+ *
+ * @param se strata estimator to remove the key from
+ * @param key key to remove
+ */
+void
+strata_estimator_remove (struct StrataEstimator *se,
+                         struct IBF_Key key);
+
+
+/**
+ * Destroy a strata estimator, free all of its resources.
+ *
+ * @param se strata estimator to destroy.
+ */
+void
+strata_estimator_destroy (struct StrataEstimator *se);
+
+
+/**
+ * Make a copy of a strata estimator.
+ *
+ * @param se the strata estimator to copy
+ * @return the copy
+ */
+struct StrataEstimator *
+strata_estimator_dup (struct StrataEstimator *se);
+
+
+#if 0                           /* keep Emacsens' auto-indent happy */
+{
+#endif
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/src/setu/gnunet-setu-ibf-profiler.c b/src/setu/gnunet-setu-ibf-profiler.c
new file mode 100644
index 0000000000000000000000000000000000000000..944b63d307f9ca70b44fec2008393067b3642c34
--- /dev/null
+++ b/src/setu/gnunet-setu-ibf-profiler.c
@@ -0,0 +1,308 @@
+/*
+     This file is part of GNUnet.
+     Copyright (C) 2012 GNUnet e.V.
+
+     GNUnet is free software: you can redistribute it and/or modify it
+     under the terms of the GNU Affero General Public License as published
+     by the Free Software Foundation, either version 3 of the License,
+     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
+     Affero General Public License for more details.
+
+     You should have received a copy of the GNU Affero General Public License
+     along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+     SPDX-License-Identifier: AGPL3.0-or-later
+ */
+
+/**
+ * @file set/gnunet-set-ibf-profiler.c
+ * @brief tool for profiling the invertible bloom filter implementation
+ * @author Florian Dold
+ */
+
+#include "platform.h"
+#include "gnunet_util_lib.h"
+
+#include "ibf.h"
+
+static unsigned int asize = 10;
+static unsigned int bsize = 10;
+static unsigned int csize = 10;
+static unsigned int hash_num = 4;
+static unsigned int ibf_size = 80;
+
+/* FIXME: add parameter for this */
+static enum GNUNET_CRYPTO_Quality random_quality = GNUNET_CRYPTO_QUALITY_WEAK;
+
+static struct GNUNET_CONTAINER_MultiHashMap *set_a;
+static struct GNUNET_CONTAINER_MultiHashMap *set_b;
+/* common elements in a and b */
+static struct GNUNET_CONTAINER_MultiHashMap *set_c;
+
+static struct GNUNET_CONTAINER_MultiHashMap *key_to_hashcode;
+
+static struct InvertibleBloomFilter *ibf_a;
+static struct InvertibleBloomFilter *ibf_b;
+
+
+static void
+register_hashcode (struct GNUNET_HashCode *hash)
+{
+  struct GNUNET_HashCode replicated;
+  struct IBF_Key key;
+
+  key = ibf_key_from_hashcode (hash);
+  ibf_hashcode_from_key (key, &replicated);
+  (void) GNUNET_CONTAINER_multihashmap_put (
+    key_to_hashcode,
+    &replicated,
+    GNUNET_memdup (hash, sizeof *hash),
+    GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE);
+}
+
+
+static void
+iter_hashcodes (struct IBF_Key key,
+                GNUNET_CONTAINER_MulitHashMapIteratorCallback iter,
+                void *cls)
+{
+  struct GNUNET_HashCode replicated;
+
+  ibf_hashcode_from_key (key, &replicated);
+  GNUNET_CONTAINER_multihashmap_get_multiple (key_to_hashcode,
+                                              &replicated,
+                                              iter,
+                                              cls);
+}
+
+
+static int
+insert_iterator (void *cls, const struct GNUNET_HashCode *key, void *value)
+{
+  struct InvertibleBloomFilter *ibf = cls;
+
+  ibf_insert (ibf, ibf_key_from_hashcode (key));
+  return GNUNET_YES;
+}
+
+
+static int
+remove_iterator (void *cls, const struct GNUNET_HashCode *key, void *value)
+{
+  struct GNUNET_CONTAINER_MultiHashMap *hashmap = cls;
+
+  /* if remove fails, there just was a collision with another key */
+  (void) GNUNET_CONTAINER_multihashmap_remove (hashmap, value, NULL);
+  return GNUNET_YES;
+}
+
+
+static void
+run (void *cls,
+     char *const *args,
+     const char *cfgfile,
+     const struct GNUNET_CONFIGURATION_Handle *cfg)
+{
+  struct GNUNET_HashCode id;
+  struct IBF_Key ibf_key;
+  int i;
+  int side;
+  int res;
+  struct GNUNET_TIME_Absolute start_time;
+  struct GNUNET_TIME_Relative delta_time;
+
+  set_a =
+    GNUNET_CONTAINER_multihashmap_create (((asize == 0) ? 1 : (asize + csize)),
+                                          GNUNET_NO);
+  set_b =
+    GNUNET_CONTAINER_multihashmap_create (((bsize == 0) ? 1 : (bsize + csize)),
+                                          GNUNET_NO);
+  set_c = GNUNET_CONTAINER_multihashmap_create (((csize == 0) ? 1 : csize),
+                                                GNUNET_NO);
+
+  key_to_hashcode =
+    GNUNET_CONTAINER_multihashmap_create (((asize + bsize + csize == 0)
+                                           ? 1
+                                           : (asize + bsize + csize)),
+                                          GNUNET_NO);
+
+  printf ("hash-num=%u, size=%u, #(A-B)=%u, #(B-A)=%u, #(A&B)=%u\n",
+          hash_num,
+          ibf_size,
+          asize,
+          bsize,
+          csize);
+
+  i = 0;
+  while (i < asize)
+  {
+    GNUNET_CRYPTO_hash_create_random (random_quality, &id);
+    if (GNUNET_YES == GNUNET_CONTAINER_multihashmap_contains (set_a, &id))
+      continue;
+    GNUNET_break (GNUNET_OK ==
+                  GNUNET_CONTAINER_multihashmap_put (
+                    set_a,
+                    &id,
+                    NULL,
+                    GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
+    register_hashcode (&id);
+    i++;
+  }
+  i = 0;
+  while (i < bsize)
+  {
+    GNUNET_CRYPTO_hash_create_random (random_quality, &id);
+    if (GNUNET_YES == GNUNET_CONTAINER_multihashmap_contains (set_a, &id))
+      continue;
+    if (GNUNET_YES == GNUNET_CONTAINER_multihashmap_contains (set_b, &id))
+      continue;
+    GNUNET_break (GNUNET_OK ==
+                  GNUNET_CONTAINER_multihashmap_put (
+                    set_b,
+                    &id,
+                    NULL,
+                    GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
+    register_hashcode (&id);
+    i++;
+  }
+  i = 0;
+  while (i < csize)
+  {
+    GNUNET_CRYPTO_hash_create_random (random_quality, &id);
+    if (GNUNET_YES == GNUNET_CONTAINER_multihashmap_contains (set_a, &id))
+      continue;
+    if (GNUNET_YES == GNUNET_CONTAINER_multihashmap_contains (set_b, &id))
+      continue;
+    if (GNUNET_YES == GNUNET_CONTAINER_multihashmap_contains (set_c, &id))
+      continue;
+    GNUNET_break (GNUNET_OK ==
+                  GNUNET_CONTAINER_multihashmap_put (
+                    set_c,
+                    &id,
+                    NULL,
+                    GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
+    register_hashcode (&id);
+    i++;
+  }
+
+  ibf_a = ibf_create (ibf_size, hash_num);
+  ibf_b = ibf_create (ibf_size, hash_num);
+  if ((NULL == ibf_a) || (NULL == ibf_b))
+  {
+    /* insufficient memory */
+    GNUNET_break (0);
+    GNUNET_SCHEDULER_shutdown ();
+    return;
+  }
+
+
+  printf ("generated sets\n");
+
+  start_time = GNUNET_TIME_absolute_get ();
+
+  GNUNET_CONTAINER_multihashmap_iterate (set_a, &insert_iterator, ibf_a);
+  GNUNET_CONTAINER_multihashmap_iterate (set_b, &insert_iterator, ibf_b);
+  GNUNET_CONTAINER_multihashmap_iterate (set_c, &insert_iterator, ibf_a);
+  GNUNET_CONTAINER_multihashmap_iterate (set_c, &insert_iterator, ibf_b);
+
+  delta_time = GNUNET_TIME_absolute_get_duration (start_time);
+
+  printf ("encoded in: %s\n",
+          GNUNET_STRINGS_relative_time_to_string (delta_time, GNUNET_NO));
+
+  ibf_subtract (ibf_a, ibf_b);
+
+
+  start_time = GNUNET_TIME_absolute_get ();
+
+  for (i = 0; i <= asize + bsize; i++)
+  {
+    res = ibf_decode (ibf_a, &side, &ibf_key);
+    if (GNUNET_SYSERR == res)
+    {
+      printf ("decode failed, %u/%u elements left\n",
+              GNUNET_CONTAINER_multihashmap_size (set_a)
+              + GNUNET_CONTAINER_multihashmap_size (set_b),
+              asize + bsize);
+      return;
+    }
+    if (GNUNET_NO == res)
+    {
+      if ((0 == GNUNET_CONTAINER_multihashmap_size (set_b)) &&
+          (0 == GNUNET_CONTAINER_multihashmap_size (set_a)))
+      {
+        delta_time = GNUNET_TIME_absolute_get_duration (start_time);
+        printf ("decoded successfully in: %s\n",
+                GNUNET_STRINGS_relative_time_to_string (delta_time, GNUNET_NO));
+      }
+      else
+      {
+        printf ("decode missed elements (should never happen)\n");
+      }
+      return;
+    }
+
+    if (side == 1)
+      iter_hashcodes (ibf_key, remove_iterator, set_a);
+    if (side == -1)
+      iter_hashcodes (ibf_key, remove_iterator, set_b);
+  }
+  printf ("cyclic IBF, %u/%u elements left\n",
+          GNUNET_CONTAINER_multihashmap_size (set_a)
+          + GNUNET_CONTAINER_multihashmap_size (set_b),
+          asize + bsize);
+}
+
+
+int
+main (int argc, char **argv)
+{
+  struct GNUNET_GETOPT_CommandLineOption options[] = {
+    GNUNET_GETOPT_option_uint ('A',
+                               "asize",
+                               NULL,
+                               gettext_noop ("number of element in set A-B"),
+                               &asize),
+
+    GNUNET_GETOPT_option_uint ('B',
+                               "bsize",
+                               NULL,
+                               gettext_noop ("number of element in set B-A"),
+                               &bsize),
+
+    GNUNET_GETOPT_option_uint ('C',
+                               "csize",
+                               NULL,
+                               gettext_noop (
+                                 "number of common elements in A and B"),
+                               &csize),
+
+    GNUNET_GETOPT_option_uint ('k',
+                               "hash-num",
+                               NULL,
+                               gettext_noop ("hash num"),
+                               &hash_num),
+
+    GNUNET_GETOPT_option_uint ('s',
+                               "ibf-size",
+                               NULL,
+                               gettext_noop ("ibf size"),
+                               &ibf_size),
+
+    GNUNET_GETOPT_OPTION_END
+  };
+
+  GNUNET_PROGRAM_run2 (argc,
+                       argv,
+                       "gnunet-consensus-ibf",
+                       "help",
+                       options,
+                       &run,
+                       NULL,
+                       GNUNET_YES);
+  return 0;
+}
diff --git a/src/setu/gnunet-setu-profiler.c b/src/setu/gnunet-setu-profiler.c
new file mode 100644
index 0000000000000000000000000000000000000000..8d6a2dc8c75a3b2d2ffae1d2f8ce46d338925004
--- /dev/null
+++ b/src/setu/gnunet-setu-profiler.c
@@ -0,0 +1,499 @@
+/*
+      This file is part of GNUnet
+      Copyright (C) 2013 GNUnet e.V.
+
+      GNUnet is free software: you can redistribute it and/or modify it
+      under the terms of the GNU Affero General Public License as published
+      by the Free Software Foundation, either version 3 of the License,
+      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
+      Affero General Public License for more details.
+
+      You should have received a copy of the GNU Affero General Public License
+      along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+     SPDX-License-Identifier: AGPL3.0-or-later
+ */
+
+/**
+ * @file setu/gnunet-setu-profiler.c
+ * @brief profiling tool for set
+ * @author Florian Dold
+ */
+#include "platform.h"
+#include "gnunet_util_lib.h"
+#include "gnunet_statistics_service.h"
+#include "gnunet_setu_service.h"
+#include "gnunet_testbed_service.h"
+
+
+static int ret;
+
+static unsigned int num_a = 5;
+static unsigned int num_b = 5;
+static unsigned int num_c = 20;
+
+static char *op_str = "union";
+
+const static struct GNUNET_CONFIGURATION_Handle *config;
+
+struct SetInfo
+{
+  char *id;
+  struct GNUNET_SETU_Handle *set;
+  struct GNUNET_SETU_OperationHandle *oh;
+  struct GNUNET_CONTAINER_MultiHashMap *sent;
+  struct GNUNET_CONTAINER_MultiHashMap *received;
+  int done;
+} info1, info2;
+
+static struct GNUNET_CONTAINER_MultiHashMap *common_sent;
+
+static struct GNUNET_HashCode app_id;
+
+static struct GNUNET_PeerIdentity local_peer;
+
+static struct GNUNET_SETU_ListenHandle *set_listener;
+
+static int byzantine;
+static unsigned int force_delta;
+static unsigned int force_full;
+static unsigned int element_size = 32;
+
+/**
+ * Handle to the statistics service.
+ */
+static struct GNUNET_STATISTICS_Handle *statistics;
+
+/**
+ * The profiler will write statistics
+ * for all peers to the file with this name.
+ */
+static char *statistics_filename;
+
+/**
+ * The profiler will write statistics
+ * for all peers to this file.
+ */
+static FILE *statistics_file;
+
+
+static int
+map_remove_iterator (void *cls,
+                     const struct GNUNET_HashCode *key,
+                     void *value)
+{
+  struct GNUNET_CONTAINER_MultiHashMap *m = cls;
+  int ret;
+
+  GNUNET_assert (NULL != key);
+
+  ret = GNUNET_CONTAINER_multihashmap_remove_all (m, key);
+  if (GNUNET_OK != ret)
+    printf ("spurious element\n");
+  return GNUNET_YES;
+}
+
+
+/**
+ * Callback function to process statistic values.
+ *
+ * @param cls closure
+ * @param subsystem name of subsystem that created the statistic
+ * @param name the name of the datum
+ * @param value the current value
+ * @param is_persistent #GNUNET_YES if the value is persistent, #GNUNET_NO if not
+ * @return #GNUNET_OK to continue, #GNUNET_SYSERR to abort iteration
+ */
+static int
+statistics_result (void *cls,
+                   const char *subsystem,
+                   const char *name,
+                   uint64_t value,
+                   int is_persistent)
+{
+  if (NULL != statistics_file)
+  {
+    fprintf (statistics_file, "%s\t%s\t%lu\n", subsystem, name, (unsigned
+                                                                 long) value);
+  }
+  return GNUNET_OK;
+}
+
+
+static void
+statistics_done (void *cls,
+                 int success)
+{
+  GNUNET_assert (GNUNET_YES == success);
+  if (NULL != statistics_file)
+    fclose (statistics_file);
+  GNUNET_SCHEDULER_shutdown ();
+}
+
+
+static void
+check_all_done (void)
+{
+  if ((info1.done == GNUNET_NO) || (info2.done == GNUNET_NO))
+    return;
+
+  GNUNET_CONTAINER_multihashmap_iterate (info1.received, map_remove_iterator,
+                                         info2.sent);
+  GNUNET_CONTAINER_multihashmap_iterate (info2.received, map_remove_iterator,
+                                         info1.sent);
+
+  printf ("set a: %d missing elements\n", GNUNET_CONTAINER_multihashmap_size (
+            info1.sent));
+  printf ("set b: %d missing elements\n", GNUNET_CONTAINER_multihashmap_size (
+            info2.sent));
+
+  if (NULL == statistics_filename)
+  {
+    GNUNET_SCHEDULER_shutdown ();
+    return;
+  }
+
+  statistics_file = fopen (statistics_filename, "w");
+  GNUNET_STATISTICS_get (statistics, NULL, NULL,
+                         &statistics_done,
+                         &statistics_result, NULL);
+}
+
+
+static void
+set_result_cb (void *cls,
+               const struct GNUNET_SETU_Element *element,
+               uint64_t current_size,
+               enum GNUNET_SETU_Status status)
+{
+  struct SetInfo *info = cls;
+
+  GNUNET_assert (GNUNET_NO == info->done);
+  switch (status)
+  {
+  case GNUNET_SETU_STATUS_DONE:
+    info->done = GNUNET_YES;
+    GNUNET_log (GNUNET_ERROR_TYPE_INFO, "set %s done\n", info->id);
+    check_all_done ();
+    info->oh = NULL;
+    return;
+
+  case GNUNET_SETU_STATUS_FAILURE:
+    info->oh = NULL;
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "failure\n");
+    GNUNET_SCHEDULER_shutdown ();
+    return;
+
+  case GNUNET_SETU_STATUS_ADD_LOCAL:
+    GNUNET_log (GNUNET_ERROR_TYPE_INFO, "set %s: local element\n", info->id);
+    break;
+  default:
+    GNUNET_assert (0);
+  }
+
+  if (element->size != element_size)
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+                "wrong element size: %u, expected %u\n",
+                element->size,
+                (unsigned int) sizeof(struct GNUNET_HashCode));
+    GNUNET_assert (0);
+  }
+
+  GNUNET_log (GNUNET_ERROR_TYPE_INFO, "set %s: got element (%s)\n",
+              info->id, GNUNET_h2s (element->data));
+  GNUNET_assert (NULL != element->data);
+  struct GNUNET_HashCode data_hash;
+  GNUNET_CRYPTO_hash (element->data, element_size, &data_hash);
+  GNUNET_CONTAINER_multihashmap_put (info->received,
+                                     &data_hash, NULL,
+                                     GNUNET_CONTAINER_MULTIHASHMAPOPTION_REPLACE);
+}
+
+
+static void
+set_listen_cb (void *cls,
+               const struct GNUNET_PeerIdentity *other_peer,
+               const struct GNUNET_MessageHeader *context_msg,
+               struct GNUNET_SETU_Request *request)
+{
+  /* max. 2 options plus terminator */
+  struct GNUNET_SETU_Option opts[3] = { { 0 } };
+  unsigned int n_opts = 0;
+
+  if (NULL == request)
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                "listener failed\n");
+    return;
+  }
+  GNUNET_assert (NULL == info2.oh);
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "set listen cb called\n");
+  if (byzantine)
+  {
+    opts[n_opts++] = (struct GNUNET_SETU_Option) { .type =
+                                                     GNUNET_SETU_OPTION_BYZANTINE };
+  }
+  GNUNET_assert (! (force_full && force_delta));
+  if (force_full)
+  {
+    opts[n_opts++] = (struct GNUNET_SETU_Option) { .type =
+                                                     GNUNET_SETU_OPTION_FORCE_FULL };
+  }
+  if (force_delta)
+  {
+    opts[n_opts++] = (struct GNUNET_SETU_Option) { .type =
+                                                     GNUNET_SETU_OPTION_FORCE_DELTA };
+  }
+
+  opts[n_opts].type = 0;
+  info2.oh = GNUNET_SETU_accept (request,
+                                 opts,
+                                 set_result_cb, &info2);
+  GNUNET_SETU_commit (info2.oh, info2.set);
+}
+
+
+static int
+set_insert_iterator (void *cls,
+                     const struct GNUNET_HashCode *key,
+                     void *value)
+{
+  struct GNUNET_SETU_Handle *set = cls;
+  struct GNUNET_SETU_Element el;
+
+  el.element_type = 0;
+  el.data = value;
+  el.size = element_size;
+  GNUNET_SETU_add_element (set, &el, NULL, NULL);
+  return GNUNET_YES;
+}
+
+
+static void
+handle_shutdown (void *cls)
+{
+  GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+              "Shutting down set profiler\n");
+  if (NULL != set_listener)
+  {
+    GNUNET_SETU_listen_cancel (set_listener);
+    set_listener = NULL;
+  }
+  if (NULL != info1.oh)
+  {
+    GNUNET_SETU_operation_cancel (info1.oh);
+    info1.oh = NULL;
+  }
+  if (NULL != info2.oh)
+  {
+    GNUNET_SETU_operation_cancel (info2.oh);
+    info2.oh = NULL;
+  }
+  if (NULL != info1.set)
+  {
+    GNUNET_SETU_destroy (info1.set);
+    info1.set = NULL;
+  }
+  if (NULL != info2.set)
+  {
+    GNUNET_SETU_destroy (info2.set);
+    info2.set = NULL;
+  }
+  GNUNET_STATISTICS_destroy (statistics, GNUNET_NO);
+}
+
+
+static void
+run (void *cls,
+     const struct GNUNET_CONFIGURATION_Handle *cfg,
+     struct GNUNET_TESTING_Peer *peer)
+{
+  unsigned int i;
+  struct GNUNET_HashCode hash;
+  /* max. 2 options plus terminator */
+  struct GNUNET_SETU_Option opts[3] = { { 0 } };
+  unsigned int n_opts = 0;
+
+  config = cfg;
+
+  GNUNET_assert (element_size > 0);
+
+  if (GNUNET_OK != GNUNET_CRYPTO_get_peer_identity (cfg, &local_peer))
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "could not retrieve host identity\n");
+    ret = 0;
+    return;
+  }
+
+  statistics = GNUNET_STATISTICS_create ("set-profiler", cfg);
+
+  GNUNET_SCHEDULER_add_shutdown (&handle_shutdown, NULL);
+
+  info1.id = "a";
+  info2.id = "b";
+
+  info1.sent = GNUNET_CONTAINER_multihashmap_create (num_a + 1, GNUNET_NO);
+  info2.sent = GNUNET_CONTAINER_multihashmap_create (num_b + 1, GNUNET_NO);
+  common_sent = GNUNET_CONTAINER_multihashmap_create (num_c + 1, GNUNET_NO);
+
+  info1.received = GNUNET_CONTAINER_multihashmap_create (num_a + 1, GNUNET_NO);
+  info2.received = GNUNET_CONTAINER_multihashmap_create (num_b + 1, GNUNET_NO);
+
+  for (i = 0; i < num_a; i++)
+  {
+    char *data = GNUNET_malloc (element_size);
+    GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_WEAK, data, element_size);
+    GNUNET_CRYPTO_hash (data, element_size, &hash);
+    GNUNET_CONTAINER_multihashmap_put (info1.sent, &hash, data,
+                                       GNUNET_CONTAINER_MULTIHASHMAPOPTION_REPLACE);
+  }
+
+  for (i = 0; i < num_b; i++)
+  {
+    char *data = GNUNET_malloc (element_size);
+    GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_WEAK, data, element_size);
+    GNUNET_CRYPTO_hash (data, element_size, &hash);
+    GNUNET_CONTAINER_multihashmap_put (info2.sent, &hash, data,
+                                       GNUNET_CONTAINER_MULTIHASHMAPOPTION_REPLACE);
+  }
+
+  for (i = 0; i < num_c; i++)
+  {
+    char *data = GNUNET_malloc (element_size);
+    GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_WEAK, data, element_size);
+    GNUNET_CRYPTO_hash (data, element_size, &hash);
+    GNUNET_CONTAINER_multihashmap_put (common_sent, &hash, data,
+                                       GNUNET_CONTAINER_MULTIHASHMAPOPTION_REPLACE);
+  }
+
+  GNUNET_CRYPTO_hash_create_random (GNUNET_CRYPTO_QUALITY_STRONG, &app_id);
+
+  /* FIXME: also implement intersection etc. */
+  info1.set = GNUNET_SETU_create (config);
+  info2.set = GNUNET_SETU_create (config);
+
+  GNUNET_CONTAINER_multihashmap_iterate (info1.sent, set_insert_iterator,
+                                         info1.set);
+  GNUNET_CONTAINER_multihashmap_iterate (info2.sent, set_insert_iterator,
+                                         info2.set);
+  GNUNET_CONTAINER_multihashmap_iterate (common_sent, set_insert_iterator,
+                                         info1.set);
+  GNUNET_CONTAINER_multihashmap_iterate (common_sent, set_insert_iterator,
+                                         info2.set);
+
+  set_listener = GNUNET_SETU_listen (config,
+                                     &app_id,
+                                     &set_listen_cb,
+                                     NULL);
+
+
+  if (byzantine)
+  {
+    opts[n_opts++] = (struct GNUNET_SETU_Option) { .type =
+                                                     GNUNET_SETU_OPTION_BYZANTINE };
+  }
+  GNUNET_assert (! (force_full && force_delta));
+  if (force_full)
+  {
+    opts[n_opts++] = (struct GNUNET_SETU_Option) { .type =
+                                                     GNUNET_SETU_OPTION_FORCE_FULL };
+  }
+  if (force_delta)
+  {
+    opts[n_opts++] = (struct GNUNET_SETU_Option) { .type =
+                                                     GNUNET_SETU_OPTION_FORCE_DELTA };
+  }
+
+  opts[n_opts].type = 0;
+
+  info1.oh = GNUNET_SETU_prepare (&local_peer, &app_id, NULL,
+                                  opts,
+                                  set_result_cb, &info1);
+  GNUNET_SETU_commit (info1.oh, info1.set);
+  GNUNET_SETU_destroy (info1.set);
+  info1.set = NULL;
+}
+
+
+static void
+pre_run (void *cls, char *const *args, const char *cfgfile,
+         const struct GNUNET_CONFIGURATION_Handle *cfg)
+{
+  if (0 != GNUNET_TESTING_peer_run ("set-profiler",
+                                    cfgfile,
+                                    &run, NULL))
+    ret = 2;
+}
+
+
+int
+main (int argc, char **argv)
+{
+  struct GNUNET_GETOPT_CommandLineOption options[] = {
+    GNUNET_GETOPT_option_uint ('A',
+                               "num-first",
+                               NULL,
+                               gettext_noop ("number of values"),
+                               &num_a),
+
+    GNUNET_GETOPT_option_uint ('B',
+                               "num-second",
+                               NULL,
+                               gettext_noop ("number of values"),
+                               &num_b),
+
+    GNUNET_GETOPT_option_flag ('b',
+                               "byzantine",
+                               gettext_noop ("use byzantine mode"),
+                               &byzantine),
+
+    GNUNET_GETOPT_option_uint ('f',
+                               "force-full",
+                               NULL,
+                               gettext_noop ("force sending full set"),
+                               &force_full),
+
+    GNUNET_GETOPT_option_uint ('d',
+                               "force-delta",
+                               NULL,
+                               gettext_noop ("number delta operation"),
+                               &force_delta),
+
+    GNUNET_GETOPT_option_uint ('C',
+                               "num-common",
+                               NULL,
+                               gettext_noop ("number of values"),
+                               &num_c),
+
+    GNUNET_GETOPT_option_string ('x',
+                                 "operation",
+                                 NULL,
+                                 gettext_noop ("operation to execute"),
+                                 &op_str),
+
+    GNUNET_GETOPT_option_uint ('w',
+                               "element-size",
+                               NULL,
+                               gettext_noop ("element size"),
+                               &element_size),
+
+    GNUNET_GETOPT_option_filename ('s',
+                                   "statistics",
+                                   "FILENAME",
+                                   gettext_noop ("write statistics to file"),
+                                   &statistics_filename),
+
+    GNUNET_GETOPT_OPTION_END
+  };
+
+  GNUNET_PROGRAM_run2 (argc, argv, "gnunet-set-profiler",
+                       "help",
+                       options, &pre_run, NULL, GNUNET_YES);
+  return ret;
+}
diff --git a/src/setu/ibf.c b/src/setu/ibf.c
new file mode 100644
index 0000000000000000000000000000000000000000..1532afceb987d13b815a4c5b3e4c1a85c0f60f34
--- /dev/null
+++ b/src/setu/ibf.c
@@ -0,0 +1,409 @@
+/*
+      This file is part of GNUnet
+      Copyright (C) 2012 GNUnet e.V.
+
+      GNUnet is free software: you can redistribute it and/or modify it
+      under the terms of the GNU Affero General Public License as published
+      by the Free Software Foundation, either version 3 of the License,
+      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
+      Affero General Public License for more details.
+
+      You should have received a copy of the GNU Affero General Public License
+      along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+     SPDX-License-Identifier: AGPL3.0-or-later
+ */
+
+/**
+ * @file set/ibf.c
+ * @brief implementation of the invertible bloom filter
+ * @author Florian Dold
+ */
+
+#include "ibf.h"
+
+/**
+ * Compute the key's hash from the key.
+ * Redefine to use a different hash function.
+ */
+#define IBF_KEY_HASH_VAL(k) (GNUNET_CRYPTO_crc32_n (&(k), sizeof(struct \
+                                                                 IBF_KeyHash)))
+
+/**
+ * Create a key from a hashcode.
+ *
+ * @param hash the hashcode
+ * @return a key
+ */
+struct IBF_Key
+ibf_key_from_hashcode (const struct GNUNET_HashCode *hash)
+{
+  return *(struct IBF_Key *) hash;
+}
+
+
+/**
+ * Create a hashcode from a key, by replicating the key
+ * until the hascode is filled
+ *
+ * @param key the key
+ * @param dst hashcode to store the result in
+ */
+void
+ibf_hashcode_from_key (struct IBF_Key key,
+                       struct GNUNET_HashCode *dst)
+{
+  struct IBF_Key *p;
+  unsigned int i;
+  const unsigned int keys_per_hashcode = sizeof(struct GNUNET_HashCode)
+                                         / sizeof(struct IBF_Key);
+
+  p = (struct IBF_Key *) dst;
+  for (i = 0; i < keys_per_hashcode; i++)
+    *p++ = key;
+}
+
+
+/**
+ * Create an invertible bloom filter.
+ *
+ * @param size number of IBF buckets
+ * @param hash_num number of buckets one element is hashed in
+ * @return the newly created invertible bloom filter, NULL on error
+ */
+struct InvertibleBloomFilter *
+ibf_create (uint32_t size, uint8_t hash_num)
+{
+  struct InvertibleBloomFilter *ibf;
+
+  GNUNET_assert (0 != size);
+
+  ibf = GNUNET_new (struct InvertibleBloomFilter);
+  ibf->count = GNUNET_malloc_large (size * sizeof(uint8_t));
+  if (NULL == ibf->count)
+  {
+    GNUNET_free (ibf);
+    return NULL;
+  }
+  ibf->key_sum = GNUNET_malloc_large (size * sizeof(struct IBF_Key));
+  if (NULL == ibf->key_sum)
+  {
+    GNUNET_free (ibf->count);
+    GNUNET_free (ibf);
+    return NULL;
+  }
+  ibf->key_hash_sum = GNUNET_malloc_large (size * sizeof(struct IBF_KeyHash));
+  if (NULL == ibf->key_hash_sum)
+  {
+    GNUNET_free (ibf->key_sum);
+    GNUNET_free (ibf->count);
+    GNUNET_free (ibf);
+    return NULL;
+  }
+  ibf->size = size;
+  ibf->hash_num = hash_num;
+
+  return ibf;
+}
+
+
+/**
+ * Store unique bucket indices for the specified key in dst.
+ */
+static void
+ibf_get_indices (const struct InvertibleBloomFilter *ibf,
+                 struct IBF_Key key,
+                 int *dst)
+{
+  uint32_t filled;
+  uint32_t i;
+  uint32_t bucket;
+
+  bucket = GNUNET_CRYPTO_crc32_n (&key, sizeof key);
+  for (i = 0, filled = 0; filled < ibf->hash_num; i++)
+  {
+    unsigned int j;
+    uint64_t x;
+    for (j = 0; j < filled; j++)
+      if (dst[j] == bucket)
+        goto try_next;
+    dst[filled++] = bucket % ibf->size;
+try_next:;
+    x = ((uint64_t) bucket << 32) | i;
+    bucket = GNUNET_CRYPTO_crc32_n (&x, sizeof x);
+  }
+}
+
+
+static void
+ibf_insert_into (struct InvertibleBloomFilter *ibf,
+                 struct IBF_Key key,
+                 const int *buckets, int side)
+{
+  int i;
+
+  for (i = 0; i < ibf->hash_num; i++)
+  {
+    const int bucket = buckets[i];
+    ibf->count[bucket].count_val += side;
+    ibf->key_sum[bucket].key_val ^= key.key_val;
+    ibf->key_hash_sum[bucket].key_hash_val
+      ^= IBF_KEY_HASH_VAL (key);
+  }
+}
+
+
+/**
+ * Insert a key into an IBF.
+ *
+ * @param ibf the IBF
+ * @param key the element's hash code
+ */
+void
+ibf_insert (struct InvertibleBloomFilter *ibf, struct IBF_Key key)
+{
+  int buckets[ibf->hash_num];
+
+  GNUNET_assert (ibf->hash_num <= ibf->size);
+  ibf_get_indices (ibf, key, buckets);
+  ibf_insert_into (ibf, key, buckets, 1);
+}
+
+
+/**
+ * Remove a key from an IBF.
+ *
+ * @param ibf the IBF
+ * @param key the element's hash code
+ */
+void
+ibf_remove (struct InvertibleBloomFilter *ibf, struct IBF_Key key)
+{
+  int buckets[ibf->hash_num];
+
+  GNUNET_assert (ibf->hash_num <= ibf->size);
+  ibf_get_indices (ibf, key, buckets);
+  ibf_insert_into (ibf, key, buckets, -1);
+}
+
+
+/**
+ * Test is the IBF is empty, i.e. all counts, keys and key hashes are zero.
+ */
+static int
+ibf_is_empty (struct InvertibleBloomFilter *ibf)
+{
+  int i;
+
+  for (i = 0; i < ibf->size; i++)
+  {
+    if (0 != ibf->count[i].count_val)
+      return GNUNET_NO;
+    if (0 != ibf->key_hash_sum[i].key_hash_val)
+      return GNUNET_NO;
+    if (0 != ibf->key_sum[i].key_val)
+      return GNUNET_NO;
+  }
+  return GNUNET_YES;
+}
+
+
+/**
+ * Decode and remove an element from the IBF, if possible.
+ *
+ * @param ibf the invertible bloom filter to decode
+ * @param ret_side sign of the cell's count where the decoded element came from.
+ *                 A negative sign indicates that the element was recovered
+ *                 resides in an IBF that was previously subtracted from.
+ * @param ret_id receives the hash code of the decoded element, if successful
+ * @return GNUNET_YES if decoding an element was successful,
+ *         GNUNET_NO if the IBF is empty,
+ *         GNUNET_SYSERR if the decoding has failed
+ */
+int
+ibf_decode (struct InvertibleBloomFilter *ibf,
+            int *ret_side, struct IBF_Key *ret_id)
+{
+  struct IBF_KeyHash hash;
+  int i;
+  int buckets[ibf->hash_num];
+
+  GNUNET_assert (NULL != ibf);
+
+  for (i = 0; i < ibf->size; i++)
+  {
+    int j;
+    int hit;
+
+    /* we can only decode from pure buckets */
+    if ((1 != ibf->count[i].count_val) && (-1 != ibf->count[i].count_val))
+      continue;
+
+    hash.key_hash_val = IBF_KEY_HASH_VAL (ibf->key_sum[i]);
+
+    /* test if the hash matches the key */
+    if (hash.key_hash_val != ibf->key_hash_sum[i].key_hash_val)
+      continue;
+
+    /* test if key in bucket hits its own location,
+     * if not, the key hash was subject to collision */
+    hit = GNUNET_NO;
+    ibf_get_indices (ibf, ibf->key_sum[i], buckets);
+    for (j = 0; j < ibf->hash_num; j++)
+      if (buckets[j] == i)
+        hit = GNUNET_YES;
+
+    if (GNUNET_NO == hit)
+      continue;
+
+    if (NULL != ret_side)
+      *ret_side = ibf->count[i].count_val;
+    if (NULL != ret_id)
+      *ret_id = ibf->key_sum[i];
+
+    /* insert on the opposite side, effectively removing the element */
+    ibf_insert_into (ibf, ibf->key_sum[i], buckets, -ibf->count[i].count_val);
+
+    return GNUNET_YES;
+  }
+
+  if (GNUNET_YES == ibf_is_empty (ibf))
+    return GNUNET_NO;
+  return GNUNET_SYSERR;
+}
+
+
+/**
+ * Write buckets from an ibf to a buffer.
+ * Exactly (IBF_BUCKET_SIZE*ibf->size) bytes are written to buf.
+ *
+ * @param ibf the ibf to write
+ * @param start with which bucket to start
+ * @param count how many buckets to write
+ * @param buf buffer to write the data to
+ */
+void
+ibf_write_slice (const struct InvertibleBloomFilter *ibf, uint32_t start,
+                 uint32_t count, void *buf)
+{
+  struct IBF_Key *key_dst;
+  struct IBF_KeyHash *key_hash_dst;
+  struct IBF_Count *count_dst;
+
+  GNUNET_assert (start + count <= ibf->size);
+
+  /* copy keys */
+  key_dst = (struct IBF_Key *) buf;
+  GNUNET_memcpy (key_dst, ibf->key_sum + start, count * sizeof *key_dst);
+  key_dst += count;
+  /* copy key hashes */
+  key_hash_dst = (struct IBF_KeyHash *) key_dst;
+  GNUNET_memcpy (key_hash_dst, ibf->key_hash_sum + start, count
+                 * sizeof *key_hash_dst);
+  key_hash_dst += count;
+  /* copy counts */
+  count_dst = (struct IBF_Count *) key_hash_dst;
+  GNUNET_memcpy (count_dst, ibf->count + start, count * sizeof *count_dst);
+}
+
+
+/**
+ * Read buckets from a buffer into an ibf.
+ *
+ * @param buf pointer to the buffer to read from
+ * @param start which bucket to start at
+ * @param count how many buckets to read
+ * @param ibf the ibf to read from
+ */
+void
+ibf_read_slice (const void *buf, uint32_t start, uint32_t count, struct
+                InvertibleBloomFilter *ibf)
+{
+  struct IBF_Key *key_src;
+  struct IBF_KeyHash *key_hash_src;
+  struct IBF_Count *count_src;
+
+  GNUNET_assert (count > 0);
+  GNUNET_assert (start + count <= ibf->size);
+
+  /* copy keys */
+  key_src = (struct IBF_Key *) buf;
+  GNUNET_memcpy (ibf->key_sum + start, key_src, count * sizeof *key_src);
+  key_src += count;
+  /* copy key hashes */
+  key_hash_src = (struct IBF_KeyHash *) key_src;
+  GNUNET_memcpy (ibf->key_hash_sum + start, key_hash_src, count
+                 * sizeof *key_hash_src);
+  key_hash_src += count;
+  /* copy counts */
+  count_src = (struct IBF_Count *) key_hash_src;
+  GNUNET_memcpy (ibf->count + start, count_src, count * sizeof *count_src);
+}
+
+
+/**
+ * Subtract ibf2 from ibf1, storing the result in ibf1.
+ * The two IBF's must have the same parameters size and hash_num.
+ *
+ * @param ibf1 IBF that is subtracted from
+ * @param ibf2 IBF that will be subtracted from ibf1
+ */
+void
+ibf_subtract (struct InvertibleBloomFilter *ibf1, const struct
+              InvertibleBloomFilter *ibf2)
+{
+  int i;
+
+  GNUNET_assert (ibf1->size == ibf2->size);
+  GNUNET_assert (ibf1->hash_num == ibf2->hash_num);
+
+  for (i = 0; i < ibf1->size; i++)
+  {
+    ibf1->count[i].count_val -= ibf2->count[i].count_val;
+    ibf1->key_hash_sum[i].key_hash_val ^= ibf2->key_hash_sum[i].key_hash_val;
+    ibf1->key_sum[i].key_val ^= ibf2->key_sum[i].key_val;
+  }
+}
+
+
+/**
+ * Create a copy of an IBF, the copy has to be destroyed properly.
+ *
+ * @param ibf the IBF to copy
+ */
+struct InvertibleBloomFilter *
+ibf_dup (const struct InvertibleBloomFilter *ibf)
+{
+  struct InvertibleBloomFilter *copy;
+
+  copy = GNUNET_malloc (sizeof *copy);
+  copy->hash_num = ibf->hash_num;
+  copy->size = ibf->size;
+  copy->key_hash_sum = GNUNET_memdup (ibf->key_hash_sum, ibf->size
+                                      * sizeof(struct IBF_KeyHash));
+  copy->key_sum = GNUNET_memdup (ibf->key_sum, ibf->size * sizeof(struct
+                                                                  IBF_Key));
+  copy->count = GNUNET_memdup (ibf->count, ibf->size * sizeof(struct
+                                                              IBF_Count));
+  return copy;
+}
+
+
+/**
+ * Destroy all resources associated with the invertible bloom filter.
+ * No more ibf_*-functions may be called on ibf after calling destroy.
+ *
+ * @param ibf the intertible bloom filter to destroy
+ */
+void
+ibf_destroy (struct InvertibleBloomFilter *ibf)
+{
+  GNUNET_free (ibf->key_sum);
+  GNUNET_free (ibf->key_hash_sum);
+  GNUNET_free (ibf->count);
+  GNUNET_free (ibf);
+}
diff --git a/src/setu/ibf.h b/src/setu/ibf.h
new file mode 100644
index 0000000000000000000000000000000000000000..7c2ab33b14a8d78efa346ce80d8b751c0bdad1df
--- /dev/null
+++ b/src/setu/ibf.h
@@ -0,0 +1,255 @@
+/*
+      This file is part of GNUnet
+      Copyright (C) 2012 GNUnet e.V.
+
+      GNUnet is free software: you can redistribute it and/or modify it
+      under the terms of the GNU Affero General Public License as published
+      by the Free Software Foundation, either version 3 of the License,
+      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
+      Affero General Public License for more details.
+
+      You should have received a copy of the GNU Affero General Public License
+      along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+     SPDX-License-Identifier: AGPL3.0-or-later
+ */
+
+/**
+ * @file set/ibf.h
+ * @brief invertible bloom filter
+ * @author Florian Dold
+ */
+
+#ifndef GNUNET_CONSENSUS_IBF_H
+#define GNUNET_CONSENSUS_IBF_H
+
+#include "platform.h"
+#include "gnunet_util_lib.h"
+
+#ifdef __cplusplus
+extern "C"
+{
+#if 0                           /* keep Emacsens' auto-indent happy */
+}
+#endif
+#endif
+
+
+/**
+ * Keys that can be inserted into and removed from an IBF.
+ */
+struct IBF_Key
+{
+  uint64_t key_val;
+};
+
+
+/**
+ * Hash of an IBF key.
+ */
+struct IBF_KeyHash
+{
+  uint32_t key_hash_val;
+};
+
+
+/**
+ * Type of the count field of IBF buckets.
+ */
+struct IBF_Count
+{
+  int8_t count_val;
+};
+
+
+/**
+ * Size of one ibf bucket in bytes
+ */
+#define IBF_BUCKET_SIZE (sizeof(struct IBF_Count) + sizeof(struct IBF_Key)   \
+                         + sizeof(struct IBF_KeyHash))
+
+
+/**
+ * Invertible bloom filter (IBF).
+ *
+ * An IBF is a counting bloom filter that has the ability to restore
+ * the hashes of its stored elements with high probability.
+ */
+struct InvertibleBloomFilter
+{
+  /**
+   * How many cells does this IBF have?
+   */
+  uint32_t size;
+
+  /**
+   * In how many cells do we hash one element?
+   * Usually 4 or 3.
+   */
+  uint8_t hash_num;
+
+  /**
+   * Xor sums of the elements' keys, used to identify the elements.
+   * Array of 'size' elements.
+   */
+  struct IBF_Key *key_sum;
+
+  /**
+   * Xor sums of the hashes of the keys of inserted elements.
+   * Array of 'size' elements.
+   */
+  struct IBF_KeyHash *key_hash_sum;
+
+  /**
+   * How many times has a bucket been hit?
+   * Can be negative, as a result of IBF subtraction.
+   * Array of 'size' elements.
+   */
+  struct IBF_Count *count;
+};
+
+
+/**
+ * Write buckets from an ibf to a buffer.
+ * Exactly (IBF_BUCKET_SIZE*ibf->size) bytes are written to buf.
+ *
+ * @param ibf the ibf to write
+ * @param start with which bucket to start
+ * @param count how many buckets to write
+ * @param buf buffer to write the data to
+ */
+void
+ibf_write_slice (const struct InvertibleBloomFilter *ibf,
+                 uint32_t start,
+                 uint32_t count,
+                 void *buf);
+
+
+/**
+ * Read buckets from a buffer into an ibf.
+ *
+ * @param buf pointer to the buffer to read from
+ * @param start which bucket to start at
+ * @param count how many buckets to read
+ * @param ibf the ibf to write to
+ */
+void
+ibf_read_slice (const void *buf,
+                uint32_t start,
+                uint32_t count,
+                struct InvertibleBloomFilter *ibf);
+
+
+/**
+ * Create a key from a hashcode.
+ *
+ * @param hash the hashcode
+ * @return a key
+ */
+struct IBF_Key
+ibf_key_from_hashcode (const struct GNUNET_HashCode *hash);
+
+
+/**
+ * Create a hashcode from a key, by replicating the key
+ * until the hascode is filled
+ *
+ * @param key the key
+ * @param dst hashcode to store the result in
+ */
+void
+ibf_hashcode_from_key (struct IBF_Key key, struct GNUNET_HashCode *dst);
+
+
+/**
+ * Create an invertible bloom filter.
+ *
+ * @param size number of IBF buckets
+ * @param hash_num number of buckets one element is hashed in, usually 3 or 4
+ * @return the newly created invertible bloom filter, NULL on error
+ */
+struct InvertibleBloomFilter *
+ibf_create (uint32_t size, uint8_t hash_num);
+
+
+/**
+ * Insert a key into an IBF.
+ *
+ * @param ibf the IBF
+ * @param key the element's hash code
+ */
+void
+ibf_insert (struct InvertibleBloomFilter *ibf, struct IBF_Key key);
+
+
+/**
+ * Remove a key from an IBF.
+ *
+ * @param ibf the IBF
+ * @param key the element's hash code
+ */
+void
+ibf_remove (struct InvertibleBloomFilter *ibf, struct IBF_Key key);
+
+
+/**
+ * Subtract ibf2 from ibf1, storing the result in ibf1.
+ * The two IBF's must have the same parameters size and hash_num.
+ *
+ * @param ibf1 IBF that is subtracted from
+ * @param ibf2 IBF that will be subtracted from ibf1
+ */
+void
+ibf_subtract (struct InvertibleBloomFilter *ibf1,
+              const struct InvertibleBloomFilter *ibf2);
+
+
+/**
+ * Decode and remove an element from the IBF, if possible.
+ *
+ * @param ibf the invertible bloom filter to decode
+ * @param ret_side sign of the cell's count where the decoded element came from.
+ *                 A negative sign indicates that the element was recovered
+ *                 resides in an IBF that was previously subtracted from.
+ * @param ret_id receives the hash code of the decoded element, if successful
+ * @return #GNUNET_YES if decoding an element was successful,
+ *         #GNUNET_NO if the IBF is empty,
+ *         #GNUNET_SYSERR if the decoding has failed
+ */
+int
+ibf_decode (struct InvertibleBloomFilter *ibf,
+            int *ret_side,
+            struct IBF_Key *ret_id);
+
+
+/**
+ * Create a copy of an IBF, the copy has to be destroyed properly.
+ *
+ * @param ibf the IBF to copy
+ */
+struct InvertibleBloomFilter *
+ibf_dup (const struct InvertibleBloomFilter *ibf);
+
+
+/**
+ * Destroy all resources associated with the invertible bloom filter.
+ * No more ibf_*-functions may be called on ibf after calling destroy.
+ *
+ * @param ibf the intertible bloom filter to destroy
+ */
+void
+ibf_destroy (struct InvertibleBloomFilter *ibf);
+
+
+#if 0                           /* keep Emacsens' auto-indent happy */
+{
+#endif
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/src/setu/ibf_sim.c b/src/setu/ibf_sim.c
new file mode 100644
index 0000000000000000000000000000000000000000..6415d00e1d665af0626ae1f2b27967c98071c6f1
--- /dev/null
+++ b/src/setu/ibf_sim.c
@@ -0,0 +1,142 @@
+/*
+      This file is part of GNUnet
+      Copyright (C) 2013 GNUnet e.V.
+
+      GNUnet is free software: you can redistribute it and/or modify it
+      under the terms of the GNU Affero General Public License as published
+      by the Free Software Foundation, either version 3 of the License,
+      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
+      Affero General Public License for more details.
+
+      You should have received a copy of the GNU Affero General Public License
+      along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+     SPDX-License-Identifier: AGPL3.0-or-later
+ */
+
+/**
+ * @file set/ibf_sim.c
+ * @brief implementation of simulation for invertible bloom filter
+ * @author Florian Dold
+ *
+ * This code was used for some internal experiments, it is not
+ * build or shipped as part of the GNUnet system.
+ */
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#define MAX_IBF_DECODE 16
+
+/* report average over how many rounds? */
+#define ROUNDS 100000
+
+/* enable one of the three below */
+// simple fix
+#define FIX1 0
+// possibly slightly better fix for large IBF_DECODE values
+#define FIX2 1
+
+// SIGCOMM algorithm
+#define STRATA 0
+
+// print each value?
+#define VERBOSE 0
+// avoid assembly? (ASM is about 50% faster)
+#define SLOW 0
+
+int
+main (int argc, char **argv)
+{
+  unsigned int round;
+  unsigned int buckets[31]; // max is 2^31 as 'random' returns only between 0 and 2^31
+  unsigned int i;
+  int j;
+  unsigned int r;
+  unsigned int ret;
+  unsigned long long total;
+  unsigned int want;
+  double predict;
+
+  srandom (time (NULL));
+  total = 0;
+  want = atoi (argv[1]);
+  for (round = 0; round < ROUNDS; round++)
+  {
+    memset (buckets, 0, sizeof(buckets));
+    for (i = 0; i < want; i++)
+    {
+      /* FIXME: might want to use 'better' PRNG to avoid
+         PRNG-induced biases */
+      r = random ();
+      if (0 == r)
+        continue;
+#if SLOW
+      for (j = 0; (j < 31) && (0 == (r & (1 << j))); j++)
+        ;
+#else
+      /* use assembly / gcc */
+      j = __builtin_ffs (r) - 1;
+#endif
+      buckets[j]++;
+    }
+    ret = 0;
+    predict = 0.0;
+    for (j = 31; j >= 0; j--)
+    {
+#if FIX1
+      /* improved algorithm, for 1000 elements with IBF-DECODE 8, I
+         get 990/1000 elements on average over 1 million runs; key
+         idea being to stop short of the 'last' possible IBF as
+         otherwise a "lowball" per-chance would unduely influence the
+         result */if ((j > 0) &&
+          (buckets[j - 1] > MAX_IBF_DECODE))
+      {
+        ret *= (1 << (j + 1));
+        break;
+      }
+#endif
+#if FIX2
+      /* another improvement: don't just always cut off the last one,
+         but rather try to predict based on all previous values where
+         that "last" one is; additional prediction can only really
+         work if MAX_IBF_DECODE is sufficiently high */
+      if ((j > 0) &&
+          ((buckets[j - 1] > MAX_IBF_DECODE) ||
+           (predict > MAX_IBF_DECODE)))
+      {
+        ret *= (1 << (j + 1));
+        break;
+      }
+#endif
+#if STRATA
+      /* original algorithm, for 1000 elements with IBF-DECODE 8,
+         I get 920/1000 elements on average over 1 million runs */
+      if (buckets[j] > MAX_IBF_DECODE)
+      {
+        ret *= (1 << (j + 1));
+        break;
+      }
+#endif
+      ret += buckets[j];
+      predict = (buckets[j] + 2.0 * predict) / 2.0;
+    }
+#if VERBOSE
+    fprintf (stderr, "%u ", ret);
+#endif
+    total += ret;
+  }
+  fprintf (stderr, "\n");
+  fprintf (stdout, "average %llu\n", total / ROUNDS);
+  return 0;
+}
+
+
+/* TODO: should calculate stddev of the results to also be able to
+   say something about the stability of the results, outside of
+   large-scale averages -- gaining 8% precision at the expense of
+   50% additional variance might not be worth it... */
diff --git a/src/setu/plugin_block_setu_test.c b/src/setu/plugin_block_setu_test.c
new file mode 100644
index 0000000000000000000000000000000000000000..fd0c8a680f5e53eb5052b90bc0d2af19554d80a9
--- /dev/null
+++ b/src/setu/plugin_block_setu_test.c
@@ -0,0 +1,123 @@
+/*
+     This file is part of GNUnet
+     Copyright (C) 2017 GNUnet e.V.
+
+     GNUnet is free software: you can redistribute it and/or modify it
+     under the terms of the GNU Affero General Public License as published
+     by the Free Software Foundation, either version 3 of the License,
+     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
+     Affero General Public License for more details.
+
+     You should have received a copy of the GNU Affero General Public License
+     along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+     SPDX-License-Identifier: AGPL3.0-or-later
+ */
+
+/**
+ * @file setu/plugin_block_setu_test.c
+ * @brief set test block, recognizes elements with non-zero first byte as invalid
+ * @author Christian Grothoff
+ */
+
+#include "platform.h"
+#include "gnunet_block_plugin.h"
+#include "gnunet_block_group_lib.h"
+
+
+/**
+ * Function called to validate a reply or a request.  For
+ * request evaluation, simply pass "NULL" for the reply_block.
+ *
+ * @param cls closure
+ * @param ctx block context
+ * @param type block type
+ * @param group block group to use
+ * @param eo control flags
+ * @param query original query (hash)
+ * @param xquery extrended query data (can be NULL, depending on type)
+ * @param xquery_size number of bytes in xquery
+ * @param reply_block response to validate
+ * @param reply_block_size number of bytes in reply block
+ * @return characterization of result
+ */
+static enum GNUNET_BLOCK_EvaluationResult
+block_plugin_setu_test_evaluate (void *cls,
+                                 struct GNUNET_BLOCK_Context *ctx,
+                                 enum GNUNET_BLOCK_Type type,
+                                 struct GNUNET_BLOCK_Group *group,
+                                 enum GNUNET_BLOCK_EvaluationOptions eo,
+                                 const struct GNUNET_HashCode *query,
+                                 const void *xquery,
+                                 size_t xquery_size,
+                                 const void *reply_block,
+                                 size_t reply_block_size)
+{
+  if ((NULL == reply_block) ||
+      (reply_block_size == 0) ||
+      (0 != ((char *) reply_block)[0]))
+    return GNUNET_BLOCK_EVALUATION_RESULT_INVALID;
+  return GNUNET_BLOCK_EVALUATION_OK_MORE;
+}
+
+
+/**
+ * Function called to obtain the key for a block.
+ *
+ * @param cls closure
+ * @param type block type
+ * @param block block to get the key for
+ * @param block_size number of bytes in block
+ * @param key set to the key (query) for the given block
+ * @return #GNUNET_OK on success, #GNUNET_SYSERR if type not supported
+ *         (or if extracting a key from a block of this type does not work)
+ */
+static int
+block_plugin_setu_test_get_key (void *cls,
+                                enum GNUNET_BLOCK_Type type,
+                                const void *block,
+                                size_t block_size,
+                                struct GNUNET_HashCode *key)
+{
+  return GNUNET_SYSERR;
+}
+
+
+/**
+ * Entry point for the plugin.
+ */
+void *
+libgnunet_plugin_block_setu_test_init (void *cls)
+{
+  static enum GNUNET_BLOCK_Type types[] = {
+    GNUNET_BLOCK_TYPE_SETU_TEST,
+    GNUNET_BLOCK_TYPE_ANY       /* end of list */
+  };
+  struct GNUNET_BLOCK_PluginFunctions *api;
+
+  api = GNUNET_new (struct GNUNET_BLOCK_PluginFunctions);
+  api->evaluate = &block_plugin_setu_test_evaluate;
+  api->get_key = &block_plugin_setu_test_get_key;
+  api->types = types;
+  return api;
+}
+
+
+/**
+ * Exit point from the plugin.
+ */
+void *
+libgnunet_plugin_block_setu_test_done (void *cls)
+{
+  struct GNUNET_BLOCK_PluginFunctions *api = cls;
+
+  GNUNET_free (api);
+  return NULL;
+}
+
+
+/* end of plugin_block_setu_test.c */
diff --git a/src/setu/setu.conf.in b/src/setu/setu.conf.in
new file mode 100644
index 0000000000000000000000000000000000000000..6c48f6156557a9aa3e3991366a61170879a0fb6f
--- /dev/null
+++ b/src/setu/setu.conf.in
@@ -0,0 +1,12 @@
+[setu]
+START_ON_DEMAND = @START_ON_DEMAND@
+@UNIXONLY@PORT = 2106
+HOSTNAME = localhost
+BINARY = gnunet-service-setu
+ACCEPT_FROM = 127.0.0.1;
+ACCEPT_FROM6 = ::1;
+UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-service-setu.sock
+UNIX_MATCH_UID = YES
+UNIX_MATCH_GID = YES
+
+#PREFIX = valgrind
diff --git a/src/setu/setu.h b/src/setu/setu.h
new file mode 100644
index 0000000000000000000000000000000000000000..e9a0def95bab1fb92c5dfb0e535ff65fc1994903
--- /dev/null
+++ b/src/setu/setu.h
@@ -0,0 +1,315 @@
+/*
+     This file is part of GNUnet.
+     Copyright (C) 2012-2014, 2020 GNUnet e.V.
+
+     GNUnet is free software: you can redistribute it and/or modify it
+     under the terms of the GNU Affero General Public License as published
+     by the Free Software Foundation, either version 3 of the License,
+     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
+     Affero General Public License for more details.
+
+     You should have received a copy of the GNU Affero General Public License
+     along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+     SPDX-License-Identifier: AGPL3.0-or-later
+ */
+/**
+ * @file set/set.h
+ * @brief messages used for the set union api
+ * @author Florian Dold
+ * @author Christian Grothoff
+ */
+#ifndef SET_H
+#define SET_H
+
+#include "platform.h"
+#include "gnunet_common.h"
+#include "gnunet_set_service.h"
+
+GNUNET_NETWORK_STRUCT_BEGIN
+
+/**
+ * Message sent by the client to the service to ask starting
+ * a new set to perform operations with.  Includes the desired
+ * set operation type.
+ */
+struct GNUNET_SETU_CreateMessage
+{
+  /**
+   * Type: #GNUNET_MESSAGE_TYPE_SETU_CREATE
+   */
+  struct GNUNET_MessageHeader header;
+
+};
+
+
+/**
+ * Message sent by the client to the service to start listening for
+ * incoming requests to perform a certain type of set operation for a
+ * certain type of application.
+ */
+struct GNUNET_SETU_ListenMessage
+{
+  /**
+   * Type: #GNUNET_MESSAGE_TYPE_SETU_LISTEN
+   */
+  struct GNUNET_MessageHeader header;
+
+  /**
+   * Always zero.
+   */
+  uint32_t reserved GNUNET_PACKED;
+
+  /**
+   * application id
+   */
+  struct GNUNET_HashCode app_id;
+};
+
+
+/**
+ * Message sent by a listening client to the service to accept
+ * performing the operation with the other peer.
+ */
+struct GNUNET_SETU_AcceptMessage
+{
+  /**
+   * Type: #GNUNET_MESSAGE_TYPE_SETU_ACCEPT
+   */
+  struct GNUNET_MessageHeader header;
+
+  /**
+   * ID of the incoming request we want to accept.
+   */
+  uint32_t accept_reject_id GNUNET_PACKED;
+
+  /**
+   * Request ID to identify responses.
+   */
+  uint32_t request_id GNUNET_PACKED;
+
+  /**
+   * Always use delta operation instead of sending full sets,
+   * even it it's less efficient.
+   */
+  uint8_t force_delta;
+
+  /**
+   * Always send full sets, even if delta operations would
+   * be more efficient.
+   */
+  uint8_t force_full;
+
+  /**
+   * #GNUNET_YES to fail operations where Byzantine faults
+   * are suspected
+   */
+  uint8_t byzantine;
+
+  /**
+   * #GNUNET_YES to also send back set elements we are sending to
+   * the remote peer.
+   */
+  uint8_t symmetric;
+
+  /**
+   * Lower bound for the set size, used only when
+   * byzantine mode is enabled.
+   */
+  uint32_t byzantine_lower_bound;
+};
+
+
+/**
+ * Message sent by a listening client to the service to reject
+ * performing the operation with the other peer.
+ */
+struct GNUNET_SETU_RejectMessage
+{
+  /**
+   * Type: #GNUNET_MESSAGE_TYPE_SETU_REJECT
+   */
+  struct GNUNET_MessageHeader header;
+
+  /**
+   * ID of the incoming request we want to reject.
+   */
+  uint32_t accept_reject_id GNUNET_PACKED;
+};
+
+
+/**
+ * A request for an operation with another client.
+ */
+struct GNUNET_SETU_RequestMessage
+{
+  /**
+   * Type: #GNUNET_MESSAGE_TYPE_SETU_REQUEST.
+   */
+  struct GNUNET_MessageHeader header;
+
+  /**
+   * ID of the to identify the request when accepting or
+   * rejecting it.
+   */
+  uint32_t accept_id GNUNET_PACKED;
+
+  /**
+   * Identity of the requesting peer.
+   */
+  struct GNUNET_PeerIdentity peer_id;
+
+  /* rest: context message, that is, application-specific
+     message to convince listener to pick up */
+};
+
+
+/**
+ * Message sent by client to service to initiate a set operation as a
+ * client (not as listener).  A set (which determines the operation
+ * type) must already exist in association with this client.
+ */
+struct GNUNET_SETU_EvaluateMessage
+{
+  /**
+   * Type: #GNUNET_MESSAGE_TYPE_SETU_EVALUATE
+   */
+  struct GNUNET_MessageHeader header;
+
+  /**
+   * Id of our set to evaluate, chosen implicitly by the client when it
+   * calls #GNUNET_SETU_commit().
+   */
+  uint32_t request_id GNUNET_PACKED;
+
+  /**
+   * Peer to evaluate the operation with
+   */
+  struct GNUNET_PeerIdentity target_peer;
+
+  /**
+   * Application id
+   */
+  struct GNUNET_HashCode app_id;
+
+  /**
+   * Always use delta operation instead of sending full sets,
+   * even it it's less efficient.
+   */
+  uint8_t force_delta;
+
+  /**
+   * Always send full sets, even if delta operations would
+   * be more efficient.
+   */
+  uint8_t force_full;
+
+  /**
+   * #GNUNET_YES to fail operations where Byzantine faults
+   * are suspected
+   */
+  uint8_t byzantine;
+
+  /**
+   * Also return set elements we are sending to the remote peer.
+   */
+  uint8_t symmetric;
+
+  /**
+   * Lower bound for the set size, used only when
+   * byzantine mode is enabled.
+   */
+  uint32_t byzantine_lower_bound;
+
+  /* rest: context message, that is, application-specific
+     message to convince listener to pick up */
+};
+
+
+/**
+ * Message sent by the service to the client to indicate an
+ * element that is removed (set intersection) or added
+ * (set union) or part of the final result, depending on
+ * options specified for the operation.
+ */
+struct GNUNET_SETU_ResultMessage
+{
+  /**
+   * Type: #GNUNET_MESSAGE_TYPE_SETU_RESULT
+   */
+  struct GNUNET_MessageHeader header;
+
+  /**
+   * Current set size.
+   */
+  uint64_t current_size;
+
+  /**
+   * id the result belongs to
+   */
+  uint32_t request_id GNUNET_PACKED;
+
+  /**
+   * Was the evaluation successful? Contains
+   * an `enum GNUNET_SETU_Status` in NBO.
+   */
+  uint16_t result_status GNUNET_PACKED;
+
+  /**
+   * Type of the element attachted to the message, if any.
+   */
+  uint16_t element_type GNUNET_PACKED;
+
+  /* rest: the actual element */
+};
+
+
+/**
+ * Message sent by client to the service to add
+ * an element to the set.
+ */
+struct GNUNET_SETU_ElementMessage
+{
+  /**
+   * Type: #GNUNET_MESSAGE_TYPE_SETU_ADD
+   */
+  struct GNUNET_MessageHeader header;
+
+  /**
+   * Type of the element to add or remove.
+   */
+  uint16_t element_type GNUNET_PACKED;
+
+  /**
+   * For alignment, always zero.
+   */
+  uint16_t reserved GNUNET_PACKED;
+
+  /* rest: the actual element */
+};
+
+
+/**
+ * Sent to the service by the client in order to cancel a set operation.
+ */
+struct GNUNET_SETU_CancelMessage
+{
+  /**
+   * Type: #GNUNET_MESSAGE_TYPE_SETU_CANCEL
+   */
+  struct GNUNET_MessageHeader header;
+
+  /**
+   * ID of the request we want to cancel.
+   */
+  uint32_t request_id GNUNET_PACKED;
+};
+
+
+GNUNET_NETWORK_STRUCT_END
+
+#endif
diff --git a/src/setu/setu_api.c b/src/setu/setu_api.c
new file mode 100644
index 0000000000000000000000000000000000000000..dd3a4a769db135d68da9ad2729ad035ef2d3ab66
--- /dev/null
+++ b/src/setu/setu_api.c
@@ -0,0 +1,897 @@
+/*
+     This file is part of GNUnet.
+     Copyright (C) 2012-2016, 2020 GNUnet e.V.
+
+     GNUnet is free software: you can redistribute it and/or modify it
+     under the terms of the GNU Affero General Public License as published
+     by the Free Software Foundation, either version 3 of the License,
+     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
+     Affero General Public License for more details.
+
+     You should have received a copy of the GNU Affero General Public License
+     along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+     SPDX-License-Identifier: AGPL3.0-or-later
+ */
+/**
+ * @file set/setu_api.c
+ * @brief api for the set union service
+ * @author Florian Dold
+ * @author Christian Grothoff
+ */
+#include "platform.h"
+#include "gnunet_util_lib.h"
+#include "gnunet_protocols.h"
+#include "gnunet_setu_service.h"
+#include "setu.h"
+
+
+#define LOG(kind, ...) GNUNET_log_from (kind, "set-api", __VA_ARGS__)
+
+/**
+ * Opaque handle to a set.
+ */
+struct GNUNET_SETU_Handle
+{
+  /**
+   * Message queue for @e client.
+   */
+  struct GNUNET_MQ_Handle *mq;
+
+  /**
+   * Linked list of operations on the set.
+   */
+  struct GNUNET_SETU_OperationHandle *ops_head;
+
+  /**
+   * Linked list of operations on the set.
+   */
+  struct GNUNET_SETU_OperationHandle *ops_tail;
+
+  /**
+   * Should the set be destroyed once all operations are gone?
+   * #GNUNET_SYSERR if #GNUNET_SETU_destroy() must raise this flag,
+   * #GNUNET_YES if #GNUNET_SETU_destroy() did raise this flag.
+   */
+  int destroy_requested;
+
+  /**
+   * Has the set become invalid (e.g. service died)?
+   */
+  int invalid;
+
+};
+
+
+/**
+ * Handle for a set operation request from another peer.
+ */
+struct GNUNET_SETU_Request
+{
+  /**
+   * Id of the request, used to identify the request when
+   * accepting/rejecting it.
+   */
+  uint32_t accept_id;
+
+  /**
+   * Has the request been accepted already?
+   * #GNUNET_YES/#GNUNET_NO
+   */
+  int accepted;
+};
+
+
+/**
+ * Handle to an operation.  Only known to the service after committing
+ * the handle with a set.
+ */
+struct GNUNET_SETU_OperationHandle
+{
+  /**
+   * Function to be called when we have a result,
+   * or an error.
+   */
+  GNUNET_SETU_ResultIterator result_cb;
+
+  /**
+   * Closure for @e result_cb.
+   */
+  void *result_cls;
+
+  /**
+   * Local set used for the operation,
+   * NULL if no set has been provided by conclude yet.
+   */
+  struct GNUNET_SETU_Handle *set;
+
+  /**
+   * Message sent to the server on calling conclude,
+   * NULL if conclude has been called.
+   */
+  struct GNUNET_MQ_Envelope *conclude_mqm;
+
+  /**
+   * Address of the request if in the conclude message,
+   * used to patch the request id into the message when the set is known.
+   */
+  uint32_t *request_id_addr;
+
+  /**
+   * Handles are kept in a linked list.
+   */
+  struct GNUNET_SETU_OperationHandle *prev;
+
+  /**
+   * Handles are kept in a linked list.
+   */
+  struct GNUNET_SETU_OperationHandle *next;
+
+  /**
+   * Request ID to identify the operation within the set.
+   */
+  uint32_t request_id;
+};
+
+
+/**
+ * Opaque handle to a listen operation.
+ */
+struct GNUNET_SETU_ListenHandle
+{
+  /**
+   * Message queue for the client.
+   */
+  struct GNUNET_MQ_Handle*mq;
+
+  /**
+   * Configuration handle for the listener, stored
+   * here to be able to reconnect transparently on
+   * connection failure.
+   */
+  const struct GNUNET_CONFIGURATION_Handle *cfg;
+
+  /**
+   * Function to call on a new incoming request,
+   * or on error.
+   */
+  GNUNET_SETU_ListenCallback listen_cb;
+
+  /**
+   * Closure for @e listen_cb.
+   */
+  void *listen_cls;
+
+  /**
+   * Application ID we listen for.
+   */
+  struct GNUNET_HashCode app_id;
+
+  /**
+   * Time to wait until we try to reconnect on failure.
+   */
+  struct GNUNET_TIME_Relative reconnect_backoff;
+
+  /**
+   * Task for reconnecting when the listener fails.
+   */
+  struct GNUNET_SCHEDULER_Task *reconnect_task;
+
+};
+
+
+/**
+ * Check that the given @a msg is well-formed.
+ *
+ * @param cls closure
+ * @param msg message to check
+ * @return #GNUNET_OK if message is well-formed
+ */
+static int
+check_result (void *cls,
+              const struct GNUNET_SETU_ResultMessage *msg)
+{
+  /* minimum size was already checked, everything else is OK! */
+  return GNUNET_OK;
+}
+
+
+/**
+ * Handle result message for a set operation.
+ *
+ * @param cls the set
+ * @param mh the message
+ */
+static void
+handle_result (void *cls,
+               const struct GNUNET_SETU_ResultMessage *msg)
+{
+  struct GNUNET_SETU_Handle *set = cls;
+  struct GNUNET_SETU_OperationHandle *oh;
+  struct GNUNET_SETU_Element e;
+  enum GNUNET_SETU_Status result_status;
+  int destroy_set;
+
+  GNUNET_assert (NULL != set->mq);
+  result_status = (enum GNUNET_SETU_Status) ntohs (msg->result_status);
+  LOG (GNUNET_ERROR_TYPE_DEBUG,
+       "Got result message with status %d\n",
+       result_status);
+  oh = GNUNET_MQ_assoc_get (set->mq,
+                            ntohl (msg->request_id));
+  if (NULL == oh)
+  {
+    /* 'oh' can be NULL if we canceled the operation, but the service
+       did not get the cancel message yet. */
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                "Ignoring result from canceled operation\n");
+    return;
+  }
+
+  switch (result_status)
+  {
+  case GNUNET_SETU_STATUS_ADD_LOCAL:
+  case GNUNET_SETU_STATUS_ADD_REMOTE:
+    e.data = &msg[1];
+    e.size = ntohs (msg->header.size)
+             - sizeof(struct GNUNET_SETU_ResultMessage);
+    e.element_type = ntohs (msg->element_type);
+    if (NULL != oh->result_cb)
+      oh->result_cb (oh->result_cls,
+                     &e,
+                     GNUNET_ntohll (msg->current_size),
+                     result_status);
+    return;
+  case GNUNET_SETU_STATUS_FAILURE:
+  case GNUNET_SETU_STATUS_DONE:
+    LOG (GNUNET_ERROR_TYPE_DEBUG,
+         "Treating result as final status\n");
+    GNUNET_MQ_assoc_remove (set->mq,
+                            ntohl (msg->request_id));
+    GNUNET_CONTAINER_DLL_remove (set->ops_head,
+                                 set->ops_tail,
+                                 oh);
+    /* Need to do this calculation _before_ the result callback,
+       as IF the application still has a valid set handle, it
+       may trigger destruction of the set during the callback. */
+    destroy_set = (GNUNET_YES == set->destroy_requested) &&
+                  (NULL == set->ops_head);
+    if (NULL != oh->result_cb)
+    {
+      oh->result_cb (oh->result_cls,
+                     NULL,
+                     GNUNET_ntohll (msg->current_size),
+                     result_status);
+    }
+    else
+    {
+      LOG (GNUNET_ERROR_TYPE_DEBUG,
+           "No callback for final status\n");
+    }
+    if (destroy_set)
+      GNUNET_SETU_destroy (set);
+    GNUNET_free (oh);
+    return;
+  }
+}
+
+
+/**
+ * Destroy the given set operation.
+ *
+ * @param oh set operation to destroy
+ */
+static void
+set_operation_destroy (struct GNUNET_SETU_OperationHandle *oh)
+{
+  struct GNUNET_SETU_Handle *set = oh->set;
+  struct GNUNET_SETU_OperationHandle *h_assoc;
+
+  if (NULL != oh->conclude_mqm)
+    GNUNET_MQ_discard (oh->conclude_mqm);
+  /* is the operation already commited? */
+  if (NULL != set)
+  {
+    GNUNET_CONTAINER_DLL_remove (set->ops_head,
+                                 set->ops_tail,
+                                 oh);
+    h_assoc = GNUNET_MQ_assoc_remove (set->mq,
+                                      oh->request_id);
+    GNUNET_assert ((NULL == h_assoc) ||
+                   (h_assoc == oh));
+  }
+  GNUNET_free (oh);
+}
+
+
+/**
+ * Cancel the given set operation.  We need to send an explicit cancel
+ * message, as all operations one one set communicate using one
+ * handle.
+ *
+ * @param oh set operation to cancel
+ */
+void
+GNUNET_SETU_operation_cancel (struct GNUNET_SETU_OperationHandle *oh)
+{
+  struct GNUNET_SETU_Handle *set = oh->set;
+  struct GNUNET_SETU_CancelMessage *m;
+  struct GNUNET_MQ_Envelope *mqm;
+
+  LOG (GNUNET_ERROR_TYPE_DEBUG,
+       "Cancelling SET operation\n");
+  if (NULL != set)
+  {
+    mqm = GNUNET_MQ_msg (m, GNUNET_MESSAGE_TYPE_SETU_CANCEL);
+    m->request_id = htonl (oh->request_id);
+    GNUNET_MQ_send (set->mq, mqm);
+  }
+  set_operation_destroy (oh);
+  if ((NULL != set) &&
+      (GNUNET_YES == set->destroy_requested) &&
+      (NULL == set->ops_head))
+  {
+    LOG (GNUNET_ERROR_TYPE_DEBUG,
+         "Destroying set after operation cancel\n");
+    GNUNET_SETU_destroy (set);
+  }
+}
+
+
+/**
+ * We encountered an error communicating with the set service while
+ * performing a set operation. Report to the application.
+ *
+ * @param cls the `struct GNUNET_SETU_Handle`
+ * @param error error code
+ */
+static void
+handle_client_set_error (void *cls,
+                         enum GNUNET_MQ_Error error)
+{
+  struct GNUNET_SETU_Handle *set = cls;
+
+  LOG (GNUNET_ERROR_TYPE_ERROR,
+       "Handling client set error %d\n",
+       error);
+  while (NULL != set->ops_head)
+  {
+    if ((NULL != set->ops_head->result_cb) &&
+        (GNUNET_NO == set->destroy_requested))
+      set->ops_head->result_cb (set->ops_head->result_cls,
+                                NULL,
+                                0,
+                                GNUNET_SETU_STATUS_FAILURE);
+    set_operation_destroy (set->ops_head);
+  }
+  set->invalid = GNUNET_YES;
+}
+
+
+/**
+ * Create an empty set, supporting the specified operation.
+ *
+ * @param cfg configuration to use for connecting to the
+ *        set service
+ * @return a handle to the set
+ */
+struct GNUNET_SETU_Handle *
+GNUNET_SETU_create (const struct GNUNET_CONFIGURATION_Handle *cfg)
+{
+  struct GNUNET_SETU_Handle *set = GNUNET_new (struct GNUNET_SETU_Handle);
+  struct GNUNET_MQ_MessageHandler mq_handlers[] = {
+    GNUNET_MQ_hd_var_size (result,
+                           GNUNET_MESSAGE_TYPE_SETU_RESULT,
+                           struct GNUNET_SETU_ResultMessage,
+                           set),
+    GNUNET_MQ_handler_end ()
+  };
+  struct GNUNET_MQ_Envelope *mqm;
+  struct GNUNET_SETU_CreateMessage *create_msg;
+
+  set->mq = GNUNET_CLIENT_connect (cfg,
+                                   "setu",
+                                   mq_handlers,
+                                   &handle_client_set_error,
+                                   set);
+  if (NULL == set->mq)
+  {
+    GNUNET_free (set);
+    return NULL;
+  }
+  mqm = GNUNET_MQ_msg (create_msg,
+                       GNUNET_MESSAGE_TYPE_SETU_CREATE);
+  GNUNET_MQ_send (set->mq,
+                  mqm);
+  return set;
+}
+
+
+/**
+ * Add an element to the given set.  After the element has been added
+ * (in the sense of being transmitted to the set service), @a cont
+ * will be called.  Multiple calls to GNUNET_SETU_add_element() can be
+ * queued.
+ *
+ * @param set set to add element to
+ * @param element element to add to the set
+ * @param cb continuation called after the element has been added
+ * @param cb_cls closure for @a cb
+ * @return #GNUNET_OK on success, #GNUNET_SYSERR if the
+ *         set is invalid (e.g. the set service crashed)
+ */
+int
+GNUNET_SETU_add_element (struct GNUNET_SETU_Handle *set,
+                         const struct GNUNET_SETU_Element *element,
+                         GNUNET_SCHEDULER_TaskCallback cb,
+                         void *cb_cls)
+{
+  struct GNUNET_MQ_Envelope *mqm;
+  struct GNUNET_SETU_ElementMessage *msg;
+
+  LOG (GNUNET_ERROR_TYPE_DEBUG,
+       "adding element of type %u to set %p\n",
+       (unsigned int) element->element_type,
+       set);
+  GNUNET_assert (NULL != set);
+  if (GNUNET_YES == set->invalid)
+  {
+    if (NULL != cb)
+      cb (cb_cls);
+    return GNUNET_SYSERR;
+  }
+  mqm = GNUNET_MQ_msg_extra (msg,
+                             element->size,
+                             GNUNET_MESSAGE_TYPE_SETU_ADD);
+  msg->element_type = htons (element->element_type);
+  GNUNET_memcpy (&msg[1],
+                 element->data,
+                 element->size);
+  GNUNET_MQ_notify_sent (mqm,
+                         cb,
+                         cb_cls);
+  GNUNET_MQ_send (set->mq,
+                  mqm);
+  return GNUNET_OK;
+}
+
+
+/**
+ * Destroy the set handle if no operations are left, mark the set
+ * for destruction otherwise.
+ *
+ * @param set set handle to destroy
+ */
+void
+GNUNET_SETU_destroy (struct GNUNET_SETU_Handle *set)
+{
+  /* destroying set while iterator is active is currently
+     not supported; we should expand the API to allow
+     clients to explicitly cancel the iteration! */
+  GNUNET_assert (NULL != set);
+  if ((NULL != set->ops_head) ||
+      (GNUNET_SYSERR == set->destroy_requested))
+  {
+    LOG (GNUNET_ERROR_TYPE_DEBUG,
+         "Set operations are pending, delaying set destruction\n");
+    set->destroy_requested = GNUNET_YES;
+    return;
+  }
+  LOG (GNUNET_ERROR_TYPE_DEBUG,
+       "Really destroying set\n");
+  if (NULL != set->mq)
+  {
+    GNUNET_MQ_destroy (set->mq);
+    set->mq = NULL;
+  }
+  GNUNET_free (set);
+}
+
+
+/**
+ * Prepare a set operation to be evaluated with another peer.
+ * The evaluation will not start until the client provides
+ * a local set with #GNUNET_SETU_commit().
+ *
+ * @param other_peer peer with the other set
+ * @param app_id hash for the application using the set
+ * @param context_msg additional information for the request
+ * @param result_cb called on error or success
+ * @param result_cls closure for @e result_cb
+ * @return a handle to cancel the operation
+ */
+struct GNUNET_SETU_OperationHandle *
+GNUNET_SETU_prepare (const struct GNUNET_PeerIdentity *other_peer,
+                     const struct GNUNET_HashCode *app_id,
+                     const struct GNUNET_MessageHeader *context_msg,
+                     const struct GNUNET_SETU_Option options[],
+                     GNUNET_SETU_ResultIterator result_cb,
+                     void *result_cls)
+{
+  struct GNUNET_MQ_Envelope *mqm;
+  struct GNUNET_SETU_OperationHandle *oh;
+  struct GNUNET_SETU_EvaluateMessage *msg;
+
+  LOG (GNUNET_ERROR_TYPE_DEBUG,
+       "Client prepares set union operation\n");
+  oh = GNUNET_new (struct GNUNET_SETU_OperationHandle);
+  oh->result_cb = result_cb;
+  oh->result_cls = result_cls;
+  mqm = GNUNET_MQ_msg_nested_mh (msg,
+                                 GNUNET_MESSAGE_TYPE_SETU_EVALUATE,
+                                 context_msg);
+  msg->app_id = *app_id;
+  msg->target_peer = *other_peer;
+  for (const struct GNUNET_SETU_Option *opt = options; opt->type != 0; opt++)
+  {
+    switch (opt->type)
+    {
+    case GNUNET_SETU_OPTION_BYZANTINE:
+      msg->byzantine = GNUNET_YES;
+      msg->byzantine_lower_bound = htonl (opt->v.num);
+      break;
+    case GNUNET_SETU_OPTION_FORCE_FULL:
+      msg->force_full = GNUNET_YES;
+      break;
+    case GNUNET_SETU_OPTION_FORCE_DELTA:
+      msg->force_delta = GNUNET_YES;
+      break;
+    case GNUNET_SETU_OPTION_SYMMETRIC:
+      msg->symmetric = GNUNET_YES;
+      break;
+    default:
+      LOG (GNUNET_ERROR_TYPE_ERROR,
+           "Option with type %d not recognized\n",
+           (int) opt->type);
+    }
+  }
+  oh->conclude_mqm = mqm;
+  oh->request_id_addr = &msg->request_id;
+  return oh;
+}
+
+
+/**
+ * Connect to the set service in order to listen for requests.
+ *
+ * @param cls the `struct GNUNET_SETU_ListenHandle *` to connect
+ */
+static void
+listen_connect (void *cls);
+
+
+/**
+ * Check validity of request message for a listen operation
+ *
+ * @param cls the listen handle
+ * @param msg the message
+ * @return #GNUNET_OK if the message is well-formed
+ */
+static int
+check_request (void *cls,
+               const struct GNUNET_SETU_RequestMessage *msg)
+{
+  const struct GNUNET_MessageHeader *context_msg;
+
+  if (ntohs (msg->header.size) == sizeof(*msg))
+    return GNUNET_OK; /* no context message is OK */
+  context_msg = GNUNET_MQ_extract_nested_mh (msg);
+  if (NULL == context_msg)
+  {
+    /* malformed context message is NOT ok */
+    GNUNET_break_op (0);
+    return GNUNET_SYSERR;
+  }
+  return GNUNET_OK;
+}
+
+
+/**
+ * Handle request message for a listen operation
+ *
+ * @param cls the listen handle
+ * @param msg the message
+ */
+static void
+handle_request (void *cls,
+                const struct GNUNET_SETU_RequestMessage *msg)
+{
+  struct GNUNET_SETU_ListenHandle *lh = cls;
+  struct GNUNET_SETU_Request req;
+  const struct GNUNET_MessageHeader *context_msg;
+  struct GNUNET_MQ_Envelope *mqm;
+  struct GNUNET_SETU_RejectMessage *rmsg;
+
+  LOG (GNUNET_ERROR_TYPE_DEBUG,
+       "Processing incoming operation request with id %u\n",
+       ntohl (msg->accept_id));
+  /* we got another valid request => reset the backoff */
+  lh->reconnect_backoff = GNUNET_TIME_UNIT_MILLISECONDS;
+  req.accept_id = ntohl (msg->accept_id);
+  req.accepted = GNUNET_NO;
+  context_msg = GNUNET_MQ_extract_nested_mh (msg);
+  /* calling #GNUNET_SETU_accept() in the listen cb will set req->accepted */
+  lh->listen_cb (lh->listen_cls,
+                 &msg->peer_id,
+                 context_msg,
+                 &req);
+  if (GNUNET_YES == req.accepted)
+    return; /* the accept-case is handled in #GNUNET_SETU_accept() */
+  LOG (GNUNET_ERROR_TYPE_DEBUG,
+       "Rejected request %u\n",
+       ntohl (msg->accept_id));
+  mqm = GNUNET_MQ_msg (rmsg,
+                       GNUNET_MESSAGE_TYPE_SETU_REJECT);
+  rmsg->accept_reject_id = msg->accept_id;
+  GNUNET_MQ_send (lh->mq,
+                  mqm);
+}
+
+
+/**
+ * Our connection with the set service encountered an error,
+ * re-initialize with exponential back-off.
+ *
+ * @param cls the `struct GNUNET_SETU_ListenHandle *`
+ * @param error reason for the disconnect
+ */
+static void
+handle_client_listener_error (void *cls,
+                              enum GNUNET_MQ_Error error)
+{
+  struct GNUNET_SETU_ListenHandle *lh = cls;
+
+  LOG (GNUNET_ERROR_TYPE_DEBUG,
+       "Listener broke down (%d), re-connecting\n",
+       (int) error);
+  GNUNET_MQ_destroy (lh->mq);
+  lh->mq = NULL;
+  lh->reconnect_task = GNUNET_SCHEDULER_add_delayed (lh->reconnect_backoff,
+                                                     &listen_connect,
+                                                     lh);
+  lh->reconnect_backoff = GNUNET_TIME_STD_BACKOFF (lh->reconnect_backoff);
+}
+
+
+/**
+ * Connect to the set service in order to listen for requests.
+ *
+ * @param cls the `struct GNUNET_SETU_ListenHandle *` to connect
+ */
+static void
+listen_connect (void *cls)
+{
+  struct GNUNET_SETU_ListenHandle *lh = cls;
+  struct GNUNET_MQ_MessageHandler mq_handlers[] = {
+    GNUNET_MQ_hd_var_size (request,
+                           GNUNET_MESSAGE_TYPE_SETU_REQUEST,
+                           struct GNUNET_SETU_RequestMessage,
+                           lh),
+    GNUNET_MQ_handler_end ()
+  };
+  struct GNUNET_MQ_Envelope *mqm;
+  struct GNUNET_SETU_ListenMessage *msg;
+
+  lh->reconnect_task = NULL;
+  GNUNET_assert (NULL == lh->mq);
+  lh->mq = GNUNET_CLIENT_connect (lh->cfg,
+                                  "setu",
+                                  mq_handlers,
+                                  &handle_client_listener_error,
+                                  lh);
+  if (NULL == lh->mq)
+    return;
+  mqm = GNUNET_MQ_msg (msg,
+                       GNUNET_MESSAGE_TYPE_SETU_LISTEN);
+  msg->app_id = lh->app_id;
+  GNUNET_MQ_send (lh->mq,
+                  mqm);
+}
+
+
+/**
+ * Wait for set operation requests for the given application id
+ *
+ * @param cfg configuration to use for connecting to
+ *            the set service, needs to be valid for the lifetime of the listen handle
+ * @param app_id id of the application that handles set operation requests
+ * @param listen_cb called for each incoming request matching the operation
+ *                  and application id
+ * @param listen_cls handle for @a listen_cb
+ * @return a handle that can be used to cancel the listen operation
+ */
+struct GNUNET_SETU_ListenHandle *
+GNUNET_SETU_listen (const struct GNUNET_CONFIGURATION_Handle *cfg,
+                    const struct GNUNET_HashCode *app_id,
+                    GNUNET_SETU_ListenCallback listen_cb,
+                    void *listen_cls)
+{
+  struct GNUNET_SETU_ListenHandle *lh;
+
+  LOG (GNUNET_ERROR_TYPE_DEBUG,
+       "Starting listener for app %s\n",
+       GNUNET_h2s (app_id));
+  lh = GNUNET_new (struct GNUNET_SETU_ListenHandle);
+  lh->listen_cb = listen_cb;
+  lh->listen_cls = listen_cls;
+  lh->cfg = cfg;
+  lh->app_id = *app_id;
+  lh->reconnect_backoff = GNUNET_TIME_UNIT_MILLISECONDS;
+  listen_connect (lh);
+  if (NULL == lh->mq)
+  {
+    GNUNET_free (lh);
+    return NULL;
+  }
+  return lh;
+}
+
+
+/**
+ * Cancel the given listen operation.
+ *
+ * @param lh handle for the listen operation
+ */
+void
+GNUNET_SETU_listen_cancel (struct GNUNET_SETU_ListenHandle *lh)
+{
+  LOG (GNUNET_ERROR_TYPE_DEBUG,
+       "Canceling listener %s\n",
+       GNUNET_h2s (&lh->app_id));
+  if (NULL != lh->mq)
+  {
+    GNUNET_MQ_destroy (lh->mq);
+    lh->mq = NULL;
+  }
+  if (NULL != lh->reconnect_task)
+  {
+    GNUNET_SCHEDULER_cancel (lh->reconnect_task);
+    lh->reconnect_task = NULL;
+  }
+  GNUNET_free (lh);
+}
+
+
+/**
+ * Accept a request we got via #GNUNET_SETU_listen.  Must be called during
+ * #GNUNET_SETU_listen, as the 'struct GNUNET_SETU_Request' becomes invalid
+ * afterwards.
+ * Call #GNUNET_SETU_commit to provide the local set to use for the operation,
+ * and to begin the exchange with the remote peer.
+ *
+ * @param request request to accept
+ * @param result_mode specified how results will be returned,
+ *        see `enum GNUNET_SETU_ResultMode`.
+ * @param result_cb callback for the results
+ * @param result_cls closure for @a result_cb
+ * @return a handle to cancel the operation
+ */
+struct GNUNET_SETU_OperationHandle *
+GNUNET_SETU_accept (struct GNUNET_SETU_Request *request,
+                    const struct GNUNET_SETU_Option options[],
+                    GNUNET_SETU_ResultIterator result_cb,
+                    void *result_cls)
+{
+  struct GNUNET_MQ_Envelope *mqm;
+  struct GNUNET_SETU_OperationHandle *oh;
+  struct GNUNET_SETU_AcceptMessage *msg;
+
+  GNUNET_assert (GNUNET_NO == request->accepted);
+  LOG (GNUNET_ERROR_TYPE_DEBUG,
+       "Client accepts set union operation with id %u\n",
+       request->accept_id);
+  request->accepted = GNUNET_YES;
+  mqm = GNUNET_MQ_msg (msg,
+                       GNUNET_MESSAGE_TYPE_SETU_ACCEPT);
+  msg->accept_reject_id = htonl (request->accept_id);
+  for (const struct GNUNET_SETU_Option *opt = options; opt->type != 0; opt++)
+  {
+    switch (opt->type)
+    {
+    case GNUNET_SETU_OPTION_BYZANTINE:
+      msg->byzantine = GNUNET_YES;
+      msg->byzantine_lower_bound = htonl (opt->v.num);
+      break;
+    case GNUNET_SETU_OPTION_FORCE_FULL:
+      msg->force_full = GNUNET_YES;
+      break;
+    case GNUNET_SETU_OPTION_FORCE_DELTA:
+      msg->force_delta = GNUNET_YES;
+      break;
+    case GNUNET_SETU_OPTION_SYMMETRIC:
+      msg->symmetric = GNUNET_YES;
+      break;
+    default:
+      LOG (GNUNET_ERROR_TYPE_ERROR,
+           "Option with type %d not recognized\n",
+           (int) opt->type);
+    }
+  }
+  oh = GNUNET_new (struct GNUNET_SETU_OperationHandle);
+  oh->result_cb = result_cb;
+  oh->result_cls = result_cls;
+  oh->conclude_mqm = mqm;
+  oh->request_id_addr = &msg->request_id;
+  return oh;
+}
+
+
+/**
+ * Commit a set to be used with a set operation.
+ * This function is called once we have fully constructed
+ * the set that we want to use for the operation.  At this
+ * time, the P2P protocol can then begin to exchange the
+ * set information and call the result callback with the
+ * result information.
+ *
+ * @param oh handle to the set operation
+ * @param set the set to use for the operation
+ * @return #GNUNET_OK on success, #GNUNET_SYSERR if the
+ *         set is invalid (e.g. the set service crashed)
+ */
+int
+GNUNET_SETU_commit (struct GNUNET_SETU_OperationHandle *oh,
+                    struct GNUNET_SETU_Handle *set)
+{
+  if (NULL != oh->set)
+  {
+    /* Some other set was already committed for this
+     * operation, there is a logic bug in the client of this API */
+    GNUNET_break (0);
+    return GNUNET_OK;
+  }
+  GNUNET_assert (NULL != set);
+  if (GNUNET_YES == set->invalid)
+    return GNUNET_SYSERR;
+  LOG (GNUNET_ERROR_TYPE_DEBUG,
+       "Client commits to SET\n");
+  GNUNET_assert (NULL != oh->conclude_mqm);
+  oh->set = set;
+  GNUNET_CONTAINER_DLL_insert (set->ops_head,
+                               set->ops_tail,
+                               oh);
+  oh->request_id = GNUNET_MQ_assoc_add (set->mq,
+                                        oh);
+  *oh->request_id_addr = htonl (oh->request_id);
+  GNUNET_MQ_send (set->mq,
+                  oh->conclude_mqm);
+  oh->conclude_mqm = NULL;
+  oh->request_id_addr = NULL;
+  return GNUNET_OK;
+}
+
+
+/**
+ * Hash a set element.
+ *
+ * @param element the element that should be hashed
+ * @param[out] ret_hash a pointer to where the hash of @a element
+ *        should be stored
+ */
+void
+GNUNET_SETU_element_hash (const struct GNUNET_SETU_Element *element,
+                          struct GNUNET_HashCode *ret_hash)
+{
+  struct GNUNET_HashContext *ctx = GNUNET_CRYPTO_hash_context_start ();
+
+  /* It's not guaranteed that the element data is always after the element header,
+     so we need to hash the chunks separately. */
+  GNUNET_CRYPTO_hash_context_read (ctx,
+                                   &element->size,
+                                   sizeof(uint16_t));
+  GNUNET_CRYPTO_hash_context_read (ctx,
+                                   &element->element_type,
+                                   sizeof(uint16_t));
+  GNUNET_CRYPTO_hash_context_read (ctx,
+                                   element->data,
+                                   element->size);
+  GNUNET_CRYPTO_hash_context_finish (ctx,
+                                     ret_hash);
+}
+
+
+/* end of setu_api.c */
diff --git a/src/setu/test_setu.conf b/src/setu/test_setu.conf
new file mode 100644
index 0000000000000000000000000000000000000000..4eaf3f0c0a531b583376225e32b0ab13a333e739
--- /dev/null
+++ b/src/setu/test_setu.conf
@@ -0,0 +1,32 @@
+@INLINE@ ../../contrib/conf/gnunet/no_forcestart.conf
+
+[PATHS]
+GNUNET_TEST_HOME = $GNUNET_TMP/test-gnunet-set/
+
+[setu]
+START_ON_DEMAND = YES
+#PREFIX = valgrind --leak-check=full
+#PREFIX = gdbserver :1234
+OPTIONS = -L INFO
+
+[transport]
+PLUGINS = unix
+OPTIONS = -LERROR
+
+[nat]
+RETURN_LOCAL_ADDRESSES = YES
+DISABLEV6 = YES
+USE_LOCALADDR = YES
+
+[peerinfo]
+NO_IO = YES
+
+[nat]
+# Use addresses from the local network interfaces (inluding loopback, but also others)
+USE_LOCALADDR = YES
+
+# Disable IPv6 support
+DISABLEV6 = NO
+
+# Do we use addresses from localhost address ranges? (::1, 127.0.0.0/8)
+RETURN_LOCAL_ADDRESSES = YES
diff --git a/src/setu/test_setu_api.c b/src/setu/test_setu_api.c
new file mode 100644
index 0000000000000000000000000000000000000000..95119873c5920781c4ea7fa4a39d2a268084c738
--- /dev/null
+++ b/src/setu/test_setu_api.c
@@ -0,0 +1,360 @@
+/*
+     This file is part of GNUnet.
+     Copyright (C) 2012 GNUnet e.V.
+
+     GNUnet is free software: you can redistribute it and/or modify it
+     under the terms of the GNU Affero General Public License as published
+     by the Free Software Foundation, either version 3 of the License,
+     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
+     Affero General Public License for more details.
+
+     You should have received a copy of the GNU Affero General Public License
+     along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+     SPDX-License-Identifier: AGPL3.0-or-later
+ */
+
+/**
+ * @file set/test_setu_api.c
+ * @brief testcase for setu_api.c
+ * @author Florian Dold
+ */
+#include "platform.h"
+#include "gnunet_util_lib.h"
+#include "gnunet_testing_lib.h"
+#include "gnunet_setu_service.h"
+
+
+static struct GNUNET_PeerIdentity local_id;
+
+static struct GNUNET_HashCode app_id;
+
+static struct GNUNET_SETU_Handle *set1;
+
+static struct GNUNET_SETU_Handle *set2;
+
+static struct GNUNET_SETU_ListenHandle *listen_handle;
+
+static struct GNUNET_SETU_OperationHandle *oh1;
+
+static struct GNUNET_SETU_OperationHandle *oh2;
+
+static const struct GNUNET_CONFIGURATION_Handle *config;
+
+static int ret;
+
+static struct GNUNET_SCHEDULER_Task *tt;
+
+
+static void
+result_cb_set1 (void *cls,
+                const struct GNUNET_SETU_Element *element,
+                uint64_t size,
+                enum GNUNET_SETU_Status status)
+{
+  switch (status)
+  {
+  case GNUNET_SETU_STATUS_ADD_LOCAL:
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "set 1: got element\n");
+    break;
+
+  case GNUNET_SETU_STATUS_FAILURE:
+    GNUNET_break (0);
+    oh1 = NULL;
+    fprintf (stderr, "set 1: received failure status!\n");
+    ret = 1;
+    if (NULL != tt)
+    {
+      GNUNET_SCHEDULER_cancel (tt);
+      tt = NULL;
+    }
+    GNUNET_SCHEDULER_shutdown ();
+    break;
+
+  case GNUNET_SETU_STATUS_DONE:
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "set 1: done\n");
+    oh1 = NULL;
+    if (NULL != set1)
+    {
+      GNUNET_SETU_destroy (set1);
+      set1 = NULL;
+    }
+    if (NULL == set2)
+    {
+      GNUNET_SCHEDULER_cancel (tt);
+      tt = NULL;
+      GNUNET_SCHEDULER_shutdown ();
+    }
+    break;
+
+  default:
+    GNUNET_assert (0);
+  }
+}
+
+
+static void
+result_cb_set2 (void *cls,
+                const struct GNUNET_SETU_Element *element,
+                uint64_t size,
+                enum GNUNET_SETU_Status status)
+{
+  switch (status)
+  {
+  case GNUNET_SETU_STATUS_ADD_LOCAL:
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "set 2: got element\n");
+    break;
+
+  case GNUNET_SETU_STATUS_FAILURE:
+    GNUNET_break (0);
+    oh2 = NULL;
+    fprintf (stderr, "set 2: received failure status\n");
+    GNUNET_SCHEDULER_shutdown ();
+    ret = 1;
+    break;
+
+  case GNUNET_SETU_STATUS_DONE:
+    oh2 = NULL;
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "set 2: done\n");
+    GNUNET_SETU_destroy (set2);
+    set2 = NULL;
+    if (NULL == set1)
+    {
+      GNUNET_SCHEDULER_cancel (tt);
+      tt = NULL;
+      GNUNET_SCHEDULER_shutdown ();
+    }
+    break;
+
+  default:
+    GNUNET_assert (0);
+  }
+}
+
+
+static void
+listen_cb (void *cls,
+           const struct GNUNET_PeerIdentity *other_peer,
+           const struct GNUNET_MessageHeader *context_msg,
+           struct GNUNET_SETU_Request *request)
+{
+  GNUNET_assert (NULL != context_msg);
+  GNUNET_assert (ntohs (context_msg->type) == GNUNET_MESSAGE_TYPE_DUMMY);
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "listen cb called\n");
+  oh2 = GNUNET_SETU_accept (request,
+                            (struct GNUNET_SETU_Option[]){ 0 },
+                            &result_cb_set2,
+                            NULL);
+  GNUNET_SETU_commit (oh2, set2);
+}
+
+
+/**
+ * Start the set operation.
+ *
+ * @param cls closure, unused
+ */
+static void
+start (void *cls)
+{
+  struct GNUNET_MessageHeader context_msg;
+
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Starting reconciliation\n");
+  context_msg.size = htons (sizeof context_msg);
+  context_msg.type = htons (GNUNET_MESSAGE_TYPE_DUMMY);
+  listen_handle = GNUNET_SETU_listen (config,
+                                      &app_id,
+                                      &listen_cb,
+                                      NULL);
+  oh1 = GNUNET_SETU_prepare (&local_id,
+                             &app_id,
+                             &context_msg,
+                             (struct GNUNET_SETU_Option[]){ 0 },
+                             &result_cb_set1,
+                             NULL);
+  GNUNET_SETU_commit (oh1, set1);
+}
+
+
+/**
+ * Initialize the second set, continue
+ *
+ * @param cls closure, unused
+ */
+static void
+init_set2 (void *cls)
+{
+  struct GNUNET_SETU_Element element;
+
+  GNUNET_log (GNUNET_ERROR_TYPE_INFO, "initializing set 2\n");
+
+  element.element_type = 0;
+  element.data = "hello";
+  element.size = strlen (element.data);
+  GNUNET_SETU_add_element (set2, &element, NULL, NULL);
+  element.data = "quux";
+  element.size = strlen (element.data);
+  GNUNET_SETU_add_element (set2, &element, NULL, NULL);
+  element.data = "baz";
+  element.size = strlen (element.data);
+  GNUNET_SETU_add_element (set2, &element, &start, NULL);
+}
+
+
+/**
+ * Initialize the first set, continue.
+ */
+static void
+init_set1 (void)
+{
+  struct GNUNET_SETU_Element element;
+
+  element.element_type = 0;
+  element.data = "hello";
+  element.size = strlen (element.data);
+  GNUNET_SETU_add_element (set1, &element, NULL, NULL);
+  element.data = "bar";
+  element.size = strlen (element.data);
+  GNUNET_SETU_add_element (set1, &element, &init_set2, NULL);
+  GNUNET_log (GNUNET_ERROR_TYPE_INFO, "initialized set 1\n");
+}
+
+
+/**
+ * Function run on timeout.
+ *
+ * @param cls closure
+ */
+static void
+timeout_fail (void *cls)
+{
+  tt = NULL;
+  GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE, "Testcase failed with timeout\n");
+  GNUNET_SCHEDULER_shutdown ();
+  ret = 1;
+}
+
+
+/**
+ * Function run on shutdown.
+ *
+ * @param cls closure
+ */
+static void
+do_shutdown (void *cls)
+{
+  if (NULL != tt)
+  {
+    GNUNET_SCHEDULER_cancel (tt);
+    tt = NULL;
+  }
+  if (NULL != oh1)
+  {
+    GNUNET_SETU_operation_cancel (oh1);
+    oh1 = NULL;
+  }
+  if (NULL != oh2)
+  {
+    GNUNET_SETU_operation_cancel (oh2);
+    oh2 = NULL;
+  }
+  if (NULL != set1)
+  {
+    GNUNET_SETU_destroy (set1);
+    set1 = NULL;
+  }
+  if (NULL != set2)
+  {
+    GNUNET_SETU_destroy (set2);
+    set2 = NULL;
+  }
+  if (NULL != listen_handle)
+  {
+    GNUNET_SETU_listen_cancel (listen_handle);
+    listen_handle = NULL;
+  }
+}
+
+
+/**
+ * Signature of the 'main' function for a (single-peer) testcase that
+ * is run using 'GNUNET_TESTING_peer_run'.
+ *
+ * @param cls closure
+ * @param cfg configuration of the peer that was started
+ * @param peer identity of the peer that was created
+ */
+static void
+run (void *cls,
+     const struct GNUNET_CONFIGURATION_Handle *cfg,
+     struct GNUNET_TESTING_Peer *peer)
+{
+  struct GNUNET_SETU_OperationHandle *my_oh;
+
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "Running preparatory tests\n");
+  tt = GNUNET_SCHEDULER_add_delayed (
+    GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 5),
+    &timeout_fail,
+    NULL);
+  GNUNET_SCHEDULER_add_shutdown (&do_shutdown, NULL);
+
+  config = cfg;
+  GNUNET_assert (GNUNET_OK == GNUNET_CRYPTO_get_peer_identity (cfg,
+                                                               &local_id));
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "my id (from CRYPTO): %s\n",
+              GNUNET_i2s (&local_id));
+  GNUNET_TESTING_peer_get_identity (peer,
+                                    &local_id);
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "my id (from TESTING): %s\n",
+              GNUNET_i2s (&local_id));
+  set1 = GNUNET_SETU_create (cfg);
+  set2 = GNUNET_SETU_create (cfg);
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "Created sets %p and %p for union operation\n",
+              set1,
+              set2);
+  GNUNET_CRYPTO_hash_create_random (GNUNET_CRYPTO_QUALITY_WEAK, &app_id);
+
+  /* test if canceling an uncommited request works! */
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "Launching and instantly stopping set operation\n");
+  my_oh = GNUNET_SETU_prepare (&local_id,
+                               &app_id,
+                               NULL,
+                               (struct GNUNET_SETU_Option[]){ 0 },
+                               NULL,
+                               NULL);
+  GNUNET_SETU_operation_cancel (my_oh);
+
+  /* test the real set reconciliation */
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "Running real set-reconciliation\n");
+  init_set1 ();
+}
+
+
+int
+main (int argc, char **argv)
+{
+  GNUNET_log_setup ("test_setu_api",
+                    "WARNING",
+                    NULL);
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "Launching peer\n");
+  if (0 !=
+      GNUNET_TESTING_peer_run ("test_setu_api",
+                               "test_setu.conf",
+                               &run,
+                               NULL))
+  {
+    return 1;
+  }
+  return ret;
+}
diff --git a/src/sq/.gitignore b/src/sq/.gitignore
new file mode 100644
index 0000000000000000000000000000000000000000..951587047616c090fdc63b4153d3136c073fd43e
--- /dev/null
+++ b/src/sq/.gitignore
@@ -0,0 +1 @@
+test_sq
diff --git a/src/statistics/.gitignore b/src/statistics/.gitignore
new file mode 100644
index 0000000000000000000000000000000000000000..f1f567149395d80b228337b2e25040e260ae39e6
--- /dev/null
+++ b/src/statistics/.gitignore
@@ -0,0 +1,7 @@
+gnunet-statistics
+gnunet-service-statistics
+test_gnunet_statistics.py
+test_statistics_api
+test_statistics_api_loop
+test_statistics_api_watch
+test_statistics_api_watch_zero_value
diff --git a/src/statistics/gnunet-service-statistics.c b/src/statistics/gnunet-service-statistics.c
index be2a49201e6c1ab7529c4bb9bc4aa22df01fc680..31c367e9180b636fa1a3b4dcda56813edf9442b9 100644
--- a/src/statistics/gnunet-service-statistics.c
+++ b/src/statistics/gnunet-service-statistics.c
@@ -290,7 +290,8 @@ save ()
         msg->flags =
           htonl (pos->persistent ? GNUNET_STATISTICS_SETFLAG_PERSISTENT : 0);
         msg->value = GNUNET_htonll (pos->value);
-        if (GNUNET_OK != GNUNET_BIO_write (wh, "statistics-save-msg", msg, size))
+        if (GNUNET_OK != GNUNET_BIO_write (wh, "statistics-save-msg", msg,
+                                           size))
         {
           GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_WARNING, "write", fn);
           if (GNUNET_OK != GNUNET_BIO_write_close (wh, NULL))
diff --git a/src/statistics/test_statistics_api.c b/src/statistics/test_statistics_api.c
index fcdeccad6b7d15b7c5d4830e6e2b3e6b9609df6c..c9e568870965e0768ccd99aad7e89421f4768487 100644
--- a/src/statistics/test_statistics_api.c
+++ b/src/statistics/test_statistics_api.c
@@ -197,8 +197,8 @@ main (int argc, char *argv_ign[])
                     NULL);
   binary = GNUNET_OS_get_libexec_binary_path ("gnunet-service-statistics");
   proc =
-    GNUNET_OS_start_process (GNUNET_YES,
-                             GNUNET_OS_INHERIT_STD_OUT_AND_ERR,
+    GNUNET_OS_start_process (GNUNET_OS_INHERIT_STD_OUT_AND_ERR
+                             | GNUNET_OS_USE_PIPE_CONTROL,
                              NULL, NULL, NULL,
                              binary,
                              "gnunet-service-statistics",
@@ -225,8 +225,8 @@ main (int argc, char *argv_ign[])
   ok = 1;
   /* restart to check persistence! */
   proc =
-    GNUNET_OS_start_process (GNUNET_YES,
-                             GNUNET_OS_INHERIT_STD_OUT_AND_ERR,
+    GNUNET_OS_start_process (GNUNET_OS_INHERIT_STD_OUT_AND_ERR
+                             | GNUNET_OS_USE_PIPE_CONTROL,
                              NULL, NULL, NULL,
                              binary,
                              "gnunet-service-statistics",
diff --git a/src/statistics/test_statistics_api_loop.c b/src/statistics/test_statistics_api_loop.c
index 50507bdc4935cc7a78955c668cdce8e0d4a54d3d..ad273287db1b989697e900c008cf919755f915a5 100644
--- a/src/statistics/test_statistics_api_loop.c
+++ b/src/statistics/test_statistics_api_loop.c
@@ -98,7 +98,8 @@ main (int argc, char *argv_ign[])
 
   binary = GNUNET_OS_get_libexec_binary_path ("gnunet-service-statistics");
   proc =
-    GNUNET_OS_start_process (GNUNET_YES, GNUNET_OS_INHERIT_STD_OUT_AND_ERR,
+    GNUNET_OS_start_process (GNUNET_OS_INHERIT_STD_OUT_AND_ERR
+                             | GNUNET_OS_USE_PIPE_CONTROL,
                              NULL, NULL, NULL,
                              binary,
                              "gnunet-service-statistics",
diff --git a/src/statistics/test_statistics_api_watch.c b/src/statistics/test_statistics_api_watch.c
index 06e639599c39df79e3d504b4af75fba0b164f52c..2d9d0830570b0e5062080493c6f3bc0f1cc4d2db 100644
--- a/src/statistics/test_statistics_api_watch.c
+++ b/src/statistics/test_statistics_api_watch.c
@@ -130,7 +130,8 @@ main (int argc, char *argv_ign[])
 
   binary = GNUNET_OS_get_libexec_binary_path ("gnunet-service-statistics");
   proc =
-    GNUNET_OS_start_process (GNUNET_YES, GNUNET_OS_INHERIT_STD_OUT_AND_ERR,
+    GNUNET_OS_start_process (GNUNET_OS_INHERIT_STD_OUT_AND_ERR
+                             | GNUNET_OS_USE_PIPE_CONTROL,
                              NULL, NULL, NULL,
                              binary,
                              "gnunet-service-statistics",
diff --git a/src/statistics/test_statistics_api_watch_zero_value.c b/src/statistics/test_statistics_api_watch_zero_value.c
index 80ca57c186838ff6d9c3364833708e8d9f0ccdc4..cb2694f8fcde64abb2b43f16e6474c307b468f8d 100644
--- a/src/statistics/test_statistics_api_watch_zero_value.c
+++ b/src/statistics/test_statistics_api_watch_zero_value.c
@@ -168,7 +168,8 @@ main (int argc, char *argv_ign[])
 
   binary = GNUNET_OS_get_libexec_binary_path ("gnunet-service-statistics");
   proc =
-    GNUNET_OS_start_process (GNUNET_YES, GNUNET_OS_INHERIT_STD_OUT_AND_ERR,
+    GNUNET_OS_start_process (GNUNET_OS_INHERIT_STD_OUT_AND_ERR
+                             | GNUNET_OS_USE_PIPE_CONTROL,
                              NULL, NULL, NULL,
                              binary,
                              "gnunet-service-statistics",
diff --git a/src/template/.gitignore b/src/template/.gitignore
new file mode 100644
index 0000000000000000000000000000000000000000..8ac4bacb5b639a3c467e5deaaf91b678ef0f269b
--- /dev/null
+++ b/src/template/.gitignore
@@ -0,0 +1,3 @@
+gnunet-template
+gnunet-service-template
+test_template_api
diff --git a/src/testbed-logger/.gitignore b/src/testbed-logger/.gitignore
new file mode 100644
index 0000000000000000000000000000000000000000..de0c2dcfe78d601bb5dd2cf3d20b2cc6176e72a9
--- /dev/null
+++ b/src/testbed-logger/.gitignore
@@ -0,0 +1,2 @@
+gnunet-service-testbed-logger
+test_testbed_logger_api
diff --git a/src/testbed/.gitignore b/src/testbed/.gitignore
new file mode 100644
index 0000000000000000000000000000000000000000..f7cfb1e2355096bcc12d7aaf78b0c4a1d0ed5bc8
--- /dev/null
+++ b/src/testbed/.gitignore
@@ -0,0 +1,37 @@
+gnunet-testbed-profiler
+generate-underlay-topology
+gnunet-daemon-latency-logger
+gnunet-daemon-testbed-blacklist
+gnunet-daemon-testbed-underlay
+gnunet-helper-testbed
+gnunet-service-testbed
+gnunet-service-test-barriers
+test_gnunet_helper_testbed
+test_testbed_api
+test_testbed_api_2peers_1controller
+test_testbed_api_3peers_3controllers
+test_testbed_api_barriers
+test_testbed_api_controllerlink
+test_testbed_api_hosts
+test_testbed_api_operations
+test_testbed_api_peer_reconfiguration
+test_testbed_api_peers_manage_services
+test_testbed_api_sd
+test_testbed_api_statistics
+test_testbed_api_test
+test_testbed_api_test_timeout
+test_testbed_api_testbed_run
+test_testbed_api_testbed_run_topology2dtorus
+test_testbed_api_testbed_run_topologyclique
+test_testbed_api_testbed_run_topologyfromfile
+test_testbed_api_testbed_run_topologyline
+test_testbed_api_testbed_run_topologyrandom
+test_testbed_api_testbed_run_topologyring
+test_testbed_api_testbed_run_topologyscalefree
+test_testbed_api_testbed_run_topologysmallworld
+test_testbed_api_testbed_run_topologysmallworldring
+test_testbed_api_testbed_run_topologystar
+test_testbed_api_testbed_run_waitforever
+test_testbed_api_topology
+test_testbed_api_topology_clique
+test_testbed_underlay
diff --git a/src/testbed/barriers.README.org b/src/testbed/barriers.README.org
new file mode 100644
index 0000000000000000000000000000000000000000..40488a0cc9fdf42f7af30e9008458baf472c2961
--- /dev/null
+++ b/src/testbed/barriers.README.org
@@ -0,0 +1,95 @@
+* Description
+The testbed subsystem's barriers API facilitates coordination among the peers
+run by the testbed and the experiment driver.  The concept is similar to the
+barrier synchronisation mechanism found in parallel programming or
+multi-threading paradigms - a peer waits at a barrier upon reaching it until the
+barrier is reached by a predefined number of peers.  This predefined number of
+peers required to cross a barrier is also called quorum.  We say a peer has
+reached a barrier if the peer is waiting for the barrier to be crossed.
+Similarly a barrier is said to be reached if the required quorum of peers reach
+the barrier.  A barrier which is reached is deemed as crossed after all the
+peers waiting on it are notified.
+
+The barriers API provides the following functions:
+1) GNUNET_TESTBED_barrier_init(): function to initialse a barrier in the
+   experiment
+2) GNUNET_TESTBED_barrier_cancel(): function to cancel a barrier which has been
+   initialised before
+3) GNUNET_TESTBED_barrier_wait(): function to signal barrier service that the
+    caller has reached a barrier and is waiting for it to be crossed
+4) GNUNET_TESTBED_barrier_wait_cancel(): function to stop waiting for a barrier
+   to be crossed
+
+Among the above functions, the first two, namely GNUNET_TESTBED_barrier_init()
+and GNUNET_TESTBED_barrier_cacel() are used by experiment drivers.  All barriers
+should be initialised by the experiment driver by calling
+GNUNET_TESTBED_barrier_init().  This function takes a name to identify the
+barrier, the quorum required for the barrier to be crossed and a notification
+callback for notifying the experiment driver when the barrier is crossed.  The
+GNUNET_TESTBED_function barrier_cancel() cancels an initialised barrier and
+frees the resources allocated for it.  This function can be called upon a
+initialised barrier before it is crossed.
+
+The remaining two functions GNUNET_TESTBED_barrier_wait() and
+GNUNET_TESTBED_barrier_wait_cancel() are used in the peer's processes.
+GNUNET_TESTBED_barrier_wait() connects to the local barrier service running on
+the same host the peer is running on and registers that the caller has reached
+the barrier and is waiting for the barrier to be crossed.  Note that this
+function can only be used by peers which are started by testbed as this function
+tries to access the local barrier service which is part of the testbed
+controller service.  Calling GNUNET_TESTBED_barrier_wait() on an uninitialised
+barrier results in failure.  GNUNET_TESTBED_barrier_wait_cancel() cancels the
+notification registered by GNUNET_TESTBED_barrier_wait().
+
+
+* Implementation
+Since barriers involve coordination between experiment driver and peers, the
+barrier service in the testbed controller is split into two components.  The
+first component responds to the message generated by the barrier API used by the
+experiment driver (functions GNUNET_TESTBED_barrier_init() and
+GNUNET_TESTBED_barrier_cancel()) and the second component to the messages
+generated by barrier API used by peers (functions GNUNET_TESTBED_barrier_wait()
+and GNUNET_TESTBED_barrier_wait_cancel()).
+
+Calling GNUNET_TESTBED_barrier_init() sends a BARRIER_INIT message to the master
+controller.  The master controller then registers a barrier and calls
+GNUNET_TESTBED_barrier_init() for each its subcontrollers.  In this way barrier
+initialisation is propagated to the controller hierarchy.  While propagating
+initialisation, any errors at a subcontroller such as timeout during further
+propagation are reported up the hierarchy back to the experiment driver.
+
+Similar to GNUNET_TESTBED_barrier_init(), GNUNET_TESTBED_barrier_cancel()
+propagates BARRIER_CANCEL message which causes controllers to remove an
+initialised barrier.
+
+The second component is implemented as a separate service in the binary
+`gnunet-service-testbed' which already has the testbed controller service.
+Although this deviates from the gnunet process architecture of having one
+service per binary, it is needed in this case as this component needs access to
+barrier data created by the first component.  This component responds to
+BARRIER_WAIT messages from local peers when they call
+GNUNET_TESTBED_barrier_wait().  Upon receiving BARRIER_WAIT message, the service
+checks if the requested barrier has been initialised before and if it was not
+initialised, an error status is sent through BARRIER_STATUS message to the local
+peer and the connection from the peer is terminated.  If the barrier is
+initialised before, the barrier's counter for reached peers is incremented and a
+notification is registered to notify the peer when the barrier is reached.  The
+connection from the peer is left open.
+
+When enough peers required to attain the quorum send BARRIER_WAIT messages, the
+controller sends a BARRIER_STATUS message to its parent informing that the
+barrier is crossed.  If the controller has started further subcontrollers, it
+delays this message until it receives a similar notification from each of those
+subcontrollers.  Finally, the barriers API at the experiment driver receives the
+BARRIER_STATUS when the barrier is reached at all the controllers.
+
+The barriers API at the experiment driver responds to the BARRIER_STATUS message
+by echoing it back to the master controller and notifying the experiment
+controller through the notification callback that a barrier has been crossed.
+The echoed BARRIER_STATUS message is propagated by the master controller to the
+controller hierarchy.  This propagation triggers the notifications registered by
+peers at each of the controllers in the hierarchy.  Note the difference between
+this downward propagation of the BARRIER_STATUS message from its upward
+propagation -- the upward propagation is needed for ensuring that the barrier is
+reached by all the controllers and the downward propagation is for triggering
+that the barrier is crossed.
diff --git a/src/testbed/buildvars.py.in b/src/testbed/buildvars.py.in
new file mode 100644
index 0000000000000000000000000000000000000000..3b2f561183cbf2b8787cb81e5fe7d3a8e9a266b7
--- /dev/null
+++ b/src/testbed/buildvars.py.in
@@ -0,0 +1,34 @@
+# This file is part of GNUnet.
+# (C) 2008--2013, 2018 Christian Grothoff (and other contributing authors)
+#
+# GNUnet is free software: you can redistribute it and/or modify it
+# under the terms of the GNU Affero General Public License as published
+# by the Free Software Foundation, either version 3 of the License,
+# 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
+# Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+#
+# SPDX-License-Identifier: AGPL3.0-or-later
+
+# file:     testbed/buildvars.py
+# brief:    file for importing variables from build system into python
+# author:   Sree Harsha Totakura
+
+import os
+
+exec_prefix = '@exec_prefix@'
+libexecdir = '@libexecdir@'
+
+if libexecdir.startswith(exec_prefix):
+    libexecdir = libexecdir[len(exec_prefix):]
+
+gnunet_prefix = os.environ.get('GNUNET_PREFIX', None)
+
+if gnunet_prefix and libexecdir.startswith('/'):
+    libexecdir = os.path.join(gnunet_prefix, libexecdir[1:])
diff --git a/src/testbed/generate-underlay-topology.c b/src/testbed/generate-underlay-topology.c
index 726bed1798e492272638516cdbcfb84b7f295a4e..97c3c1e6767a3e0f70bdf72c9e9be44eac246a9d 100644
--- a/src/testbed/generate-underlay-topology.c
+++ b/src/testbed/generate-underlay-topology.c
@@ -51,12 +51,12 @@
                      __LINE__,                                    \
                      sqlite3_errmsg (db));                        \
     if (msg != NULL)                                              \
-      GNUNET_asprintf (msg,                                       \
-                       _ ("`%s' failed at %s:%u with error: %s"), \
-                       cmd,                                       \
-                       __FILE__,                                  \
-                       __LINE__,                                  \
-                       sqlite3_errmsg (db));                      \
+    GNUNET_asprintf (msg,                                       \
+                     _ ("`%s' failed at %s:%u with error: %s"), \
+                     cmd,                                       \
+                     __FILE__,                                  \
+                     __LINE__,                                  \
+                     sqlite3_errmsg (db));                      \
   } while (0)
 
 
diff --git a/src/testbed/gnunet-daemon-latency-logger.c b/src/testbed/gnunet-daemon-latency-logger.c
index c13750db7128101db42db73424018c04a516daf7..cbc9cfdbf36253c45213228c17e05786c0b2f3e6 100644
--- a/src/testbed/gnunet-daemon-latency-logger.c
+++ b/src/testbed/gnunet-daemon-latency-logger.c
@@ -53,8 +53,8 @@
                        "`%s' failed at %s:%d with error: %s\n"), \
                      cmd, __FILE__, __LINE__, sqlite3_errmsg (db));  \
     if (msg != NULL)                                                    \
-      GNUNET_asprintf (msg, _ ("`%s' failed at %s:%u with error: %s"), cmd, \
-                       __FILE__, __LINE__, sqlite3_errmsg (db));     \
+    GNUNET_asprintf (msg, _ ("`%s' failed at %s:%u with error: %s"), cmd, \
+                     __FILE__, __LINE__, sqlite3_errmsg (db));     \
   } while (0)
 
 
diff --git a/src/testbed/gnunet-daemon-testbed-underlay.c b/src/testbed/gnunet-daemon-testbed-underlay.c
index 2bff7cdd49b1be50a8862fc72e47ba5f1a0eaf6b..c3b424c9b3c6304a7a79b9974c9f599caccd73c4 100644
--- a/src/testbed/gnunet-daemon-testbed-underlay.c
+++ b/src/testbed/gnunet-daemon-testbed-underlay.c
@@ -57,8 +57,8 @@
                        "`%s' failed at %s:%d with error: %s\n"), \
                      cmd, __FILE__, __LINE__, sqlite3_errmsg (db));  \
     if (msg != NULL)                                                    \
-      GNUNET_asprintf (msg, _ ("`%s' failed at %s:%u with error: %s"), cmd, \
-                       __FILE__, __LINE__, sqlite3_errmsg (db));     \
+    GNUNET_asprintf (msg, _ ("`%s' failed at %s:%u with error: %s"), cmd, \
+                     __FILE__, __LINE__, sqlite3_errmsg (db));     \
   } while (0)
 
 
diff --git a/src/testbed/gnunet-helper-testbed-valgrind.patch b/src/testbed/gnunet-helper-testbed-valgrind.patch
new file mode 100644
index 0000000000000000000000000000000000000000..1777c30d0c435efc0f19c7d4995b6dbb966d890f
--- /dev/null
+++ b/src/testbed/gnunet-helper-testbed-valgrind.patch
@@ -0,0 +1,21 @@
+Index: gnunet-helper-testbed.c
+===================================================================
+--- gnunet-helper-testbed.c	(revision 32320)
++++ gnunet-helper-testbed.c	(working copy)
+@@ -462,7 +462,15 @@
+   testbed =
+       GNUNET_OS_start_process (PIPE_CONTROL,
+                                GNUNET_OS_INHERIT_STD_ERR /*verbose? */ , NULL,
+-                               NULL, binary, "gnunet-service-testbed", "-c",
++                               NULL, "valgrind",
++                               "valgrind",
++                               "--leak-check=full",
++                               "--show-reachable=yes",
++                               "--suppressions=$HOME/gnunet/src/util/util.supp",
++                               "--suppressions=$HOME/gnunet/src/testbed/misc.supp",
++                               "--suppressions=$HOME/gnunet/src/testbed/valgrind-zlib.supp",
++                               "--suppressions=$HOME/gnunet/src/testbed/x64_misc.supp",
++                               binary, "-c",
+                                config, NULL);
+   GNUNET_free (binary);
+   GNUNET_free (config);
diff --git a/src/testbed/gnunet-helper-testbed.c b/src/testbed/gnunet-helper-testbed.c
index 24c212d6b4c31778d6aafb551e607254cb5fef73..5d0c3b048c1aed87b058217c78e3e2f70a493028 100644
--- a/src/testbed/gnunet-helper-testbed.c
+++ b/src/testbed/gnunet-helper-testbed.c
@@ -57,12 +57,6 @@
 #define LOG_DEBUG(...) LOG (GNUNET_ERROR_TYPE_DEBUG, __VA_ARGS__)
 
 
-/**
- * We need pipe control only on WINDOWS
- */
-#define PIPE_CONTROL GNUNET_NO
-
-
 /**
  * Context for a single write on a chunk of memory
  */
@@ -435,8 +429,7 @@ tokenizer_cb (void *cls, const struct GNUNET_MessageHeader *message)
                                             see putenv(): becomes part of envrionment! */
     evstr = NULL;
   }
-  testbed = GNUNET_OS_start_process (PIPE_CONTROL,
-                                     GNUNET_OS_INHERIT_STD_ERR /*verbose? */,
+  testbed = GNUNET_OS_start_process (GNUNET_OS_INHERIT_STD_ERR /*verbose? */,
                                      NULL,
                                      NULL,
                                      NULL,
@@ -594,7 +587,7 @@ main (int argc, char **argv)
 
   status = GNUNET_OK;
   if (NULL ==
-      (sigpipe = GNUNET_DISK_pipe (GNUNET_NO, GNUNET_NO, GNUNET_NO, GNUNET_NO)))
+      (sigpipe = GNUNET_DISK_pipe (GNUNET_DISK_PF_NONE)))
   {
     GNUNET_break (0);
     return 1;
diff --git a/src/testbed/gnunet-service-testbed.h b/src/testbed/gnunet-service-testbed.h
index 03955327cb2e2680bb43d71d65e57ebaabbab506..ae477ccb48603e15268af9643caf83eeff60b323 100644
--- a/src/testbed/gnunet-service-testbed.h
+++ b/src/testbed/gnunet-service-testbed.h
@@ -498,7 +498,7 @@ extern char *GST_stats_dir;
     GNUNET_assert (size <= accommodate_size);                            \
     growth_size = size;                                                 \
     while (growth_size <= accommodate_size)                             \
-      growth_size += LIST_GROW_STEP;                                    \
+    growth_size += LIST_GROW_STEP;                                    \
     GNUNET_array_grow (ptr, size, growth_size);                         \
     GNUNET_assert (size > accommodate_size);                            \
   } while (0)
diff --git a/src/testbed/gnunet_mpi_test.c b/src/testbed/gnunet_mpi_test.c
new file mode 100644
index 0000000000000000000000000000000000000000..e0caf9676960ac3b63e9113043eeb0e3fc16dcef
--- /dev/null
+++ b/src/testbed/gnunet_mpi_test.c
@@ -0,0 +1,107 @@
+#include "platform.h"
+#include "gnunet_util_lib.h"
+#include <mpi.h>
+
+/**
+ * Generic logging shorthand
+ */
+#define LOG(kind, ...)                                           \
+  GNUNET_log_from (kind, "gnunet-mpi-test", __VA_ARGS__)
+
+int
+main (int argc, char *argv[])
+{
+  char *msg;
+  char *filename;
+  char **argv2;
+  struct GNUNET_OS_Process *proc;
+  unsigned long code;
+  pid_t pid;
+  enum GNUNET_OS_ProcessStatusType proc_status;
+  int ntasks;
+  int rank;
+  int msg_size;
+  int ret;
+  unsigned int cnt;
+
+  ret = GNUNET_SYSERR;
+  if (argc < 2)
+  {
+    printf ("Need arguments: gnunet-mpi-test <cmd> <cmd_args>");
+    return 1;
+  }
+  if (MPI_SUCCESS != MPI_Init (&argc, &argv))
+  {
+    GNUNET_break (0);
+    return 1;
+  }
+  if (MPI_SUCCESS != MPI_Comm_size (MPI_COMM_WORLD, &ntasks))
+  {
+    GNUNET_break (0);
+    goto finalize;
+  }
+  if (MPI_SUCCESS != MPI_Comm_rank (MPI_COMM_WORLD, &rank))
+  {
+    GNUNET_break (0);
+    goto finalize;
+  }
+  pid = getpid ();
+  (void) GNUNET_asprintf (&filename, "%d-%d.mpiout", (int) pid, rank);
+  msg_size = GNUNET_asprintf (&msg, "My rank is: %d\n", rank);
+  printf ("%s", msg);
+  if (msg_size ==
+      GNUNET_DISK_fn_write (filename, msg, msg_size,
+                            GNUNET_DISK_PERM_USER_READ
+                            | GNUNET_DISK_PERM_GROUP_READ
+                            | GNUNET_DISK_PERM_USER_WRITE
+                            | GNUNET_DISK_PERM_GROUP_WRITE))
+    ret = GNUNET_OK;
+  GNUNET_free (filename);
+  GNUNET_free (msg);
+  if (GNUNET_OK != ret)
+  {
+    GNUNET_break (0);
+    goto finalize;
+  }
+
+  ret = GNUNET_SYSERR;
+  argv2 = GNUNET_malloc (sizeof(char *) * (argc));
+  for (cnt = 1; cnt < argc; cnt++)
+    argv2[cnt - 1] = argv[cnt];
+  proc =
+    GNUNET_OS_start_process_vap (GNUNET_NO, GNUNET_OS_INHERIT_STD_ALL, NULL,
+                                 NULL, NULL, argv2[0], argv2);
+  if (NULL == proc)
+  {
+    printf ("Cannot exec\n");
+    GNUNET_free (argv2);
+    goto finalize;
+  }
+  do
+  {
+    (void) sleep (1);
+    ret = GNUNET_OS_process_status (proc, &proc_status, &code);
+  }
+  while (GNUNET_NO == ret);
+  GNUNET_free (argv2);
+  GNUNET_assert (GNUNET_NO != ret);
+  if (GNUNET_OK == ret)
+  {
+    if (0 != code)
+    {
+      LOG (GNUNET_ERROR_TYPE_WARNING, "Child terminated abnormally\n");
+      ret = GNUNET_SYSERR;
+      GNUNET_break (0);
+      goto finalize;
+    }
+  }
+  else
+    GNUNET_break (0);
+
+finalize:
+  (void) MPI_Finalize ();
+  if (GNUNET_OK == ret)
+    return 0;
+  printf ("Something went wrong\n");
+  return 1;
+}
diff --git a/src/testbed/gnunet_testbed_mpi_spawn.c b/src/testbed/gnunet_testbed_mpi_spawn.c
new file mode 100644
index 0000000000000000000000000000000000000000..577ffbebab3fd78e2c1914143a1db00a24519625
--- /dev/null
+++ b/src/testbed/gnunet_testbed_mpi_spawn.c
@@ -0,0 +1,327 @@
+#include "platform.h"
+#include "gnunet_util_lib.h"
+#include "gnunet_testbed_service.h"
+
+
+/**
+ * Generic logging shorthand
+ */
+#define LOG(kind, ...)                           \
+  GNUNET_log (kind, __VA_ARGS__)
+
+/**
+ * Debug logging shorthand
+ */
+#define LOG_DEBUG(...)                          \
+  LOG (GNUNET_ERROR_TYPE_DEBUG, __VA_ARGS__)
+
+/**
+ * Global result
+ */
+static int ret;
+
+/**
+ * The child process we spawn
+ */
+static struct GNUNET_OS_Process *child;
+
+/**
+ * The arguments including the binary to spawn
+ */
+static char **argv2;
+
+/**
+ * Pipe used to communicate shutdown via signal.
+ */
+static struct GNUNET_DISK_PipeHandle *sigpipe;
+
+/**
+ * Filename of the unique file
+ */
+static char *fn;
+
+/**
+ * Handle to the unique file
+ */
+static int fh;
+
+/**
+ * The return code of the binary
+ */
+static unsigned long child_exit_code;
+
+/**
+ * The process status of the child
+ */
+static enum GNUNET_OS_ProcessStatusType child_status;
+
+/**
+ * Task to kill the child
+ */
+static struct GNUNET_SCHEDULER_Task *terminate_task_id;
+
+/**
+ * Task to kill the child
+ */
+static struct GNUNET_SCHEDULER_Task *child_death_task_id;
+
+/**
+ * The shutdown task
+ */
+static void
+shutdown_task (void *cls)
+{
+  if (0 != child_exit_code)
+  {
+    LOG (GNUNET_ERROR_TYPE_WARNING, "Child exited with error code: %lu\n",
+         child_exit_code);
+    ret = 128 + (int) child_exit_code;
+  }
+  if (0 != fh)
+  {
+    close (fh);
+  }
+  if ((NULL != fn) && (0 != unlink (fn)))
+  {
+    GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "open");
+    ret = GNUNET_SYSERR;
+  }
+}
+
+
+static void
+terminate_task (void *cls)
+{
+  static int hard_kill;
+
+  GNUNET_assert (NULL != child);
+  terminate_task_id =
+    GNUNET_SCHEDULER_add_shutdown (&terminate_task, NULL);
+  if (0 != hard_kill)
+  {
+    switch (hard_kill)
+    {
+    case 1:
+    case 2:
+      LOG (GNUNET_ERROR_TYPE_WARNING,
+           "%d more interrupts needed to send SIGKILL to the child\n",
+           3 - hard_kill);
+      hard_kill++;
+      return;
+
+    case 3:
+      GNUNET_break (0 == GNUNET_OS_process_kill (child, SIGKILL));
+      return;
+    }
+  }
+  hard_kill++;
+  GNUNET_break (0 == GNUNET_OS_process_kill (child, GNUNET_TERM_SIG));
+  LOG (GNUNET_ERROR_TYPE_INFO, _ ("Waiting for child to exit.\n"));
+}
+
+
+/**
+ * Task triggered whenever we receive a SIGCHLD (child
+ * process died).
+ *
+ * @param cls closure, NULL if we need to self-restart
+ */
+static void
+child_death_task (void *cls)
+{
+  const struct GNUNET_DISK_FileHandle *pr;
+  char c[16];
+  const struct GNUNET_SCHEDULER_TaskContext *tc;
+
+
+  pr = GNUNET_DISK_pipe_handle (sigpipe, GNUNET_DISK_PIPE_END_READ);
+  child_death_task_id = NULL;
+  tc = GNUNET_SCHEDULER_get_task_context ();
+  if (0 == (tc->reason & GNUNET_SCHEDULER_REASON_READ_READY))
+  {
+    child_death_task_id =
+      GNUNET_SCHEDULER_add_read_file (GNUNET_TIME_UNIT_FOREVER_REL,
+                                      pr, &child_death_task, NULL);
+    return;
+  }
+  /* consume the signal */
+  GNUNET_break (0 < GNUNET_DISK_file_read (pr, &c, sizeof(c)));
+  LOG_DEBUG ("Child died\n");
+  GNUNET_SCHEDULER_cancel (terminate_task_id);
+  terminate_task_id = NULL;
+  GNUNET_assert (GNUNET_OK == GNUNET_OS_process_status (child, &child_status,
+                                                        &child_exit_code));
+  GNUNET_OS_process_destroy (child);
+  child = NULL;
+  GNUNET_SCHEDULER_add_now (&shutdown_task, NULL);
+}
+
+
+static void
+destroy_hosts (struct GNUNET_TESTBED_Host **hosts, unsigned int nhosts)
+{
+  unsigned int host;
+
+  GNUNET_assert (NULL != hosts);
+  for (host = 0; host < nhosts; host++)
+    if (NULL != hosts[host])
+      GNUNET_TESTBED_host_destroy (hosts[host]);
+  GNUNET_free (hosts);
+  hosts = NULL;
+}
+
+
+/**
+ * The main scheduler run task
+ *
+ * @param cls NULL
+ */
+static void
+run (void *cls)
+{
+  struct GNUNET_TESTBED_Host **hosts;
+  const struct GNUNET_CONFIGURATION_Handle *null_cfg;
+  char *tmpdir;
+  char *hostname;
+  size_t hostname_len;
+  unsigned int nhosts;
+
+  null_cfg = GNUNET_CONFIGURATION_create ();
+  nhosts = GNUNET_TESTBED_hosts_load_from_loadleveler (null_cfg, &hosts);
+  if (0 == nhosts)
+  {
+    GNUNET_break (0);
+    ret = GNUNET_SYSERR;
+    return;
+  }
+  hostname_len = GNUNET_OS_get_hostname_max_length ();
+  hostname = GNUNET_malloc (hostname_len);
+  if (0 != gethostname (hostname, hostname_len))
+  {
+    LOG (GNUNET_ERROR_TYPE_ERROR, "Cannot get hostname.  Exiting\n");
+    GNUNET_free (hostname);
+    destroy_hosts (hosts, nhosts);
+    ret = GNUNET_SYSERR;
+    return;
+  }
+  if (NULL == strstr (GNUNET_TESTBED_host_get_hostname (hosts[0]), hostname))
+  {
+    LOG_DEBUG ("Exiting as `%s' is not the lowest host\n", hostname);
+    GNUNET_free (hostname);
+    ret = GNUNET_OK;
+    return;
+  }
+  LOG_DEBUG ("Will be executing `%s' on host `%s'\n", argv2[0], hostname);
+  GNUNET_free (hostname);
+  destroy_hosts (hosts, nhosts);
+  tmpdir = getenv ("TMPDIR");
+  if (NULL == tmpdir)
+    tmpdir = getenv ("TMP");
+  if (NULL == tmpdir)
+    tmpdir = getenv ("TEMP");
+  if (NULL == tmpdir)
+    tmpdir = "/tmp";
+  (void) GNUNET_asprintf (&fn, "%s/gnunet-testbed-spawn.lock", tmpdir);
+  /* Open the unique file; we can create it then we can spawn the child process
+     else we exit */
+  fh = open (fn, O_CREAT | O_EXCL | O_CLOEXEC,
+             S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP);
+  if (-1 == fh)
+  {
+    if (EEXIST == errno)
+    {
+      LOG_DEBUG ("Lock file already created by other process.  Exiting\n");
+      ret = GNUNET_OK;
+      return;
+    }
+    GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "open");
+    ret = GNUNET_SYSERR;
+    return;
+  }
+  /* Spawn the new process here */
+  LOG (GNUNET_ERROR_TYPE_INFO, _ ("Spawning process `%s'\n"), argv2[0]);
+  child = GNUNET_OS_start_process_vap (GNUNET_NO, GNUNET_OS_INHERIT_STD_ALL,
+                                       NULL,
+                                       NULL, NULL,
+                                       argv2[0], argv2);
+  if (NULL == child)
+  {
+    GNUNET_break (0);
+    ret = GNUNET_SYSERR;
+    GNUNET_SCHEDULER_add_now (&shutdown_task, NULL);
+    return;
+  }
+  ret = GNUNET_OK;
+  terminate_task_id =
+    GNUNET_SCHEDULER_add_shutdown (&terminate_task, NULL);
+  child_death_task_id =
+    GNUNET_SCHEDULER_add_read_file (GNUNET_TIME_UNIT_FOREVER_REL,
+                                    GNUNET_DISK_pipe_handle (sigpipe,
+                                                             GNUNET_DISK_PIPE_END_READ),
+                                    &child_death_task, NULL);
+}
+
+
+/**
+ * Signal handler called for SIGCHLD.
+ */
+static void
+sighandler_child_death ()
+{
+  static char c;
+  int old_errno = errno;        /* back-up errno */
+
+  GNUNET_break (1 ==
+                GNUNET_DISK_file_write (GNUNET_DISK_pipe_handle
+                                          (sigpipe, GNUNET_DISK_PIPE_END_WRITE),
+                                        &c, sizeof(c)));
+  errno = old_errno;            /* restore errno */
+}
+
+
+/**
+ * Execution start point
+ */
+int
+main (int argc, char *argv[])
+{
+  struct GNUNET_SIGNAL_Context *shc_chld;
+  unsigned int cnt;
+
+  ret = -1;
+  if (argc < 2)
+  {
+    printf ("Need arguments: gnunet-testbed-mpi-spawn <cmd> <cmd_args>");
+    return 1;
+  }
+  if (GNUNET_OK != GNUNET_log_setup ("gnunet-testbed-spawn", NULL, NULL))
+  {
+    GNUNET_break (0);
+    return 1;
+  }
+  if (NULL == (sigpipe = GNUNET_DISK_pipe (GNUNET_DISK_PF_NONE)))
+  {
+    GNUNET_break (0);
+    ret = GNUNET_SYSERR;
+    return 1;
+  }
+  shc_chld =
+    GNUNET_SIGNAL_handler_install (GNUNET_SIGCHLD, &sighandler_child_death);
+  if (NULL == shc_chld)
+  {
+    LOG (GNUNET_ERROR_TYPE_ERROR, "Cannot install a signal handler\n");
+    return 1;
+  }
+  argv2 = GNUNET_malloc (sizeof(char *) * argc);
+  for (cnt = 1; cnt < argc; cnt++)
+    argv2[cnt - 1] = argv[cnt];
+  GNUNET_SCHEDULER_run (run, NULL);
+  GNUNET_free (argv2);
+  GNUNET_SIGNAL_handler_uninstall (shc_chld);
+  shc_chld = NULL;
+  GNUNET_DISK_pipe_close (sigpipe);
+  GNUNET_free (fn);
+  if (GNUNET_OK != ret)
+    return ret;
+  return 0;
+}
diff --git a/src/testbed/misc.supp b/src/testbed/misc.supp
new file mode 100644
index 0000000000000000000000000000000000000000..4e4424b6cd8b080b580b75d4183e55f98b17cbc0
--- /dev/null
+++ b/src/testbed/misc.supp
@@ -0,0 +1,49 @@
+{
+   <get_log_call_status>
+   Memcheck:Leak
+   fun:malloc
+   ...
+   fun:re_acquire_state_context
+   fun:build_trtable
+   fun:re_search_internal
+   fun:regexec@@GLIBC_2.3.4
+   fun:GNUNET_get_log_call_status
+   ...
+}
+{
+   <log_setup>
+   Memcheck:Leak
+   ...
+   fun:GNUNET_log_setup   
+   ...
+}
+{
+   <get_log_status>
+   Memcheck:Leak
+   ...
+   fun:GNUNET_get_log_call_status
+   ...
+}
+{
+   <linux-loader>
+   Memcheck:Leak
+   fun:malloc
+   obj:/lib/i386-linux-gnu/libgcrypt.so.11.7.0
+   ...
+   obj:/lib/i386-linux-gnu/ld-2.15.so
+}
+{
+   <glibc-networking>
+   Memcheck:Leak
+   fun:malloc
+   fun:make_request
+   fun:__check_pf
+}
+{
+   <crypto-reachable>
+   Memcheck:Leak
+   ...
+   fun:GNUNET_CRYPTO_random_init
+   fun:call_init
+   ...
+}
diff --git a/src/testbed/profile-testbed.patch b/src/testbed/profile-testbed.patch
new file mode 100644
index 0000000000000000000000000000000000000000..50a8d5fed65a1ba005633b909f8beee112d8c639
--- /dev/null
+++ b/src/testbed/profile-testbed.patch
@@ -0,0 +1,43 @@
+Index: Makefile.am
+===================================================================
+--- Makefile.am	(revision 29343)
++++ Makefile.am	(working copy)
+@@ -59,7 +59,7 @@
+  $(top_builddir)/src/testing/libgnunettesting.la \
+  $(top_builddir)/src/testbed/libgnunettestbed.la \
+  $(top_builddir)/src/arm/libgnunetarm.la \
+- $(LTLIBINTL) $(Z_LIBS)
++ $(LTLIBINTL) $(Z_LIBS) -lprofiler
+ gnunet_service_testbed_DEPENDENCIES = \
+  libgnunettestbed.la
+ 
+Index: gnunet-service-testbed.c
+===================================================================
+--- gnunet-service-testbed.c	(revision 29341)
++++ gnunet-service-testbed.c	(working copy)
+@@ -26,6 +26,7 @@
+ 
+ #include "gnunet-service-testbed.h"
+ #include "gnunet-service-testbed_barriers.h"
++#include <gperftools/profiler.h>
+ 
+ /***********/
+ /* Globals */
+@@ -956,9 +957,14 @@
+ main (int argc, char *const *argv)
+ {
+   //sleep (15);                 /* Debugging */
+-  return (GNUNET_OK ==
+-          GNUNET_SERVICE_run (argc, argv, "testbed", GNUNET_SERVICE_OPTION_NONE,
+-                              &testbed_run, NULL)) ? 0 : 1;
++  int ret;
++
++  ProfilerStart (NULL);
++  ret = GNUNET_SERVICE_run (argc, argv, "testbed", GNUNET_SERVICE_OPTION_NONE,
++                            &testbed_run, NULL);
++  ProfilerStop ();
++  return (GNUNET_OK == ret) ? 0 : 1;
++  
+ }
+ 
+ /* end of gnunet-service-testbed.c */
diff --git a/src/testbed/test_testbed_api.c b/src/testbed/test_testbed_api.c
index dd270df17389b617896cac7522e4fada38e8cffb..49f1d9ae9692232d3bbe9a7a4851d0922f0dbde8 100644
--- a/src/testbed/test_testbed_api.c
+++ b/src/testbed/test_testbed_api.c
@@ -163,7 +163,7 @@ do_shutdown (void *cls)
     if (! (cond)) {                                              \
       GNUNET_break (0);                                          \
       if (NULL != abort_task)               \
-        GNUNET_SCHEDULER_cancel (abort_task);                   \
+      GNUNET_SCHEDULER_cancel (abort_task);                   \
       abort_task = NULL;                    \
       GNUNET_SCHEDULER_add_now (do_shutdown, NULL);             \
       ret;                                                   \
diff --git a/src/testbed/test_testbed_api_2peers_1controller.c b/src/testbed/test_testbed_api_2peers_1controller.c
index c854d1ccc33337727f6c6bef4a21d87536f2cb42..4a8b8a5841cd4295cafd71814d1aa2bd8702da14 100644
--- a/src/testbed/test_testbed_api_2peers_1controller.c
+++ b/src/testbed/test_testbed_api_2peers_1controller.c
@@ -173,7 +173,7 @@ static enum Stage result;
     if (! (cond)) {                                              \
       GNUNET_break (0);                                          \
       if (NULL != abort_task)               \
-        GNUNET_SCHEDULER_cancel (abort_task);                   \
+      GNUNET_SCHEDULER_cancel (abort_task);                   \
       abort_task = NULL;                    \
       GNUNET_SCHEDULER_add_now (do_shutdown, NULL);             \
       return;                                                   \
diff --git a/src/testbed/test_testbed_api_controllerlink.c b/src/testbed/test_testbed_api_controllerlink.c
index 16a3f7b916657fde00066551c29ce4ace35cb1e3..784407520878fb6fd43694f7a71224b8255de6d2 100644
--- a/src/testbed/test_testbed_api_controllerlink.c
+++ b/src/testbed/test_testbed_api_controllerlink.c
@@ -298,7 +298,7 @@ static enum Stage result;
     {                                         \
       GNUNET_break (0);                       \
       if (NULL != abort_task)                 \
-        GNUNET_SCHEDULER_cancel (abort_task); \
+      GNUNET_SCHEDULER_cancel (abort_task); \
       abort_task = NULL;                      \
       GNUNET_SCHEDULER_shutdown ();           \
       return;                                 \
diff --git a/src/testbed/test_testbed_api_peer_reconfiguration.c b/src/testbed/test_testbed_api_peer_reconfiguration.c
index 91955c13d2c0c651f3c05ce47a498577d240f0cb..22dd46b536592b377447a9a8ddaa08079b355b53 100644
--- a/src/testbed/test_testbed_api_peer_reconfiguration.c
+++ b/src/testbed/test_testbed_api_peer_reconfiguration.c
@@ -77,7 +77,7 @@ enum
     if (! (cond)) {                                              \
       GNUNET_break (0);                                          \
       if (NULL != abort_task)               \
-        GNUNET_SCHEDULER_cancel (abort_task);                   \
+      GNUNET_SCHEDULER_cancel (abort_task);                   \
       abort_task = GNUNET_SCHEDULER_add_now (&do_abort, NULL);  \
       ret;                                                      \
     }                                                           \
diff --git a/src/testbed/test_testbed_api_peers_manage_services.c b/src/testbed/test_testbed_api_peers_manage_services.c
index 6d4f8196afac193b587e9c4c9b3b7e5bb6e2f992..93b0da550895a4b7c80ccf44f1a391083ad824c2 100644
--- a/src/testbed/test_testbed_api_peers_manage_services.c
+++ b/src/testbed/test_testbed_api_peers_manage_services.c
@@ -92,7 +92,7 @@ enum
     if (! (cond)) {                                              \
       GNUNET_break (0);                                          \
       if (NULL != abort_task)               \
-        GNUNET_SCHEDULER_cancel (abort_task);                   \
+      GNUNET_SCHEDULER_cancel (abort_task);                   \
       abort_task = GNUNET_SCHEDULER_add_now (&do_abort, NULL);  \
       ret;                                                      \
     }                                                           \
diff --git a/src/testbed/test_testbed_api_statistics.c b/src/testbed/test_testbed_api_statistics.c
index dc305d008d14fb3db579f20771e330967e3f901c..4d42cda6a19cd3ecfb8bffe2bfac9e9c95789aa7 100644
--- a/src/testbed/test_testbed_api_statistics.c
+++ b/src/testbed/test_testbed_api_statistics.c
@@ -76,7 +76,7 @@ static unsigned int num_seen_peers;
     if (! (cond)) {                                              \
       GNUNET_break (0);                                          \
       if (NULL != abort_task)               \
-        GNUNET_SCHEDULER_cancel (abort_task);                   \
+      GNUNET_SCHEDULER_cancel (abort_task);                   \
       abort_task = GNUNET_SCHEDULER_add_now (&do_abort, NULL);  \
       ret;                                                      \
     }                                                           \
diff --git a/src/testbed/test_testbed_api_test.c b/src/testbed/test_testbed_api_test.c
index d3fec78d92d8248c7c97c7649440ff280a846efc..aefbd340e88530e8fafa3521b4f1b228eb680bd2 100644
--- a/src/testbed/test_testbed_api_test.c
+++ b/src/testbed/test_testbed_api_test.c
@@ -90,10 +90,10 @@ do_shutdown (void *cls)
     if (! (cond)) {                                                      \
       GNUNET_break (0);                                                  \
       if (NULL != abort_task)                       \
-        GNUNET_SCHEDULER_cancel (abort_task);                           \
+      GNUNET_SCHEDULER_cancel (abort_task);                           \
       abort_task = NULL;                            \
       if (NULL == shutdown_task)                    \
-        shutdown_task = GNUNET_SCHEDULER_add_now (&do_shutdown, NULL);   \
+      shutdown_task = GNUNET_SCHEDULER_add_now (&do_shutdown, NULL);   \
       return;                                                           \
     }                                                                   \
 } while (0)
diff --git a/src/testbed/testbed_api_hosts.c b/src/testbed/testbed_api_hosts.c
index f7352250da162dfec7afab02735fcb12a95f9003..95a6bf76fdebe7db6396a9bd7536c65c92ebc84f 100644
--- a/src/testbed/testbed_api_hosts.c
+++ b/src/testbed/testbed_api_hosts.c
@@ -56,7 +56,7 @@
   do                                                                       \
   {                                                                        \
     if (cond)                                                              \
-      break;                                                               \
+    break;                                                               \
     LOG (GNUNET_ERROR_TYPE_ERROR, "API violation detected: %s\n", errstr); \
     GNUNET_assert (0);                                                     \
   } while (0)
@@ -1384,8 +1384,7 @@ GNUNET_TESTBED_is_host_habitable (
     join_argv ((const char **) rsh_args, (const char **) rsh_suffix_args);
   free_argv (rsh_suffix_args);
   free_argv (rsh_args);
-  h->auxp = GNUNET_OS_start_process_vap (GNUNET_NO,
-                                         GNUNET_OS_INHERIT_STD_ERR,
+  h->auxp = GNUNET_OS_start_process_vap (GNUNET_OS_INHERIT_STD_ERR,
                                          NULL,
                                          NULL,
                                          NULL,
diff --git a/src/testbed/testbed_api_underlay.c b/src/testbed/testbed_api_underlay.c
new file mode 100644
index 0000000000000000000000000000000000000000..7e509fdfe031b375a5b37d05aa2675e49ef822dd
--- /dev/null
+++ b/src/testbed/testbed_api_underlay.c
@@ -0,0 +1,259 @@
+/*
+   This file is part of GNUnet.
+   Copyright (C) 2008--2013 GNUnet e.V.
+
+   GNUnet is free software: you can redistribute it and/or modify it
+   under the terms of the GNU Affero General Public License as published
+   by the Free Software Foundation, either version 3 of the License,
+   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
+   Affero General Public License for more details.
+
+   You should have received a copy of the GNU Affero General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+     SPDX-License-Identifier: AGPL3.0-or-later
+ */
+
+/**
+ * @file testbed/testbed_api_underlay.c
+ * @brief testbed underlay API implementation
+ * @author Sree Harsha Totakura <sreeharsha@totakura.in>
+ */
+
+#include "testbed_api_peers.h"
+
+
+/**
+ * An underlay link
+ */
+struct LinkProperty
+{
+  /**
+   * next pointer for list
+   */
+  struct LinkProperty *next;
+
+  /**
+   * the peer whose link is defined by these properties
+   */
+  struct GNUNET_TESTBED_Peer *peer;
+
+  /**
+   * latency of the link in microseconds
+   */
+  uint32_t latency;
+
+  /**
+   * data loss on the link expressed as percentage
+   */
+  uint32_t loss;
+
+  /**
+   * bandwidth of the link in kilobytes per second
+   */
+  uint32_t bandwidth;
+};
+
+
+/**
+ * Container for holding a peer in whitelist/blacklist
+ */
+struct ListEntry
+{
+  /**
+   * the next pointer
+   */
+  struct ListEntry *next;
+
+  /**
+   * the peer
+   */
+  struct GNUNET_TESTBED_Peer *peer;
+};
+
+
+/**
+ * Model for configuring underlay links of a peer
+ * @ingroup underlay
+ */
+struct GNUNET_TESTBED_UnderlayLinkModel
+{
+  /**
+   * The peer associated with this model
+   */
+  struct GNUNET_TESTBED_Peer *peer;
+
+  /**
+   * List of peers in the list
+   */
+  struct ListEntry *entries;
+
+  /**
+   * list of link properties
+   */
+  struct LinkProperty *props;
+
+  /**
+   * the type of this model
+   */
+  enum GNUNET_TESTBED_UnderlayLinkModelType type;
+}
+
+
+/**
+ * Function to free resources of list entries
+ *
+ * @param model the model
+ */
+static void
+free_entries (struct GNUNET_TESTBED_UnderlayLinkModel *model)
+{
+  struct ListEntry *e;
+
+  while (NULL != (e = model->entries))
+  {
+    model->entries = e->next;
+    GNUNET_free (e);
+  }
+}
+
+
+/**
+ * Function to free resources of link properties added to the given model
+ *
+ * @param model the model
+ */
+static void
+free_link_properties (struct GNUNET_TESTBED_UnderlayLinkModel *model)
+{
+  struct LinkProperty *p;
+
+  while (NULL != (p = model->props))
+  {
+    model->props = p->next;
+    GNUNET_free (p);
+  }
+}
+
+
+/**
+ * Create a GNUNET_TESTBED_UnderlayLinkModel for the given peer.  A peer can
+ * have ONLY ONE model and it can be either a blacklist or whitelist based one.
+ *
+ * @ingroup underlay
+ * @param peer the peer for which the model has to be created
+ * @param type the type of the model
+ * @return the model
+ */
+struct GNUNET_TESTBED_UnderlayLinkModel *
+GNUNET_TESTBED_underlaylinkmodel_create (struct GNUNET_TESTBED_Peer *peer,
+                                         enum
+                                         GNUNET_TESTBED_UnderlayLinkModelType
+                                         type)
+{
+  struct GNUNET_TESTBED_UnderlayLinkModel *m;
+
+  GNUNET_assert (0 == peer->underlay_model_exists);
+  m = GNUNET_new (struct GNUNET_TESTBED_UnderlayLinkModel);
+  peer->underlay_model_exists = 1;
+  m->type = type;
+  return m;
+}
+
+
+/**
+ * Add a peer to the given model.  Underlay connections to the given peer will
+ * be permitted if the model is whitelist based; otherwise they will not be
+ * permitted.
+ *
+ * @ingroup underlay
+ * @param model the model
+ * @param peer the peer to add
+ */
+void
+GNUNET_TESTBED_underlaylinkmodel_add_peer (struct
+                                           GNUNET_TESTBED_UnderlayLinkModel *
+                                           model,
+                                           struct GNUNET_TESTBED_Peer *peer)
+{
+  struct ListEntry *entry;
+
+  entry = GNUNET_new (struct ListEntry);
+  entry->peer = peer;
+  entry->next = model->entries;
+  model->entries = entry;
+}
+
+
+/**
+ * Set the metrics for a link to the given peer in the underlay model.  The link
+ * SHOULD be permittable according to the given model.
+ *
+ * @ingroup underlay
+ * @param model the model
+ * @param peer the other end peer of the link
+ * @param latency latency of the link in microseconds
+ * @param loss data loss of the link expressed as a percentage
+ * @param bandwidth bandwidth of the link in kilobytes per second [kB/s]
+ */
+void
+GNUNET_TESTBED_underlaylinkmodel_set_link (struct
+                                           GNUNET_TESTBED_UnderlayLinkModel *
+                                           model,
+                                           struct GNUNET_TESTBED_Peer *peer,
+                                           uint32_t latency,
+                                           uint32_t loss,
+                                           uint32_t bandwidth)
+{
+  struct LinkProperty *prop;
+
+  prop = GNUNET_new (struct LinkProperty);
+  prop->peer = peer;
+  prop->latency = latency;
+  prop->loss = loss;
+  prop->bandwidth = bandwidth;
+  prop->next = model->props;
+  model->props = prop;
+}
+
+
+/**
+ * Free the resources of the model.  Use this function only if the model has not
+ * be committed and has to be unallocated.  The peer can then have another model
+ * created.
+ *
+ * @ingroup underlay
+ * @param model the model to unallocate
+ */
+void
+GNUNET_TESTBED_underlaylinkmodel_free (struct
+                                       GNUNET_TESTBED_UnderlayLinkModel *model)
+{
+  model->peer->underlay_model_exists = 0;
+  free_entries (model);
+  free_link_properties (model);
+  gnunet_free (model);
+}
+
+
+/**
+ * Commit the model.  The model is freed in this function(!).
+ *
+ * @ingroup underlay
+ * @param model the model to commit
+ */
+void
+GNUNET_TESTBED_underlaylinkmodel_commit (struct
+                                         GNUNET_TESTBED_UnderlayLinkModel *model)
+{
+  /* FIXME: Marshal the model into a message */
+  GNUNET_break (0);
+  /* do not reset the value of model->peer->underlay_model_exists */
+  free_entries (model);
+  free_link_properties (model);
+  GNUNET_free (model);
+}
diff --git a/src/testbed/valgrind-zlib.supp b/src/testbed/valgrind-zlib.supp
new file mode 100644
index 0000000000000000000000000000000000000000..ca6ce115fcf24a4e50e7e197b3013f9ca39f1d4c
--- /dev/null
+++ b/src/testbed/valgrind-zlib.supp
@@ -0,0 +1,6 @@
+{
+   <ZlibInflateReset2UninitJump>
+   Memcheck:Cond
+   fun:inflateReset2
+   ...
+}
diff --git a/src/testbed/x64_misc.supp b/src/testbed/x64_misc.supp
new file mode 100644
index 0000000000000000000000000000000000000000..e6a19c33e3d47ac8dc2d9c3b83acb43c2804f1ce
--- /dev/null
+++ b/src/testbed/x64_misc.supp
@@ -0,0 +1,34 @@
+{
+   <unknown invalid free>
+   Memcheck:Free
+   fun:free
+   fun:free_mem
+   fun:__libc_freeres
+   fun:_vgnU_freeres
+   fun:__run_exit_handlers
+   fun:exit
+   fun:(below main)
+}
+{
+   <gnunet_crypto_init>
+   Memcheck:Leak
+   fun:malloc
+   obj:/usr/lib/libgcrypt.so.11.5.3
+   ...
+   obj:/usr/lib/libgcrypt.so.11.5.3
+   fun:gcry_control
+   fun:GNUNET_CRYPTO_random_init
+   obj:/home/harsha/repos/gnunet/src/util/.libs/libgnunetutil.so.8.0.0
+   obj:/home/harsha/repos/gnunet/src/util/.libs/libgnunetutil.so.8.0.0
+}
+
+{
+   <insert_a_suppression_name_here>
+   Memcheck:Leak
+   fun:malloc
+   ...
+   fun:gcry_control
+   fun:GNUNET_CRYPTO_random_init
+   obj:/home/totakura/gnunet/src/util/.libs/libgnunetutil.so.8.0.0
+   obj:/home/totakura/gnunet/src/util/.libs/libgnunetutil.so.8.0.0
+}
diff --git a/src/testing/.gitignore b/src/testing/.gitignore
new file mode 100644
index 0000000000000000000000000000000000000000..f350da1f2726e2e4881b190769abf92f9e0a7d5c
--- /dev/null
+++ b/src/testing/.gitignore
@@ -0,0 +1,7 @@
+list-keys
+gnunet-testing
+test_testing_peerstartup
+test_testing_peerstartup2
+test_testing_portreservation
+test_testing_servicestartup
+test_testing_sharedservices
diff --git a/src/testing/testing.c b/src/testing/testing.c
index 0ca4c30632102ef584c801d402aa4f2b8d374bad..9724fb55baf5b325671cccd44fb581379fdb0b76 100644
--- a/src/testing/testing.c
+++ b/src/testing/testing.c
@@ -37,12 +37,6 @@
 #define LOG(kind, ...) GNUNET_log_from (kind, "testing-api", __VA_ARGS__)
 
 
-/**
- * We need pipe control only on WINDOWS
- */
-#define PIPE_CONTROL GNUNET_NO
-
-
 /**
  * Lowest port used for GNUnet testing.  Should be high enough to not
  * conflict with other applications running on the hosts but be low
@@ -492,8 +486,7 @@ start_shared_service_instance (struct SharedServiceInstance *i)
   (void) GNUNET_asprintf (&binary, "gnunet-service-%s", i->ss->sname);
   libexec_binary = GNUNET_OS_get_libexec_binary_path (binary);
   GNUNET_free (binary);
-  i->proc = GNUNET_OS_start_process (PIPE_CONTROL,
-                                     GNUNET_OS_INHERIT_STD_OUT_AND_ERR,
+  i->proc = GNUNET_OS_start_process (GNUNET_OS_INHERIT_STD_OUT_AND_ERR,
                                      NULL,
                                      NULL,
                                      NULL,
@@ -1378,8 +1371,7 @@ GNUNET_TESTING_peer_start (struct GNUNET_TESTING_Peer *peer)
   peer->main_binary =
     GNUNET_CONFIGURATION_expand_dollar (peer->cfg, peer->main_binary);
   peer->main_process =
-    GNUNET_OS_start_process_s (PIPE_CONTROL,
-                               GNUNET_OS_INHERIT_STD_OUT_AND_ERR,
+    GNUNET_OS_start_process_s (GNUNET_OS_INHERIT_STD_OUT_AND_ERR,
                                NULL,
                                peer->main_binary,
                                peer->args,
diff --git a/src/topology/.gitignore b/src/topology/.gitignore
new file mode 100644
index 0000000000000000000000000000000000000000..cfa95ec7ebd19c2f7f1d02ec355c4704f942189c
--- /dev/null
+++ b/src/topology/.gitignore
@@ -0,0 +1,2 @@
+gnunet-daemon-topology
+test_gnunet_daemon_topology
diff --git a/src/transport/.gitignore b/src/transport/.gitignore
new file mode 100644
index 0000000000000000000000000000000000000000..d88d40ef790477c479168b495061791b72938cfc
--- /dev/null
+++ b/src/transport/.gitignore
@@ -0,0 +1,91 @@
+gnunet-transport-wlan-sender
+gnunet-helper-transport-bluetooth
+gnunet-helper-transport-wlan
+gnunet-helper-transport-wlan-dummy
+gnunet-service-transport
+gnunet-transport
+gnunet-transport-certificate-creation
+gnunet-transport-profiler
+gnunet-transport-wlan-receiver
+https_cert_qutoa_p2.crt
+https_key_quota_p2.key
+test_http_common
+test_plugin_bluetooth
+test_plugin_http_client
+test_plugin_http_server
+test_plugin_https_client
+test_plugin_https_server
+test_plugin_tcp
+test_plugin_udp
+test_plugin_unix
+test_plugin_wlan
+test_quota_compliance_bluetooth
+test_quota_compliance_bluetooth_asymmetric
+test_quota_compliance_http
+test_quota_compliance_http_asymmetric
+test_quota_compliance_https
+test_quota_compliance_https_asymmetric
+test_quota_compliance_tcp
+test_quota_compliance_tcp_asymmetric
+test_quota_compliance_udp
+test_quota_compliance_unix
+test_quota_compliance_unix_asymmetric
+test_quota_compliance_wlan
+test_quota_compliance_wlan_asymmetric
+test_transport_address_switch_http
+test_transport_address_switch_https
+test_transport_address_switch_tcp
+test_transport_address_switch_udp
+test_transport_api_blacklisting_tcp
+test_transport_api_bluetooth
+test_transport_api_disconnect_tcp
+test_transport_api_http
+test_transport_api_http_reverse
+test_transport_api_https
+test_transport_api_limited_sockets_tcp
+test_transport_api_manipulation_cfg
+test_transport_api_manipulation_recv_tcp
+test_transport_api_manipulation_send_tcp
+test_transport_api_monitor_peers
+test_transport_api_multi
+test_transport_api_reliability_bluetooth
+test_transport_api_reliability_http
+test_transport_api_reliability_http_xhr
+test_transport_api_reliability_https
+test_transport_api_reliability_https_xhr
+test_transport_api_reliability_tcp
+test_transport_api_reliability_tcp_nat
+test_transport_api_reliability_udp
+test_transport_api_reliability_unix
+test_transport_api_reliability_wlan
+test_transport_api_restart_1peer
+test_transport_api_restart_2peers
+test_transport_api_slow_ats
+test_transport_api_tcp
+test_transport_api_tcp_nat
+test_transport_api_timeout_bluetooth
+test_transport_api_timeout_http
+test_transport_api_timeout_https
+test_transport_api_timeout_tcp
+test_transport_api_timeout_udp
+test_transport_api_timeout_unix
+test_transport_api_timeout_wlan
+test_transport_api_udp
+test_transport_api_udp_nat
+test_transport_api_unix
+test_transport_api_unix_abstract
+test_transport_api_wlan
+test_transport_blacklisting_inbound_bl_full
+test_transport_blacklisting_inbound_bl_plugin
+test_transport_blacklisting_multiple_plugins
+test_transport_blacklisting_no_bl
+test_transport_blacklisting_outbound_bl_full
+test_transport_blacklisting_outbound_bl_plugin
+test_transport_testing_restart
+test_transport_testing_startstop
+gnunet-communicator-unix
+gnunet-service-tng
+gnunet-communicator-tcp
+gnunet-communicator-udp
+test_communicator_unix
+test_communicator_basic_unix
diff --git a/src/transport/Makefile.am b/src/transport/Makefile.am
index 354bb1cf48091cd069cf4e0e27cadf8c937837f3..e0369059db6c73a5e43471f2c2c7a28d3a67d08e 100644
--- a/src/transport/Makefile.am
+++ b/src/transport/Makefile.am
@@ -278,6 +278,7 @@ gnunet_communicator_tcp_SOURCES = \
  gnunet-communicator-tcp.c
 gnunet_communicator_tcp_LDADD = \
   libgnunettransportcommunicator.la \
+  $(top_builddir)/src/peerstore/libgnunetpeerstore.la \
   $(top_builddir)/src/nat/libgnunetnatnew.la \
   $(top_builddir)/src/nt/libgnunetnt.la \
   $(top_builddir)/src/statistics/libgnunetstatistics.la \
diff --git a/src/transport/NOTES b/src/transport/NOTES
new file mode 100644
index 0000000000000000000000000000000000000000..41404e1f94e4efdf924d1621c1e77d0b5f490e5b
--- /dev/null
+++ b/src/transport/NOTES
@@ -0,0 +1,46 @@
+KEY DESIGN CHOICES:
+ - who decides which connections to keep/create?
+   => higher level session/key management!
+ - who enforces things like F2F topology, etc?
+   => higher level session/key management!
+ - who tracks all known HELLOs & validates? 
+   => We validate, PEERINFO tracks!
+ - who advertises our HELLO?
+   => us! (need background job; previously: advertising)
+ - who advertises other peers HELLOs?
+   => higher level (core?)
+ - who does bootstrapping?
+   => bootstrap service (external!)
+ - who enforces inbound bandwidth limits?
+   => transport-service and plugins! (previously: core); 
+      either by limiting reads (TCP) or discarding packets 
+      (transport-service)
+ - who enforces outbound bandwidth limits?
+   => transport_api!
+ - who decides outbound bandwidth limits?
+   => other peer, via core (need authenticated limits!)
+ - who decides inbound bandwidth limits?
+   => core / apps above core (need trust info)
+ - cost function for transports is latency estimate in ms
+   => plugin provides latency data, transport-service
+      selects plugin(s) for transmission
+ - who is responsible for fragmentation?
+   => plugins! (may use common shared library)
+ - should we require UDP to be reliable?
+   => NO.  There are other places that may (rarely)
+      use messages that we can not fix
+ - how do we access the 50% of service that we need for TCP/UDP
+   from service.c without code replication or getting 50%
+   that we do not want (i.e. shutdown, pid-file-writing, etc.)
+   => use GNUNET_SERVICE_start/stop functions!
+ - At what level do we manage timeouts? 
+   => At the plugin (TCP connections),
+      transport-service (neighbours) and 
+      core (sessions) level!
+   => All plugins have to disconnect before service-level
+      disconnect occurs
+   => We can have a plugin-connection die, but the session
+      survives!
+   => We can have a session die (no further authenticated
+      communication) even if the plugin thinks it is still
+      up!
diff --git a/src/transport/benchmark.sh b/src/transport/benchmark.sh
new file mode 100755
index 0000000000000000000000000000000000000000..a29e6ec2ddfbdc17e83e044f02113640ee42ebba
--- /dev/null
+++ b/src/transport/benchmark.sh
@@ -0,0 +1,13 @@
+#!/bin/sh
+
+for i in $(seq 1 0)
+do
+ echo RUN $i
+ ./test_transport_api_reliability_http
+done
+
+for i in $(seq 1 100)
+do
+ echo RUN $i
+ ./test_transport_api_reliability_https
+done
diff --git a/src/transport/communicator.h b/src/transport/communicator.h
new file mode 100644
index 0000000000000000000000000000000000000000..ab7a25de6809d71e7bcbf575f4488eb3cc7587c9
--- /dev/null
+++ b/src/transport/communicator.h
@@ -0,0 +1,138 @@
+/*
+     This file is part of GNUnet.
+     Copyright (C) 2009-2014 GNUnet e.V.
+
+     GNUnet is free software: you can redistribute it and/or modify it
+     under the terms of the GNU Affero General Public License as published
+     by the Free Software Foundation, either version 3 of the License,
+     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
+     Affero General Public License for more details.
+
+     You should have received a copy of the GNU Affero General Public License
+     along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+     SPDX-License-Identifier: AGPL3.0-or-later
+ */
+
+/**
+ * @file transport/communicator.h
+ * @brief common internal definitions for communicator services
+ * @author Christian Grothoff
+ */
+#ifndef COMMUNICATOR_H
+#define COMMUNICAOTR_H
+
+#include "gnunet_util_lib.h"
+#include "gnunet_protocols.h"
+
+GNUNET_NETWORK_STRUCT_BEGIN
+
+/**
+ * Message used to tell a communicator about a successful
+ * key exchange.
+ *
+ * Note that this style of KX acknowledgement typically only applies
+ * for communicators where the underlying network protocol is
+ * unidirectional and/or lacks cryptography.  Furthermore, this is
+ * just the recommended "generic" style, communicators are always free
+ * to implement original designs that better fit their requirements.
+ */
+struct GNUNET_TRANSPORT_CommunicatorGenericKXConfirmation
+{
+  /**
+   * Type is #GNUNET_MESSAGE_TYPE_TRANSPORT_COMMUNICATOR_KX_CONFIRMATION
+   */
+  struct GNUNET_MessageHeader header;
+
+  /**
+   * Timestamp from the original sender which identifies the original KX.
+   */
+  struct GNUNET_TIME_AbsoluteNBO monotonic_time;
+
+  /**
+   * How long does the receiver of the KX believe that the address
+   * on which the KX was received will continue to be valid.
+   */
+  struct GNUNET_TIME_RelativeNBO validity;
+
+  /**
+   * Hash of the shared secret. Specific hash function may depend on
+   * the communicator's protocol details.
+   */
+  struct GNUNET_HashCode token;
+};
+
+
+/**
+ * Message used to tell a communicator about the receiver's
+ * flow control limits and to acknowledge receipt of certain
+ * messages.
+ *
+ * Note that a sender MAY choose to violate the flow-control
+ * limits provided in this message by a receiver, which may
+ * result in messages being lost (after all, transport is an
+ * unreliable channel).  So if the sender violates these
+ * constraints, it should expect that the receive will simply
+ * discard the (partially) received "old" messages.
+ *
+ * This way, if a sender or receiver crashes, there is no protocol
+ * violation.
+ *
+ * Note that this style of flow control typically only applies
+ * for communicators where the underlying network protocol does
+ * not already implement flow control.  Furthermore, this is
+ * just the recommended "generic" style, communicators are always
+ * free to implement original designs that better fit their
+ * requirements.
+ */
+struct GNUNET_TRANSPORT_CommunicatorGenericFCLimits
+{
+  /**
+   * Type is #GNUNET_MESSAGE_TYPE_TRANSPORT_COMMUNICATOR_FC_LIMITS
+   */
+  struct GNUNET_MessageHeader header;
+
+  /**
+   * Maximum number of messages beyond the acknowledged message
+   * number that can still be transmitted concurrently without
+   * further acknowledgements.
+   */
+  uint32_t msg_window_size;
+
+  /**
+   * Up to which message number were all messages received.
+   */
+  uint64_t msg_cummulative_ack;
+
+  /**
+   * Maximum number of payload bytes beyond the acknowledged
+   * number of bytes can still be transmitted without further
+   * acknowledgements.
+   */
+  uint64_t bytes_window_size;
+
+  /**
+   * Cummulative acknowledgement for number of bytes received.
+   */
+  uint64_t bytes_cummulative_ack;
+
+  /**
+   * Followed by a variable-size bitfield for messages received
+   * beyond @e msg_cummulative_ack. Index at offset 0 must thus
+   * be zero, otherwise @e msg_cummulative_ack should be
+   * increased.  Note that this field can be overall of 0 bytes.
+   * The variable-size bitfield must be a multiple of 64 bits
+   * long.
+   */
+  /* uint64_t msg_selective_ack_field[]; */
+};
+
+
+GNUNET_NETWORK_STRUCT_END
+
+/* end of communicator.h */
+#endif
diff --git a/src/transport/gnunet-communicator-tcp.c b/src/transport/gnunet-communicator-tcp.c
index e25cdf13916ace68b0c07b0ed817e5bd7b5e6f82..59f42496a03c7277e5c39fc784d5fcf9946c44fa 100644
--- a/src/transport/gnunet-communicator-tcp.c
+++ b/src/transport/gnunet-communicator-tcp.c
@@ -24,26 +24,22 @@
  * @author Christian Grothoff
  *
  * TODO:
- * - support DNS names in BINDTO option (#5528)
  * - support NAT connection reversal method (#5529)
  * - support other TCP-specific NAT traversal methods (#5531)
- * - add replay protection support to the protocol by
- *   adding a nonce in the KX and requiring (!) a
- *   nounce ACK to be send within the first X bytes of
- *   data (#5530)
  */
 #include "platform.h"
 #include "gnunet_util_lib.h"
+#include "gnunet_core_service.h"
+#include "gnunet_peerstore_service.h"
 #include "gnunet_protocols.h"
 #include "gnunet_signatures.h"
 #include "gnunet_constants.h"
 #include "gnunet_nt_lib.h"
 #include "gnunet_nat_service.h"
 #include "gnunet_statistics_service.h"
-#include "gnunet_ats_transport_service.h"
-#include "transport.h"
 #include "gnunet_transport_communication_service.h"
 #include "gnunet_resolver_service.h"
+
 /**
  * How long do we believe our addresses to remain up (before
  * the other peer should revalidate).
@@ -91,6 +87,13 @@
   (sizeof(struct GNUNET_CRYPTO_EcdhePublicKey)   \
    + sizeof(struct TCPConfirmation))
 
+/**
+ * Size of the initial core key exchange messages.
+ */
+#define INITIAL_CORE_KX_SIZE          \
+  (sizeof(struct EphemeralKeyMessage)   \
+   + sizeof(struct PingMessage) \
+   + sizeof(struct PongMessage))
 
 /**
  * Address prefix used by the communicator.
@@ -136,8 +139,45 @@ struct TcpHandshakeSignature
    * (if receiver persists times by sender).
    */
   struct GNUNET_TIME_AbsoluteNBO monotonic_time;
+
+  /**
+   * Challenge value used to protect against replay attack, if there is no stored monotonic time value.
+   */
+  struct ChallengeNonceP challenge;
 };
 
+/**
+ * Signature we use to verify that the ack from the receiver of the ephemeral key was really send by
+ * the specified sender.
+ */
+struct TcpHandshakeAckSignature
+{
+  /**
+   * Purpose must be #GNUNET_SIGNATURE_COMMUNICATOR_TCP_HANDSHAKE_ACK
+   */
+  struct GNUNET_CRYPTO_EccSignaturePurpose purpose;
+
+  /**
+   * Identity of the inititor of the TCP connection (TCP client).
+   */
+  struct GNUNET_PeerIdentity sender;
+
+  /**
+   * Presumed identity of the target of the TCP connection (TCP server)
+   */
+  struct GNUNET_PeerIdentity receiver;
+
+  /**
+   * Monotonic time of @e sender, to possibly help detect replay attacks
+   * (if receiver persists times by sender).
+   */
+  struct GNUNET_TIME_AbsoluteNBO monotonic_time;
+
+  /**
+   * Challenge value used to protect against replay attack, if there is no stored monotonic time value.
+   */
+  struct ChallengeNonceP challenge;
+};
 
 /**
  * Encrypted continuation of TCP initial handshake.
@@ -159,8 +199,48 @@ struct TCPConfirmation
    * (if receiver persists times by sender).
    */
   struct GNUNET_TIME_AbsoluteNBO monotonic_time;
+
+  /**
+   * Challenge value used to protect against replay attack, if there is no stored monotonic time value.
+   */
+  struct ChallengeNonceP challenge;
+
 };
 
+/**
+ * Ack for the encrypted continuation of TCP initial handshake.
+ */
+struct TCPConfirmationAck
+{
+
+
+  /**
+   * Type is #GNUNET_MESSAGE_TYPE_COMMUNICATOR_TCP_CONFIRMATION_ACK.
+   */
+  struct GNUNET_MessageHeader header;
+
+  /**
+   * Sender's identity
+   */
+  struct GNUNET_PeerIdentity sender;
+
+  /**
+   * Sender's signature of type #GNUNET_SIGNATURE_COMMUNICATOR_TCP_HANDSHAKE_ACK
+   */
+  struct GNUNET_CRYPTO_EddsaSignature sender_sig;
+
+  /**
+   * Monotonic time of @e sender, to possibly help detect replay attacks
+   * (if receiver persists times by sender).
+   */
+  struct GNUNET_TIME_AbsoluteNBO monotonic_time;
+
+  /**
+   * Challenge value used to protect against replay attack, if there is no stored monotonic time value.
+   */
+  struct ChallengeNonceP challenge;
+
+};
 
 /**
  * TCP message box.  Always sent encrypted!
@@ -228,6 +308,38 @@ struct TCPRekey
   struct GNUNET_TIME_AbsoluteNBO monotonic_time;
 };
 
+/**
+ * Signature we use to verify that the ephemeral key was really chosen by
+ * the specified sender.
+ */
+struct TcpRekeySignature
+{
+  /**
+   * Purpose must be #GNUNET_SIGNATURE_COMMUNICATOR_TCP_REKEY
+   */
+  struct GNUNET_CRYPTO_EccSignaturePurpose purpose;
+
+  /**
+   * Identity of the inititor of the TCP connection (TCP client).
+   */
+  struct GNUNET_PeerIdentity sender;
+
+  /**
+   * Presumed identity of the target of the TCP connection (TCP server)
+   */
+  struct GNUNET_PeerIdentity receiver;
+
+  /**
+   * Ephemeral key used by the @e sender.
+   */
+  struct GNUNET_CRYPTO_EcdhePublicKey ephemeral;
+
+  /**
+   * Monotonic time of @e sender, to possibly help detect replay attacks
+   * (if receiver persists times by sender).
+   */
+  struct GNUNET_TIME_AbsoluteNBO monotonic_time;
+};
 
 /**
  * TCP finish. Sender asks for the connection to be closed.
@@ -281,11 +393,6 @@ struct Queue
    */
   struct GNUNET_PeerIdentity target;
 
-  /**
-   * ID of listen task
-   */
-  struct GNUNET_SCHEDULER_Task *listen_task;
-
   /**
    * Listen socket.
    */
@@ -456,6 +563,56 @@ struct Queue
    * re-decrypt ciphertext.
    */
   int rekeyed;
+
+  /**
+   * Monotonic time value for rekey message.
+   */
+  struct GNUNET_TIME_AbsoluteNBO rekey_monotonic_time;
+
+  /**
+   * Monotonic time value for handshake message.
+   */
+  struct GNUNET_TIME_AbsoluteNBO handshake_monotonic_time;
+
+  /**
+   * Monotonic time value for handshake ack message.
+   */
+  struct GNUNET_TIME_AbsoluteNBO handshake_ack_monotonic_time;
+
+  /**
+   * Challenge value used to protect against replay attack, if there is no stored monotonic time value.
+   */
+  struct ChallengeNonceP challenge;
+
+  /**
+   * Iteration Context for retrieving the monotonic time send with key for rekeying.
+   */
+  struct GNUNET_PEERSTORE_IterateContext *rekey_monotime_get;
+
+  /**
+   * Iteration Context for retrieving the monotonic time send with the handshake.
+   */
+  struct GNUNET_PEERSTORE_IterateContext *handshake_monotime_get;
+
+  /**
+   * Iteration Context for retrieving the monotonic time send with the handshake ack.
+   */
+  struct GNUNET_PEERSTORE_IterateContext *handshake_ack_monotime_get;
+
+  /**
+   * Store Context for retrieving the monotonic time send with key for rekeying.
+   */
+  struct GNUNET_PEERSTORE_StoreContext *rekey_monotime_sc;
+
+  /**
+   * Store Context for retrieving the monotonic time send with the handshake.
+   */
+  struct GNUNET_PEERSTORE_StoreContext *handshake_monotime_sc;
+
+  /**
+   * Store Context for retrieving the monotonic time send with the handshake ack.
+   */
+  struct GNUNET_PEERSTORE_StoreContext *handshake_ack_monotime_sc;
 };
 
 
@@ -475,11 +632,6 @@ struct ProtoQueue
    */
   struct ProtoQueue *prev;
 
-  /**
-   * ID of listen task
-   */
-  struct GNUNET_SCHEDULER_Task *listen_task;
-
   /**
    * Listen socket.
    */
@@ -535,7 +687,7 @@ struct PortOnlyIpv4Ipv6
   /**
    * Length of ipv4 address.
    */
-  socklen_t *addr_len_ipv4;
+  socklen_t addr_len_ipv4;
 
   /**
    * Ipv6 address we like to bind to.
@@ -545,7 +697,7 @@ struct PortOnlyIpv4Ipv6
   /**
    * Length of ipv6 address.
    */
-  socklen_t *addr_len_ipv6;
+  socklen_t addr_len_ipv6;
 
 };
 
@@ -598,6 +750,11 @@ static struct GNUNET_TRANSPORT_CommunicatorHandle *ch;
  */
 static struct GNUNET_CONTAINER_MultiPeerMap *queue_map;
 
+/**
+ * ListenTasks (map from socket to `struct ListenTask`)
+ */
+static struct GNUNET_CONTAINER_MultiHashMap *lt_map;
+
 /**
  * Our public key.
  */
@@ -653,11 +810,41 @@ struct Addresses *addrs_head;
  */
 struct Addresses *addrs_tail;
 
+/**
+ * Head of DLL with ListenTasks.
+ */
+struct ListenTask *lts_head;
+
+/**
+ * Head of DLL with ListenTask.
+ */
+struct ListenTask *lts_tail;
+
 /**
  * Number of addresses in the DLL for register at NAT service.
  */
 int addrs_lens;
 
+/**
+ * Size of data received without KX challenge played back.
+ */
+size_t unverified_size;
+
+/**
+ * Database for peer's HELLOs.
+ */
+static struct GNUNET_PEERSTORE_Handle *peerstore;
+
+/**
+ * A flag indicating we are already doing a shutdown.
+ */
+int shutdown_running = GNUNET_NO;
+
+/**
+ * The port the communicator should be assigned to.
+ */
+unsigned int bind_port;
+
 /**
  * We have been notified that our listen socket has something to
  * read. Do the read and reschedule this function to be called again
@@ -668,7 +855,6 @@ int addrs_lens;
 static void
 listen_cb (void *cls);
 
-
 /**
  * Functions with this signature are called whenever we need
  * to close a queue due to a disconnect or failure to
@@ -679,19 +865,47 @@ listen_cb (void *cls);
 static void
 queue_destroy (struct Queue *queue)
 {
-  struct GNUNET_MQ_Handle *mq;
-  struct ListenTask *lt;
-  lt = GNUNET_new (struct ListenTask);
-  lt->listen_sock = queue->listen_sock;
-  lt->listen_task = queue->listen_task;
+  struct ListenTask *lt = NULL;
+  struct GNUNET_HashCode h_sock;
+
+  GNUNET_CRYPTO_hash (queue->listen_sock,
+                      sizeof(queue->listen_sock),
+                      &h_sock);
+
+  lt =   GNUNET_CONTAINER_multihashmap_get (lt_map, &h_sock);
 
   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
               "Disconnecting queue for peer `%s'\n",
               GNUNET_i2s (&queue->target));
-  if (NULL != (mq = queue->mq))
+  if (NULL != queue->rekey_monotime_sc)
   {
-    queue->mq = NULL;
-    GNUNET_MQ_destroy (mq);
+    GNUNET_PEERSTORE_store_cancel (queue->rekey_monotime_sc);
+    queue->rekey_monotime_sc = NULL;
+  }
+  if (NULL != queue->handshake_monotime_sc)
+  {
+    GNUNET_PEERSTORE_store_cancel (queue->handshake_monotime_sc);
+    queue->handshake_monotime_sc = NULL;
+  }
+  if (NULL != queue->handshake_ack_monotime_sc)
+  {
+    GNUNET_PEERSTORE_store_cancel (queue->handshake_ack_monotime_sc);
+    queue->handshake_ack_monotime_sc = NULL;
+  }
+  if (NULL != queue->rekey_monotime_get)
+  {
+    GNUNET_PEERSTORE_iterate_cancel (queue->rekey_monotime_get);
+    queue->rekey_monotime_get = NULL;
+  }
+  if (NULL != queue->handshake_monotime_get)
+  {
+    GNUNET_PEERSTORE_iterate_cancel (queue->handshake_monotime_get);
+    queue->handshake_monotime_get = NULL;
+  }
+  if (NULL != queue->handshake_ack_monotime_get)
+  {
+    GNUNET_PEERSTORE_iterate_cancel (queue->handshake_ack_monotime_get);
+    queue->handshake_ack_monotime_get = NULL;
   }
   if (NULL != queue->qh)
   {
@@ -715,7 +929,11 @@ queue_destroy (struct Queue *queue)
     GNUNET_SCHEDULER_cancel (queue->write_task);
     queue->write_task = NULL;
   }
-  GNUNET_NETWORK_socket_close (queue->sock);
+  if (GNUNET_SYSERR == GNUNET_NETWORK_socket_close (queue->sock))
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                "closing socket failed\n");
+  }
   gcry_cipher_close (queue->in_cipher);
   gcry_cipher_close (queue->out_cipher);
   GNUNET_free (queue->address);
@@ -724,12 +942,18 @@ queue_destroy (struct Queue *queue)
   else
     GNUNET_free (queue);
 
-  if (NULL == lt->listen_task)
+  if ((! shutdown_running) && (NULL == lt->listen_task))
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                "add read net listen\n");
     lt->listen_task = GNUNET_SCHEDULER_add_read_net (
       GNUNET_TIME_UNIT_FOREVER_REL,
       lt->listen_sock,
       &listen_cb,
       lt);
+  }
+  else
+    GNUNET_free (lt);
 }
 
 
@@ -831,6 +1055,13 @@ core_read_finished_cb (void *cls, int success)
                               "# messages lost in communicator API towards CORE",
                               1,
                               GNUNET_NO);
+  if (NULL == queue)
+    return;
+
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "backpressure %u\n",
+              queue->backpressure);
+
   queue->backpressure--;
   /* handle deferred queue destruction */
   if ((queue->destroyed) && (0 == queue->backpressure))
@@ -838,15 +1069,18 @@ core_read_finished_cb (void *cls, int success)
     GNUNET_free (queue);
     return;
   }
-  reschedule_queue_timeout (queue);
-  /* possibly unchoke reading, now that CORE made progress */
-  if (NULL == queue->read_task)
-    queue->read_task =
-      GNUNET_SCHEDULER_add_read_net (GNUNET_TIME_absolute_get_remaining (
-                                       queue->timeout),
-                                     queue->sock,
-                                     &queue_read,
-                                     queue);
+  else if (GNUNET_YES != queue->destroyed)
+  {
+    reschedule_queue_timeout (queue);
+    /* possibly unchoke reading, now that CORE made progress */
+    if (NULL == queue->read_task)
+      queue->read_task =
+        GNUNET_SCHEDULER_add_read_net (GNUNET_TIME_absolute_get_remaining (
+                                         queue->timeout),
+                                       queue->sock,
+                                       &queue_read,
+                                       queue);
+  }
 }
 
 
@@ -965,6 +1199,78 @@ setup_in_cipher (const struct GNUNET_CRYPTO_EcdhePublicKey *ephemeral,
   setup_cipher (&dh, &my_identity, &queue->in_cipher, &queue->in_hmac);
 }
 
+/**
+ * Callback called when peerstore store operation for rekey monotime value is finished.
+ * @param cls Queue context the store operation was executed.
+ * @param success Store operation was successful (GNUNET_OK) or not.
+ */
+static void
+rekey_monotime_store_cb (void *cls, int success)
+{
+  struct Queue *queue = cls;
+  if (GNUNET_OK != success)
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                "Failed to store rekey monotonic time in PEERSTORE!\n");
+  }
+  queue->rekey_monotime_sc = NULL;
+}
+
+/**
+ * Callback called by peerstore when records for GNUNET_PEERSTORE_TRANSPORT_TCP_COMMUNICATOR_REKEY
+ * where found.
+ * @param cls Queue context the store operation was executed.
+ * @param record The record found or NULL if there is no record left.
+ * @param emsg Message from peerstore.
+ */
+static void
+rekey_monotime_cb (void *cls,
+                   const struct GNUNET_PEERSTORE_Record *record,
+                   const char *emsg)
+{
+  struct Queue *queue = cls;
+  struct GNUNET_TIME_AbsoluteNBO *mtbe;
+  struct GNUNET_TIME_Absolute mt;
+  const struct GNUNET_PeerIdentity *pid;
+  struct GNUNET_TIME_AbsoluteNBO *rekey_monotonic_time;
+
+  (void) emsg;
+
+  rekey_monotonic_time = &queue->rekey_monotonic_time;
+  pid = &queue->target;
+  if (NULL == record)
+  {
+    queue->rekey_monotime_get = NULL;
+    return;
+  }
+  if (sizeof(*mtbe) != record->value_size)
+  {
+    GNUNET_break (0);
+    return;
+  }
+  mtbe = record->value;
+  mt = GNUNET_TIME_absolute_ntoh (*mtbe);
+  if (mt.abs_value_us > GNUNET_TIME_absolute_ntoh (
+        queue->rekey_monotonic_time).abs_value_us)
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                "Queue from %s dropped, rekey monotime in the past\n",
+                GNUNET_i2s (&queue->target));
+    GNUNET_break (0);
+    queue_finish (queue);
+    return;
+  }
+  queue->rekey_monotime_sc = GNUNET_PEERSTORE_store (peerstore,
+                                                     "transport_tcp_communicator",
+                                                     pid,
+                                                     GNUNET_PEERSTORE_TRANSPORT_TCP_COMMUNICATOR_REKEY,
+                                                     rekey_monotonic_time,
+                                                     sizeof(rekey_monotonic_time),
+                                                     GNUNET_TIME_UNIT_FOREVER_ABS,
+                                                     GNUNET_PEERSTORE_STOREOPTION_REPLACE,
+                                                     &rekey_monotime_store_cb,
+                                                     queue);
+}
 
 /**
  * Handle @a rekey message on @a queue. The message was already
@@ -977,14 +1283,34 @@ setup_in_cipher (const struct GNUNET_CRYPTO_EcdhePublicKey *ephemeral,
 static void
 do_rekey (struct Queue *queue, const struct TCPRekey *rekey)
 {
-  struct TcpHandshakeSignature thp;
+  struct TcpRekeySignature thp;
+
   thp.purpose.purpose = htonl (GNUNET_SIGNATURE_COMMUNICATOR_TCP_REKEY);
   thp.purpose.size = htonl (sizeof(thp));
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "do_rekey size %u\n",
+              thp.purpose.size);
   thp.sender = queue->target;
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "sender %s\n",
+              GNUNET_p2s (&thp.sender.public_key));
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "sender %s\n",
+              GNUNET_p2s (&queue->target.public_key));
   thp.receiver = my_identity;
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "receiver %s\n",
+              GNUNET_p2s (&thp.receiver.public_key));
   thp.ephemeral = rekey->ephemeral;
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "ephemeral %s\n",
+              GNUNET_e2s (&thp.ephemeral));
   thp.monotonic_time = rekey->monotonic_time;
-  /* FIXME: check monotonic time is monotonic... */
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "time %s\n",
+              GNUNET_STRINGS_absolute_time_to_string (
+                GNUNET_TIME_absolute_ntoh (thp.monotonic_time)));
+  GNUNET_assert (ntohl ((&thp)->purpose.size) == sizeof (*(&thp)));
   if (GNUNET_OK !=
       GNUNET_CRYPTO_eddsa_verify (GNUNET_SIGNATURE_COMMUNICATOR_TCP_REKEY,
                                   &thp,
@@ -995,11 +1321,93 @@ do_rekey (struct Queue *queue, const struct TCPRekey *rekey)
     queue_finish (queue);
     return;
   }
+  queue->rekey_monotonic_time = rekey->monotonic_time;
+  queue->rekey_monotime_get = GNUNET_PEERSTORE_iterate (peerstore,
+                                                        "transport_tcp_communicator",
+                                                        &queue->target,
+                                                        GNUNET_PEERSTORE_TRANSPORT_TCP_COMMUNICATOR_REKEY,
+                                                        &rekey_monotime_cb,
+                                                        queue);
   gcry_cipher_close (queue->in_cipher);
   queue->rekeyed = GNUNET_YES;
   setup_in_cipher (&rekey->ephemeral, queue);
 }
 
+/**
+ * Callback called when peerstore store operation for handshake ack monotime value is finished.
+ * @param cls Queue context the store operation was executed.
+ * @param success Store operation was successful (GNUNET_OK) or not.
+ */
+static void
+handshake_ack_monotime_store_cb (void *cls, int success)
+{
+  struct Queue *queue = cls;
+
+  if (GNUNET_OK != success)
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                "Failed to store handshake ack monotonic time in PEERSTORE!\n");
+  }
+  queue->handshake_ack_monotime_sc = NULL;
+}
+
+/**
+ * Callback called by peerstore when records for GNUNET_PEERSTORE_TRANSPORT_TCP_COMMUNICATOR_HANDSHAKE_ACK
+ * where found.
+ * @param cls Queue context the store operation was executed.
+ * @param record The record found or NULL if there is no record left.
+ * @param emsg Message from peerstore.
+ */
+static void
+handshake_ack_monotime_cb (void *cls,
+                           const struct GNUNET_PEERSTORE_Record *record,
+                           const char *emsg)
+{
+  struct Queue *queue = cls;
+  struct GNUNET_TIME_AbsoluteNBO *mtbe;
+  struct GNUNET_TIME_Absolute mt;
+  const struct GNUNET_PeerIdentity *pid;
+  struct GNUNET_TIME_AbsoluteNBO *handshake_ack_monotonic_time;
+
+  (void) emsg;
+
+  handshake_ack_monotonic_time = &queue->handshake_ack_monotonic_time;
+  pid = &queue->target;
+  if (NULL == record)
+  {
+    queue->handshake_ack_monotime_get = NULL;
+    return;
+  }
+  if (sizeof(*mtbe) != record->value_size)
+  {
+    GNUNET_break (0);
+    return;
+  }
+  mtbe = record->value;
+  mt = GNUNET_TIME_absolute_ntoh (*mtbe);
+  if (mt.abs_value_us > GNUNET_TIME_absolute_ntoh (
+        queue->handshake_ack_monotonic_time).abs_value_us)
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                "Queue from %s dropped, handshake ack monotime in the past\n",
+                GNUNET_i2s (&queue->target));
+    GNUNET_break (0);
+    queue_finish (queue);
+    return;
+  }
+  queue->handshake_ack_monotime_sc = GNUNET_PEERSTORE_store (peerstore,
+                                                             "transport_tcp_communicator",
+                                                             pid,
+                                                             GNUNET_PEERSTORE_TRANSPORT_TCP_COMMUNICATOR_HANDSHAKE_ACK,
+                                                             handshake_ack_monotonic_time,
+                                                             sizeof(
+                                                               handshake_ack_monotonic_time),
+                                                             GNUNET_TIME_UNIT_FOREVER_ABS,
+                                                             GNUNET_PEERSTORE_STOREOPTION_REPLACE,
+                                                             &
+                                                             handshake_ack_monotime_store_cb,
+                                                             queue);
+}
 
 /**
  * Test if we have received a full message in plaintext.
@@ -1013,6 +1421,8 @@ try_handle_plaintext (struct Queue *queue)
 {
   const struct GNUNET_MessageHeader *hdr =
     (const struct GNUNET_MessageHeader *) queue->pread_buf;
+  const struct TCPConfirmationAck *tca = (const struct
+                                          TCPConfirmationAck *) queue->pread_buf;
   const struct TCPBox *box = (const struct TCPBox *) queue->pread_buf;
   const struct TCPRekey *rekey = (const struct TCPRekey *) queue->pread_buf;
   const struct TCPFinish *fin = (const struct TCPFinish *) queue->pread_buf;
@@ -1021,12 +1431,92 @@ try_handle_plaintext (struct Queue *queue)
   struct GNUNET_ShortHashCode tmac;
   uint16_t type;
   size_t size = 0; /* make compiler happy */
+  struct TcpHandshakeAckSignature thas;
+  const struct ChallengeNonceP challenge = queue->challenge;
+
+  if ((sizeof(*hdr) > queue->pread_off))
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                "Handling plaintext, not even a header!\n");
+    return 0; /* not even a header */
+  }
+
+  if ((-1 != unverified_size) && (unverified_size > INITIAL_CORE_KX_SIZE))
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                "Already received data of size %lu bigger than KX size %lu!\n",
+                unverified_size,
+                INITIAL_CORE_KX_SIZE);
+    GNUNET_break_op (0);
+    queue_finish (queue);
+    return 0;
+  }
+
+  type = ntohs (hdr->type);
+  switch (type)
+  {
+  case GNUNET_MESSAGE_TYPE_COMMUNICATOR_TCP_CONFIRMATION_ACK:
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                "start processing ack\n");
+    if (sizeof(*tca) > queue->pread_off)
+    {
+      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                  "Handling plaintext size of tca greater than pread offset.\n");
+      return 0;
+    }
+    if (ntohs (hdr->size) != sizeof(*tca))
+    {
+      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                  "Handling plaintext size does not match message type.\n");
+      GNUNET_break_op (0);
+      queue_finish (queue);
+      return 0;
+    }
+
+    thas.purpose.purpose = htonl (
+      GNUNET_SIGNATURE_COMMUNICATOR_TCP_HANDSHAKE_ACK);
+    thas.purpose.size = htonl (sizeof(thas));
+    thas.sender = tca->sender;
+    thas.receiver = my_identity;
+    thas.monotonic_time = tca->monotonic_time;
+    thas.challenge = tca->challenge;
+
+    if (GNUNET_SYSERR == GNUNET_CRYPTO_eddsa_verify (
+          GNUNET_SIGNATURE_COMMUNICATOR_TCP_HANDSHAKE_ACK,
+          &thas,
+          &tca->sender_sig,
+          &tca->sender.public_key))
+    {
+      GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                  "Verification of signature failed!\n");
+      GNUNET_break (0);
+      queue_finish (queue);
+      return 0;
+    }
+    if (0 != GNUNET_memcmp (&tca->challenge, &challenge))
+    {
+      GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                  "Challenge in TCPConfirmationAck not correct!\n");
+      GNUNET_break (0);
+      queue_finish (queue);
+      return 0;
+    }
 
-  if (sizeof(*hdr) > queue->pread_off)
-    return 0; /* not even a header */
-  type = ntohs (hdr->type);
-  switch (type)
-  {
+    queue->handshake_ack_monotime_get = GNUNET_PEERSTORE_iterate (peerstore,
+                                                                  "transport_tcp_communicator",
+                                                                  &queue->target,
+                                                                  GNUNET_PEERSTORE_TRANSPORT_TCP_COMMUNICATOR_HANDSHAKE_ACK,
+                                                                  &
+                                                                  handshake_ack_monotime_cb,
+                                                                  queue);
+
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                "Handling plaintext, ack processed!");
+
+    unverified_size = -1;
+
+    size = ntohs (hdr->size);
+    break;
   case GNUNET_MESSAGE_TYPE_COMMUNICATOR_TCP_BOX:
     /* Special case: header size excludes box itself! */
     if (ntohs (hdr->size) + sizeof(struct TCPBox) > queue->pread_off)
@@ -1040,6 +1530,8 @@ try_handle_plaintext (struct Queue *queue)
     }
     pass_plaintext_to_core (queue, (const void *) &box[1], ntohs (hdr->size));
     size = ntohs (hdr->size) + sizeof(*box);
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                "Handling plaintext, box processed!\n");
     break;
 
   case GNUNET_MESSAGE_TYPE_COMMUNICATOR_TCP_REKEY:
@@ -1062,6 +1554,8 @@ try_handle_plaintext (struct Queue *queue)
     }
     do_rekey (queue, rekey);
     size = ntohs (hdr->size);
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                "Handling plaintext, rekey processed!\n");
     break;
 
   case GNUNET_MESSAGE_TYPE_COMMUNICATOR_TCP_FINISH:
@@ -1084,14 +1578,20 @@ try_handle_plaintext (struct Queue *queue)
     }
     /* handle FINISH by destroying queue */
     queue_destroy (queue);
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                "Handling plaintext, finish processed!\n");
     break;
 
   default:
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                "Handling plaintext, nothing processed!\n");
     GNUNET_break_op (0);
     queue_finish (queue);
     return 0;
   }
   GNUNET_assert (0 != size);
+  if (-1 != unverified_size)
+    unverified_size += size;
   return size;
 }
 
@@ -1216,20 +1716,15 @@ tcp_address_to_sockaddr_numeric_v6 (socklen_t *sock_len, struct sockaddr_in6 v6,
 {
   struct sockaddr *in;
 
-  GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-              "1 address %s\n",
-              GNUNET_a2s (in, *sock_len));
-
   v6.sin6_family = AF_INET6;
   v6.sin6_port = htons ((uint16_t) port);
 #if HAVE_SOCKADDR_IN_SIN_LEN
   v6.sin6_len = sizeof(sizeof(struct sockaddr_in6));
 #endif
+  v6.sin6_flowinfo = 0;
+  v6.sin6_scope_id = 0;
   in = GNUNET_memdup (&v6, sizeof(v6));
   *sock_len = sizeof(struct sockaddr_in6);
-  GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-              "address %s\n",
-              GNUNET_a2s (in, *sock_len));
 
   return in;
 }
@@ -1292,7 +1787,7 @@ tcp_address_to_sockaddr_port_only (const char *bindto, unsigned int *port)
     i4 = GNUNET_malloc (sizeof(struct sockaddr_in));
     po->addr_ipv4 = tcp_address_to_sockaddr_numeric_v4 (&sock_len_ipv4, *i4,
                                                         *port);
-    po->addr_len_ipv4 = &sock_len_ipv4;
+    po->addr_len_ipv4 = sock_len_ipv4;
   }
   else
   {
@@ -1300,21 +1795,19 @@ tcp_address_to_sockaddr_port_only (const char *bindto, unsigned int *port)
     i4 = GNUNET_malloc (sizeof(struct sockaddr_in));
     po->addr_ipv4 = tcp_address_to_sockaddr_numeric_v4 (&sock_len_ipv4, *i4,
                                                         *port);
-    po->addr_len_ipv4 = &sock_len_ipv4;
-
-    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                "3.5 address %s\n",
-                GNUNET_a2s (po->addr_ipv4, sock_len_ipv4));
+    po->addr_len_ipv4 = sock_len_ipv4;
 
     i6 = GNUNET_malloc (sizeof(struct sockaddr_in6));
     po->addr_ipv6 = tcp_address_to_sockaddr_numeric_v6 (&sock_len_ipv6, *i6,
                                                         *port);
-    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                "3 address %s\n",
-                GNUNET_a2s (po->addr_ipv6, sock_len_ipv6));
 
-    po->addr_len_ipv6 = &sock_len_ipv6;
+    po->addr_len_ipv6 = sock_len_ipv6;
+
+    GNUNET_free (i6);
   }
+
+  GNUNET_free (i4);
+
   return po;
 }
 
@@ -1333,11 +1826,19 @@ extract_address (const char *bindto)
   char *cp;
   char *rest = NULL;
 
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "extract address with bindto %s\n",
+              bindto);
+
   if (NULL == bindto)
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
                 "bindto is NULL\n");
 
   cp = GNUNET_strdup (bindto);
+
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "extract address 2\n");
+
   start = cp;
   if (('[' == *cp) && (']' == cp[strlen (cp) - 1]))
   {
@@ -1357,7 +1858,11 @@ extract_address (const char *bindto)
     }
   }
 
-  // GNUNET_free(cp);
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "extract address 3\n");
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "extract address with start %s\n",
+              start);
 
   return start;
 }
@@ -1459,10 +1964,25 @@ tcp_address_to_sockaddr (const char *bindto, socklen_t *sock_len)
   // cp = GNUNET_strdup (bindto);
   start = extract_address (bindto);
 
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "start %s\n",
+              start);
+
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "!bindto %s\n",
+              bindto);
+
+
+
   if (1 == inet_pton (AF_INET, start, &v4.sin_addr))
   {
     // colon = strrchr (cp, ':');
     port = extract_port (bindto);
+
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                "port %u\n",
+                port);
+
     in = tcp_address_to_sockaddr_numeric_v4 (sock_len, v4, port);
   }
   else if (1 == inet_pton (AF_INET6, start, &v6.sin6_addr))
@@ -1471,6 +1991,11 @@ tcp_address_to_sockaddr (const char *bindto, socklen_t *sock_len)
     port = extract_port (bindto);
     in = tcp_address_to_sockaddr_numeric_v6 (sock_len, v6, port);
   }
+  else{
+    GNUNET_assert (0);
+  }
+
+  // GNUNET_free (start);
 
   return in;
 }
@@ -1507,7 +2032,7 @@ static void
 inject_rekey (struct Queue *queue)
 {
   struct TCPRekey rekey;
-  struct TcpHandshakeSignature thp;
+  struct TcpRekeySignature thp;
 
   GNUNET_assert (0 == queue->pwrite_off);
   memset (&rekey, 0, sizeof(rekey));
@@ -1519,10 +2044,26 @@ inject_rekey (struct Queue *queue)
     GNUNET_TIME_absolute_hton (GNUNET_TIME_absolute_get_monotonic (cfg));
   thp.purpose.purpose = htonl (GNUNET_SIGNATURE_COMMUNICATOR_TCP_REKEY);
   thp.purpose.size = htonl (sizeof(thp));
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "inject_rekey size %u\n",
+              thp.purpose.size);
   thp.sender = my_identity;
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "sender %s\n",
+              GNUNET_p2s (&thp.sender.public_key));
   thp.receiver = queue->target;
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "receiver %s\n",
+              GNUNET_p2s (&thp.receiver.public_key));
   thp.ephemeral = rekey.ephemeral;
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "ephemeral %s\n",
+              GNUNET_e2s (&thp.ephemeral));
   thp.monotonic_time = rekey.monotonic_time;
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "time %s\n",
+              GNUNET_STRINGS_absolute_time_to_string (
+                GNUNET_TIME_absolute_ntoh (thp.monotonic_time)));
   GNUNET_CRYPTO_eddsa_sign (my_private_key,
                             &thp,
                             &rekey.sender_sig);
@@ -1598,10 +2139,11 @@ queue_write (void *cls)
     queue->cwrite_off += queue->pwrite_off;
     queue->pwrite_off = 0;
   }
-  if ((0 == queue->pwrite_off) &&
-      ((0 == queue->rekey_left_bytes) ||
-       (0 ==
-        GNUNET_TIME_absolute_get_remaining (queue->rekey_time).rel_value_us)))
+  if ((-1 != unverified_size)&& ((0 == queue->pwrite_off) &&
+                                 ((0 == queue->rekey_left_bytes) ||
+                                  (0 ==
+                                   GNUNET_TIME_absolute_get_remaining (
+                                     queue->rekey_time).rel_value_us))))
   {
     inject_rekey (queue);
   }
@@ -1821,12 +2363,16 @@ transmit_kx (struct Queue *queue,
   tc.sender = my_identity;
   tc.monotonic_time =
     GNUNET_TIME_absolute_hton (GNUNET_TIME_absolute_get_monotonic (cfg));
+  GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_NONCE,
+                              &tc.challenge,
+                              sizeof(tc.challenge));
   ths.purpose.purpose = htonl (GNUNET_SIGNATURE_COMMUNICATOR_TCP_HANDSHAKE);
   ths.purpose.size = htonl (sizeof(ths));
   ths.sender = my_identity;
   ths.receiver = queue->target;
   ths.ephemeral = *epub;
   ths.monotonic_time = tc.monotonic_time;
+  ths.challenge = tc.challenge;
   GNUNET_CRYPTO_eddsa_sign (my_private_key,
                             &ths,
                             &tc.sender_sig);
@@ -1836,7 +2382,12 @@ transmit_kx (struct Queue *queue,
                                       sizeof(tc),
                                       &tc,
                                       sizeof(tc)));
+  queue->challenge = tc.challenge;
   queue->cwrite_off += sizeof(tc);
+
+  GNUNET_log_from_nocheck (GNUNET_ERROR_TYPE_DEBUG,
+                           "transport",
+                           "handshake written\n");
 }
 
 
@@ -1858,6 +2409,80 @@ start_initial_kx_out (struct Queue *queue)
   transmit_kx (queue, &epub);
 }
 
+/**
+ * Callback called when peerstore store operation for handshake monotime is finished.
+ * @param cls Queue context the store operation was executed.
+ * @param success Store operation was successful (GNUNET_OK) or not.
+ */
+static void
+handshake_monotime_store_cb (void *cls, int success)
+{
+  struct Queue *queue = cls;
+  if (GNUNET_OK != success)
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                "Failed to store handshake monotonic time in PEERSTORE!\n");
+  }
+  queue->handshake_monotime_sc = NULL;
+}
+
+/**
+ * Callback called by peerstore when records for GNUNET_PEERSTORE_TRANSPORT_TCP_COMMUNICATOR_HANDSHAKE
+ * where found.
+ * @param cls Queue context the store operation was executed.
+ * @param record The record found or NULL if there is no record left.
+ * @param emsg Message from peerstore.
+ */
+static void
+handshake_monotime_cb (void *cls,
+                       const struct GNUNET_PEERSTORE_Record *record,
+                       const char *emsg)
+{
+  struct Queue *queue = cls;
+  struct GNUNET_TIME_AbsoluteNBO *mtbe;
+  struct GNUNET_TIME_Absolute mt;
+  const struct GNUNET_PeerIdentity *pid;
+  struct GNUNET_TIME_AbsoluteNBO *handshake_monotonic_time;
+
+  (void) emsg;
+
+  handshake_monotonic_time = &queue->handshake_monotonic_time;
+  pid = &queue->target;
+  if (NULL == record)
+  {
+    queue->handshake_monotime_get = NULL;
+    return;
+  }
+  if (sizeof(*mtbe) != record->value_size)
+  {
+    GNUNET_break (0);
+    return;
+  }
+  mtbe = record->value;
+  mt = GNUNET_TIME_absolute_ntoh (*mtbe);
+  if (mt.abs_value_us > GNUNET_TIME_absolute_ntoh (
+        queue->handshake_monotonic_time).abs_value_us)
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                "Queue from %s dropped, handshake monotime in the past\n",
+                GNUNET_i2s (&queue->target));
+    GNUNET_break (0);
+    queue_finish (queue);
+    return;
+  }
+  queue->handshake_monotime_sc = GNUNET_PEERSTORE_store (peerstore,
+                                                         "transport_tcp_communicator",
+                                                         pid,
+                                                         GNUNET_PEERSTORE_TRANSPORT_TCP_COMMUNICATOR_HANDSHAKE,
+                                                         handshake_monotonic_time,
+                                                         sizeof(
+                                                           handshake_monotonic_time),
+                                                         GNUNET_TIME_UNIT_FOREVER_ABS,
+                                                         GNUNET_PEERSTORE_STOREOPTION_REPLACE,
+                                                         &
+                                                         handshake_monotime_store_cb,
+                                                         queue);
+}
 
 /**
  * We have received the first bytes from the other side on a @a queue.
@@ -1890,13 +2515,19 @@ decrypt_and_check_tc (struct Queue *queue,
   ths.receiver = my_identity;
   memcpy (&ths.ephemeral, ibuf, sizeof(struct GNUNET_CRYPTO_EcdhePublicKey));
   ths.monotonic_time = tc->monotonic_time;
-  /* FIXME: check monotonic time against previous mono times
-     from this sender! */
+  ths.challenge = tc->challenge;
   return GNUNET_CRYPTO_eddsa_verify (
     GNUNET_SIGNATURE_COMMUNICATOR_TCP_HANDSHAKE,
     &ths,
     &tc->sender_sig,
     &tc->sender.public_key);
+  queue->handshake_monotime_get = GNUNET_PEERSTORE_iterate (peerstore,
+                                                            "transport_tcp_communicator",
+                                                            &queue->target,
+                                                            GNUNET_PEERSTORE_TRANSPORT_TCP_COMMUNICATOR_HANDSHAKE,
+                                                            &
+                                                            handshake_monotime_cb,
+                                                            queue);
 }
 
 
@@ -1908,11 +2539,6 @@ decrypt_and_check_tc (struct Queue *queue,
 static void
 free_proto_queue (struct ProtoQueue *pq)
 {
-  if (NULL != pq->listen_task)
-  {
-    GNUNET_SCHEDULER_cancel (pq->listen_task);
-    pq->listen_task = NULL;
-  }
   if (NULL != pq->listen_sock)
   {
     GNUNET_break (GNUNET_OK == GNUNET_NETWORK_socket_close (pq->listen_sock));
@@ -1924,6 +2550,47 @@ free_proto_queue (struct ProtoQueue *pq)
   GNUNET_free (pq);
 }
 
+/**
+ * Sending challenge with TcpConfirmationAck back to sender of ephemeral key.
+ *
+ * @param tc The TCPConfirmation originally send.
+ * @param queue The queue context.
+ */
+static void
+send_challenge (struct TCPConfirmation tc, struct Queue *queue)
+{
+  struct TCPConfirmationAck tca;
+  struct TcpHandshakeAckSignature thas;
+
+  GNUNET_log_from_nocheck (GNUNET_ERROR_TYPE_DEBUG,
+                           "transport",
+                           "sending challenge\n");
+
+  tca.header.type = ntohs (
+    GNUNET_MESSAGE_TYPE_COMMUNICATOR_TCP_CONFIRMATION_ACK);
+  tca.header.size = ntohs (sizeof(tca));
+  tca.challenge = tc.challenge;
+  tca.sender = my_identity;
+  tca.monotonic_time =
+    GNUNET_TIME_absolute_hton (GNUNET_TIME_absolute_get_monotonic (cfg));
+  thas.purpose.purpose = htonl (
+    GNUNET_SIGNATURE_COMMUNICATOR_TCP_HANDSHAKE_ACK);
+  thas.purpose.size = htonl (sizeof(thas));
+  thas.sender = my_identity;
+  thas.receiver = queue->target;
+  thas.monotonic_time = tca.monotonic_time;
+  thas.challenge = tca.challenge;
+  GNUNET_CRYPTO_eddsa_sign (my_private_key,
+                            &thas,
+                            &tca.sender_sig);
+  GNUNET_assert (0 ==
+                 gcry_cipher_encrypt (queue->out_cipher,
+                                      &queue->cwrite_buf[queue->cwrite_off],
+                                      sizeof(tca),
+                                      &tca,
+                                      sizeof(tca)));
+  queue->cwrite_off += sizeof(tca);
+}
 
 /**
  * Read from the socket of the proto queue until we have enough data
@@ -1990,9 +2657,13 @@ proto_read_kx (void *cls)
   queue->address = pq->address; /* steals reference */
   queue->address_len = pq->address_len;
   queue->target = tc.sender;
-  queue->listen_task = pq->listen_task;
   queue->listen_sock = pq->listen_sock;
   queue->sock = pq->sock;
+
+
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "start kx proto\n");
+
   start_initial_kx_out (queue);
   boot_queue (queue, GNUNET_TRANSPORT_CS_INBOUND);
   queue->read_task =
@@ -2005,6 +2676,8 @@ proto_read_kx (void *cls)
                                     queue->sock,
                                     &queue_write,
                                     queue);
+  send_challenge (tc, queue);
+
   GNUNET_CONTAINER_DLL_remove (proto_head, proto_tail, pq);
   GNUNET_free (pq);
 }
@@ -2026,6 +2699,9 @@ listen_cb (void *cls)
   struct ProtoQueue *pq;
   struct ListenTask *lt;
 
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "listen_cb\n");
+
   lt = cls;
 
   lt->listen_task = NULL;
@@ -2128,7 +2804,7 @@ queue_read_kx (void *cls)
     queue_destroy (queue);
     return;
   }
-
+  send_challenge (tc, queue);
   /* update queue timeout */
   reschedule_queue_timeout (queue);
   /* prepare to continue with regular read task immediately */
@@ -2164,7 +2840,7 @@ mq_init (void *cls, const struct GNUNET_PeerIdentity *peer, const char *address)
   struct Queue *queue;
   const char *path;
   struct sockaddr *in;
-  socklen_t in_len;
+  socklen_t in_len = 0;
   struct GNUNET_NETWORK_Handle *sock;
 
   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
@@ -2186,6 +2862,10 @@ mq_init (void *cls, const struct GNUNET_PeerIdentity *peer, const char *address)
     return GNUNET_SYSERR;
   }
 
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "in %s\n",
+              GNUNET_a2s (in, in_len));
+
   sock = GNUNET_NETWORK_socket_create (in->sa_family, SOCK_STREAM, IPPROTO_TCP);
   if (NULL == sock)
   {
@@ -2220,6 +2900,11 @@ mq_init (void *cls, const struct GNUNET_PeerIdentity *peer, const char *address)
                                    queue->sock,
                                    &queue_read_kx,
                                    queue);
+
+
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "start kx mq_init\n");
+
   start_initial_kx_out (queue);
   queue->write_task =
     GNUNET_SCHEDULER_add_write_net (GNUNET_TIME_UNIT_FOREVER_REL,
@@ -2229,6 +2914,36 @@ mq_init (void *cls, const struct GNUNET_PeerIdentity *peer, const char *address)
   return GNUNET_OK;
 }
 
+/**
+ * Iterator over all ListenTasks to clean up.
+ *
+ * @param cls NULL
+ * @param key unused
+ * @param value the ListenTask to cancel.
+ * @return #GNUNET_OK to continue to iterate
+ */
+static int
+get_lt_delete_it (void *cls,
+                  const struct GNUNET_HashCode *key,
+                  void *value)
+{
+  struct ListenTask *lt = value;
+
+  (void) cls;
+  (void) key;
+  if (NULL != lt->listen_task)
+  {
+    GNUNET_SCHEDULER_cancel (lt->listen_task);
+    lt->listen_task = NULL;
+  }
+  if (NULL != lt->listen_sock)
+  {
+    GNUNET_break (GNUNET_OK == GNUNET_NETWORK_socket_close (lt->listen_sock));
+    lt->listen_sock = NULL;
+  }
+  return GNUNET_OK;
+}
+
 /**
  * Iterator over all message queues to clean up.
  *
@@ -2250,7 +2965,6 @@ get_queue_delete_it (void *cls,
   return GNUNET_OK;
 }
 
-
 /**
  * Shutdown the UNIX communicator.
  *
@@ -2259,6 +2973,15 @@ get_queue_delete_it (void *cls,
 static void
 do_shutdown (void *cls)
 {
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "Shutdown %s!\n",
+              shutdown_running ? "running" : "not running");
+
+  if (GNUNET_YES == shutdown_running)
+    return;
+  else
+    shutdown_running = GNUNET_YES;
+
   while (NULL != proto_head)
     free_proto_queue (proto_head);
   if (NULL != nat)
@@ -2266,8 +2989,10 @@ do_shutdown (void *cls)
     GNUNET_NAT_unregister (nat);
     nat = NULL;
   }
+  GNUNET_CONTAINER_multihashmap_iterate (lt_map, &get_lt_delete_it, NULL);
   GNUNET_CONTAINER_multipeermap_iterate (queue_map, &get_queue_delete_it, NULL);
   GNUNET_CONTAINER_multipeermap_destroy (queue_map);
+  GNUNET_TRANSPORT_communicator_address_remove_all (ch);
   if (NULL != ch)
   {
     GNUNET_TRANSPORT_communicator_disconnect (ch);
@@ -2288,6 +3013,18 @@ do_shutdown (void *cls)
     GNUNET_NT_scanner_done (is);
     is = NULL;
   }
+  if (NULL != peerstore)
+  {
+    GNUNET_PEERSTORE_disconnect (peerstore, GNUNET_NO);
+    peerstore = NULL;
+  }
+  if (NULL != resolve_request_handle)
+  {
+    GNUNET_RESOLVER_request_cancel (resolve_request_handle);
+    resolve_request_handle = NULL;
+  }
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "Shutdown done!\n");
 }
 
 
@@ -2338,8 +3075,9 @@ nat_address_cb (void *cls,
   char *my_addr;
   struct GNUNET_TRANSPORT_AddressIdentifier *ai;
 
-  GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-              "1 nat_address %s\n",
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "nat address cb %s %s\n",
+              add_remove ? "add" : "remove",
               GNUNET_a2s (addr, addrlen));
 
   if (GNUNET_YES == add_remove)
@@ -2367,6 +3105,35 @@ nat_address_cb (void *cls,
   }
 }
 
+/**
+ * This method adds addresses to the DLL, that are later register at the NAT service.
+ */
+static void
+add_addr (struct sockaddr *in, socklen_t in_len)
+{
+
+  struct Addresses *saddrs;
+
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "add address %s\n",
+              GNUNET_a2s (in, in_len));
+
+  saddrs = GNUNET_new (struct Addresses);
+  saddrs->addr = in;
+  saddrs->addr_len = in_len;
+  GNUNET_CONTAINER_DLL_insert (addrs_head, addrs_tail, saddrs);
+
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "after add address %s\n",
+              GNUNET_a2s (in, in_len));
+
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "add address %s\n",
+              GNUNET_a2s (saddrs->addr, saddrs->addr_len));
+
+  addrs_lens++;
+}
+
 /**
  * This method launch network interactions for each address we like to bind to.
  *
@@ -2375,13 +3142,14 @@ nat_address_cb (void *cls,
  * @return GNUNET_SYSERR in case of error. GNUNET_OK in case we are successfully listen to the address.
  */
 static int
-init_socket (const struct sockaddr *addr,
+init_socket (struct sockaddr *addr,
              socklen_t in_len)
 {
   struct sockaddr_storage in_sto;
   socklen_t sto_len;
   struct GNUNET_NETWORK_Handle *listen_sock;
   struct ListenTask *lt;
+  struct GNUNET_HashCode h_sock;
 
   if (NULL == addr)
   {
@@ -2390,10 +3158,6 @@ init_socket (const struct sockaddr *addr,
     return GNUNET_SYSERR;
   }
 
-  GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-              "4 address %s\n",
-              GNUNET_a2s (addr, in_len));
-
   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
               "address %s\n",
               GNUNET_a2s (addr, in_len));
@@ -2437,13 +3201,12 @@ init_socket (const struct sockaddr *addr,
     sto_len = in_len;
   }
 
-  addr = (struct sockaddr *) &in_sto;
+  // addr = (struct sockaddr *) &in_sto;
   in_len = sto_len;
   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
               "Bound to `%s'\n",
               GNUNET_a2s ((const struct sockaddr *) &in_sto, sto_len));
   stats = GNUNET_STATISTICS_create ("C-TCP", cfg);
-  GNUNET_SCHEDULER_add_shutdown (&do_shutdown, NULL);
 
   if (NULL == is)
     is = GNUNET_NT_scanner_init ();
@@ -2456,7 +3219,8 @@ init_socket (const struct sockaddr *addr,
       GNUNET_ERROR_TYPE_ERROR,
       _ (
         "Transport service is lacking key configuration settings. Exiting.\n"));
-    GNUNET_RESOLVER_request_cancel (resolve_request_handle);
+    if (NULL != resolve_request_handle)
+      GNUNET_RESOLVER_request_cancel (resolve_request_handle);
     GNUNET_SCHEDULER_shutdown ();
     return GNUNET_SYSERR;
   }
@@ -2471,6 +3235,27 @@ init_socket (const struct sockaddr *addr,
                                                    &listen_cb,
                                                    lt);
 
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "creating hash\n");
+  GNUNET_CRYPTO_hash (lt->listen_sock,
+                      sizeof(lt->listen_sock),
+                      &h_sock);
+
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "creating map\n");
+  if (NULL == lt_map)
+    lt_map = GNUNET_CONTAINER_multihashmap_create (2, GNUNET_NO);
+
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "creating map entry\n");
+  GNUNET_CONTAINER_multihashmap_put (lt_map,
+                                     &h_sock,
+                                     lt,
+                                     GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY);
+
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "map entry created\n");
+
   if (NULL == queue_map)
     queue_map = GNUNET_CONTAINER_multipeermap_create (10, GNUNET_NO);
 
@@ -2487,11 +3272,13 @@ init_socket (const struct sockaddr *addr,
   if (NULL == ch)
   {
     GNUNET_break (0);
-    GNUNET_RESOLVER_request_cancel (resolve_request_handle);
+    if (NULL != resolve_request_handle)
+      GNUNET_RESOLVER_request_cancel (resolve_request_handle);
     GNUNET_SCHEDULER_shutdown ();
     return GNUNET_SYSERR;
   }
 
+  add_addr (addr, in_len);
   return GNUNET_OK;
 
 }
@@ -2508,35 +3295,27 @@ nat_register ()
   int i;
   struct Addresses *pos;
 
-  GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-              "nat here\n");
+
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "starting nat register!\n");
 
   i = 0;
   saddrs = GNUNET_malloc ((addrs_lens + 1) * sizeof(struct sockaddr *));
 
-  GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-              "2 nat here\n");
-
   saddr_lens = GNUNET_malloc ((addrs_lens + 1) * sizeof(socklen_t));
 
-  GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-              "3 nat here\n");
-
   for (pos = addrs_head; NULL != pos; pos = pos->next)
   {
 
-    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                "5 nat here\n");
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                "registering address %s\n",
+                GNUNET_a2s (addrs_head->addr, addrs_head->addr_len));
 
     saddr_lens[i] = addrs_head->addr_len;
-    saddrs[i] = GNUNET_malloc (saddr_lens[i]);
-    saddrs[i] = addrs_head->addr;
+    saddrs[i] = GNUNET_memdup (addrs_head->addr, saddr_lens[i]);
 
     i++;
 
-    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                "6 nat here\n");
-
   }
 
   nat = GNUNET_NAT_register (cfg,
@@ -2549,30 +3328,22 @@ nat_register ()
                              NULL /* FIXME: support reversal: #5529 */,
                              NULL /* closure */);
 
+  i = 0;
+
+  for (i = addrs_lens - 1; i >= 0; i--)
+    GNUNET_free (saddrs[i]);
+  GNUNET_free (saddrs);
+  GNUNET_free (saddr_lens);
+
   if (NULL == nat)
   {
     GNUNET_break (0);
-    GNUNET_RESOLVER_request_cancel (resolve_request_handle);
+    if (NULL != resolve_request_handle)
+      GNUNET_RESOLVER_request_cancel (resolve_request_handle);
     GNUNET_SCHEDULER_shutdown ();
   }
 }
 
-/**
- * This method adds addresses to the DLL, that are later register at the NAT service.
- */
-static void
-add_addr (struct sockaddr *in, socklen_t in_len)
-{
-
-  struct Addresses *saddrs;
-
-  saddrs = GNUNET_new (struct Addresses);
-  saddrs->addr = in;
-  saddrs->addr_len = in_len;
-  GNUNET_CONTAINER_DLL_insert (addrs_head, addrs_tail, saddrs);
-  addrs_lens++;
-}
-
 /**
  * This method is the callback called by the resolver API, and wraps method init_socket.
  *
@@ -2588,22 +3359,19 @@ init_socket_resolv (void *cls,
   struct sockaddr_in *v4;
   struct sockaddr_in6 *v6;
   struct sockaddr *in;
-  unsigned int *port;
 
-  port = cls;
+  (void) cls;
   if (NULL  != addr)
   {
     if (AF_INET == addr->sa_family)
     {
       v4 = (struct sockaddr_in *) addr;
-      in = tcp_address_to_sockaddr_numeric_v4 (&in_len, *v4, *port);// _global);
-      add_addr (in, in_len);
+      in = tcp_address_to_sockaddr_numeric_v4 (&in_len, *v4, bind_port);// _global);
     }
     else if (AF_INET6 == addr->sa_family)
     {
       v6 = (struct sockaddr_in6 *) addr;
-      in = tcp_address_to_sockaddr_numeric_v6 (&in_len, *v6, *port);// _global);
-      add_addr (in, in_len);
+      in = tcp_address_to_sockaddr_numeric_v6 (&in_len, *v6, bind_port);// _global);
     }
     else
     {
@@ -2614,14 +3382,20 @@ init_socket_resolv (void *cls,
                   AF_INET6);
       return;
     }
-    init_socket (in,
-                 in_len);
+    init_socket (in, in_len);
   }
   else
   {
     GNUNET_log (GNUNET_ERROR_TYPE_INFO,
                 "Address is NULL. This might be an error or the resolver finished resolving.\n");
+    if (NULL == addrs_head)
+    {
+      GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+                  "Resolver finished resolving, but we do not listen to an address!.\n");
+      return;
+    }
     nat_register ();
+
   }
 }
 
@@ -2649,6 +3423,8 @@ run (void *cls,
   char dummy[2];
   char *rest = NULL;
   struct PortOnlyIpv4Ipv6 *po;
+  socklen_t addr_len_ipv4;
+  socklen_t addr_len_ipv6;
 
   (void) cls;
   cfg = c;
@@ -2676,56 +3452,79 @@ run (void *cls,
                                            &rekey_interval))
     rekey_interval = DEFAULT_REKEY_INTERVAL;
 
+  peerstore = GNUNET_PEERSTORE_connect (cfg);
+  if (NULL == peerstore)
+  {
+    GNUNET_break (0);
+    GNUNET_SCHEDULER_shutdown ();
+    return;
+  }
 
-  // cp = GNUNET_strdup (bindto);
-  start = extract_address (bindto);
+  GNUNET_SCHEDULER_add_shutdown (&do_shutdown, NULL);
 
-  if (1 == sscanf (bindto, "%u%1s", &port, dummy))
+  if (1 == sscanf (bindto, "%u%1s", &bind_port, dummy))
   {
-    po = tcp_address_to_sockaddr_port_only (bindto, &port);
+    po = tcp_address_to_sockaddr_port_only (bindto, &bind_port);
 
-    if (NULL != &po->addr_ipv4)
+    addr_len_ipv4 = po->addr_len_ipv4;
+
+
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                "address po %s\n",
+                GNUNET_a2s (po->addr_ipv4, addr_len_ipv4));
+
+    if (NULL != po->addr_ipv4)
     {
-      init_socket (po->addr_ipv4, *po->addr_len_ipv4);
-      add_addr (po->addr_ipv4, *po->addr_len_ipv4);
+      init_socket (po->addr_ipv4, addr_len_ipv4);
     }
 
-    if (NULL != &po->addr_ipv6)
+    if (NULL != po->addr_ipv6)
     {
-      init_socket (po->addr_ipv6, *po->addr_len_ipv6);
-      add_addr (po->addr_ipv6, *po->addr_len_ipv6);
+      addr_len_ipv6 = po->addr_len_ipv6;
+      init_socket (po->addr_ipv6, addr_len_ipv6);
     }
 
+    GNUNET_free (po);
     nat_register ();
+    GNUNET_free (bindto);
+
+    return;
   }
-  else if (1 == inet_pton (AF_INET, start, &v4.sin_addr))
+
+  start = extract_address (bindto);
+
+  if (1 == inet_pton (AF_INET, start, &v4.sin_addr))
   {
-    port = extract_port (bindto);
+    bind_port = extract_port (bindto);
 
-    in = tcp_address_to_sockaddr_numeric_v4 (&in_len, v4, port);
+    in = tcp_address_to_sockaddr_numeric_v4 (&in_len, v4, bind_port);
     init_socket (in, in_len);
-    add_addr (in, in_len);
     nat_register ();
+    GNUNET_free (bindto);
+
+    return;
   }
-  else if (1 == inet_pton (AF_INET6, start, &v6.sin6_addr))
+
+  if (1 == inet_pton (AF_INET6, start, &v6.sin6_addr))
   {
-    port = extract_port (bindto);
-    in = tcp_address_to_sockaddr_numeric_v6 (&in_len, v6, port);
+    bind_port = extract_port (bindto);
+    in = tcp_address_to_sockaddr_numeric_v6 (&in_len, v6, bind_port);
     init_socket (in, in_len);
-    add_addr (in, in_len);
     nat_register ();
-  }
-  else
-  {
-    port = extract_port (bindto);
+    GNUNET_free (bindto);
 
-    resolve_request_handle = GNUNET_RESOLVER_ip_get (strtok_r (bindto, ":",
-                                                               &rest),
-                                                     AF_UNSPEC,
-                                                     GNUNET_TIME_UNIT_MINUTES,
-                                                     &init_socket_resolv,
-                                                     &port);
+    return;
   }
+
+
+  bind_port = extract_port (bindto);
+
+  resolve_request_handle = GNUNET_RESOLVER_ip_get (strtok_r (bindto, ":",
+                                                             &rest),
+                                                   AF_UNSPEC,
+                                                   GNUNET_TIME_UNIT_MINUTES,
+                                                   &init_socket_resolv,
+                                                   &port);
   GNUNET_free (bindto);
 }
 
diff --git a/src/transport/gnunet-communicator-udp.c b/src/transport/gnunet-communicator-udp.c
index efbbd08a73d5d367f61ecd431939810c2096717d..03c120cc9366af4a0575220a8f1971f3bf8ca15b 100644
--- a/src/transport/gnunet-communicator-udp.c
+++ b/src/transport/gnunet-communicator-udp.c
@@ -1309,7 +1309,8 @@ handle_ack (void *cls, const struct GNUNET_PeerIdentity *pid, void *value)
                     "Tell transport we have more acks!\n");
         GNUNET_TRANSPORT_communicator_mq_update (ch,
                                                  receiver->d_qh,
-                                                 (allowed - ss->sequence_allowed),
+                                                 (allowed
+                                                  - ss->sequence_allowed),
                                                  1);
         ss->sequence_allowed = allowed;
         /* move ss to head to avoid discarding it anytime soon! */
diff --git a/src/transport/gnunet-communicator-unix.c b/src/transport/gnunet-communicator-unix.c
index 6ea0ea360acf333b1ff4eedbfe99932591273ff1..d7e18f87a53ef63fa4ed7390e665e3cc15fa0fa5 100644
--- a/src/transport/gnunet-communicator-unix.c
+++ b/src/transport/gnunet-communicator-unix.c
@@ -673,7 +673,8 @@ setup_queue (const struct GNUNET_PeerIdentity *target,
     queue->qh = GNUNET_TRANSPORT_communicator_mq_add (ch,
                                                       &queue->target,
                                                       foreign_addr,
-                                                      UNIX_MTU - sizeof (struct UNIXMessage),
+                                                      UNIX_MTU - sizeof (struct
+                                                                         UNIXMessage),
                                                       GNUNET_TRANSPORT_QUEUE_LENGTH_UNLIMITED,
                                                       0,
                                                       GNUNET_NT_LOOPBACK,
@@ -799,7 +800,7 @@ select_read_cb (void *cls)
     /* ensure aligned access */
     memcpy (&al_hdr, currhdr, sizeof(al_hdr));
     if ((tsize < sizeof(struct GNUNET_MessageHeader)) ||
-        (tsize != ntohs(al_hdr.size)))
+        (tsize != ntohs (al_hdr.size)))
     {
       GNUNET_break_op (0);
       return;
diff --git a/src/transport/gnunet-service-tng.c b/src/transport/gnunet-service-tng.c
index 5f3178939c6ed275c5f2c9122a8dfbb87a91365f..2f6e17f3b58ed5ce11f5e590fb8c6110652dbc03 100644
--- a/src/transport/gnunet-service-tng.c
+++ b/src/transport/gnunet-service-tng.c
@@ -329,19 +329,6 @@ struct AcknowledgementUUIDP
   struct GNUNET_Uuid value;
 };
 
-
-/**
- * Type of a nonce used for challenges.
- */
-struct ChallengeNonceP
-{
-  /**
-   * The value of the nonce.  Note that this is NOT a hash.
-   */
-  struct GNUNET_ShortHashCode value;
-};
-
-
 /**
  * Outer layer of an encapsulated backchannel message.
  */
@@ -3222,7 +3209,7 @@ notify_monitors (const struct GNUNET_PeerIdentity *peer,
       continue;
     if (tc->details.monitor.one_shot)
       continue;
-    if ((0 != GNUNET_is_zero (&tc->details.monitor.peer)) &&
+    if ((GNUNET_NO == GNUNET_is_zero (&tc->details.monitor.peer)) &&
         (0 != GNUNET_memcmp (&tc->details.monitor.peer, peer)))
       continue;
     notify_monitor (tc, peer, address, nt, me);
diff --git a/src/transport/ieee80211_radiotap.h b/src/transport/ieee80211_radiotap.h
new file mode 100644
index 0000000000000000000000000000000000000000..1a79cf214d813d4f6b91df41acc1dc360a624809
--- /dev/null
+++ b/src/transport/ieee80211_radiotap.h
@@ -0,0 +1,276 @@
+/*
+ * Copyright (c) 2003, 2004 David Young.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. The name of David Young may not be used to endorse or promote
+ *    products derived from this software without specific prior
+ *    written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY DAVID YOUNG ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ * PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL DAVID
+ * YOUNG BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+ * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
+ * OF SUCH DAMAGE.
+ */
+
+/*
+ * Modifications to fit into the linux IEEE 802.11 stack,
+ * Mike Kershaw (dragorn@kismetwireless.net)
+ */
+
+#ifndef IEEE80211RADIOTAP_H
+#define IEEE80211RADIOTAP_H
+
+#include <linux/if_ether.h>
+#include <linux/kernel.h>
+// #include <asm/unaligned.h>
+
+/* Base version of the radiotap packet header data */
+#define PKTHDR_RADIOTAP_VERSION         0
+
+/* A generic radio capture format is desirable. There is one for
+ * Linux, but it is neither rigidly defined (there were not even
+ * units given for some fields) nor easily extensible.
+ *
+ * I suggest the following extensible radio capture format. It is
+ * based on a bitmap indicating which fields are present.
+ *
+ * I am trying to describe precisely what the application programmer
+ * should expect in the following, and for that reason I tell the
+ * units and origin of each measurement (where it applies), or else I
+ * use sufficiently weaselly language ("is a monotonically nondecreasing
+ * function of...") that I cannot set false expectations for lawyerly
+ * readers.
+ */
+
+/*
+ * The radio capture header precedes the 802.11 header.
+ * All data in the header is little endian on all platforms.
+ */
+struct ieee80211_radiotap_header
+{
+  u8 it_version;                /* Version 0. Only increases
+                                 * for drastic changes,
+                                 * introduction of compatible
+                                 * new fields does not count.
+                                 */
+  u8 it_pad;
+  __le16 it_len;                /* length of the whole
+                                 * header in bytes, including
+                                 * it_version, it_pad,
+                                 * it_len, and data fields.
+                                 */
+  __le32 it_present;            /* A bitmap telling which
+                                 * fields are present. Set bit 31
+                                 * (0x80000000) to extend the
+                                 * bitmap by another 32 bits.
+                                 * Additional extensions are made
+                                 * by setting bit 31.
+                                 */
+} __packed;
+
+/* Name                                 Data type    Units
+ * ----                                 ---------    -----
+ *
+ * IEEE80211_RADIOTAP_TSFT              __le64       microseconds
+ *
+ *      Value in microseconds of the MAC's 64-bit 802.11 Time
+ *      Synchronization Function timer when the first bit of the
+ *      MPDU arrived at the MAC. For received frames, only.
+ *
+ * IEEE80211_RADIOTAP_CHANNEL           2 x __le16   MHz, bitmap
+ *
+ *      Tx/Rx frequency in MHz, followed by flags (see below).
+ *
+ * IEEE80211_RADIOTAP_FHSS              __le16       see below
+ *
+ *      For frequency-hopping radios, the hop set (first byte)
+ *      and pattern (second byte).
+ *
+ * IEEE80211_RADIOTAP_RATE              u8           500kb/s
+ *
+ *      Tx/Rx data rate
+ *
+ * IEEE80211_RADIOTAP_DBM_ANTSIGNAL     s8           decibels from
+ *                                                   one milliwatt (dBm)
+ *
+ *      RF signal power at the antenna, decibel difference from
+ *      one milliwatt.
+ *
+ * IEEE80211_RADIOTAP_DBM_ANTNOISE      s8           decibels from
+ *                                                   one milliwatt (dBm)
+ *
+ *      RF noise power at the antenna, decibel difference from one
+ *      milliwatt.
+ *
+ * IEEE80211_RADIOTAP_DB_ANTSIGNAL      u8           decibel (dB)
+ *
+ *      RF signal power at the antenna, decibel difference from an
+ *      arbitrary, fixed reference.
+ *
+ * IEEE80211_RADIOTAP_DB_ANTNOISE       u8           decibel (dB)
+ *
+ *      RF noise power at the antenna, decibel difference from an
+ *      arbitrary, fixed reference point.
+ *
+ * IEEE80211_RADIOTAP_LOCK_QUALITY      __le16       unitless
+ *
+ *      Quality of Barker code lock. Unitless. Monotonically
+ *      nondecreasing with "better" lock strength. Called "Signal
+ *      Quality" in datasheets.  (Is there a standard way to measure
+ *      this?)
+ *
+ * IEEE80211_RADIOTAP_TX_ATTENUATION    __le16       unitless
+ *
+ *      Transmit power expressed as unitless distance from max
+ *      power set at factory calibration.  0 is max power.
+ *      Monotonically nondecreasing with lower power levels.
+ *
+ * IEEE80211_RADIOTAP_DB_TX_ATTENUATION __le16       decibels (dB)
+ *
+ *      Transmit power expressed as decibel distance from max power
+ *      set at factory calibration.  0 is max power.  Monotonically
+ *      nondecreasing with lower power levels.
+ *
+ * IEEE80211_RADIOTAP_DBM_TX_POWER      s8           decibels from
+ *                                                   one milliwatt (dBm)
+ *
+ *      Transmit power expressed as dBm (decibels from a 1 milliwatt
+ *      reference). This is the absolute power level measured at
+ *      the antenna port.
+ *
+ * IEEE80211_RADIOTAP_FLAGS             u8           bitmap
+ *
+ *      Properties of transmitted and received frames. See flags
+ *      defined below.
+ *
+ * IEEE80211_RADIOTAP_ANTENNA           u8           antenna index
+ *
+ *      Unitless indication of the Rx/Tx antenna for this packet.
+ *      The first antenna is antenna 0.
+ *
+ * IEEE80211_RADIOTAP_RX_FLAGS          __le16       bitmap
+ *
+ *     Properties of received frames. See flags defined below.
+ *
+ * IEEE80211_RADIOTAP_TX_FLAGS          __le16       bitmap
+ *
+ *     Properties of transmitted frames. See flags defined below.
+ *
+ * IEEE80211_RADIOTAP_RTS_RETRIES       u8           data
+ *
+ *     Number of rts retries a transmitted frame used.
+ *
+ * IEEE80211_RADIOTAP_DATA_RETRIES      u8           data
+ *
+ *     Number of unicast retries a transmitted frame used.
+ *
+ */
+enum ieee80211_radiotap_type
+{
+  IEEE80211_RADIOTAP_TSFT = 0,
+  IEEE80211_RADIOTAP_FLAGS = 1,
+  IEEE80211_RADIOTAP_RATE = 2,
+  IEEE80211_RADIOTAP_CHANNEL = 3,
+  IEEE80211_RADIOTAP_FHSS = 4,
+  IEEE80211_RADIOTAP_DBM_ANTSIGNAL = 5,
+  IEEE80211_RADIOTAP_DBM_ANTNOISE = 6,
+  IEEE80211_RADIOTAP_LOCK_QUALITY = 7,
+  IEEE80211_RADIOTAP_TX_ATTENUATION = 8,
+  IEEE80211_RADIOTAP_DB_TX_ATTENUATION = 9,
+  IEEE80211_RADIOTAP_DBM_TX_POWER = 10,
+  IEEE80211_RADIOTAP_ANTENNA = 11,
+  IEEE80211_RADIOTAP_DB_ANTSIGNAL = 12,
+  IEEE80211_RADIOTAP_DB_ANTNOISE = 13,
+  IEEE80211_RADIOTAP_RX_FLAGS = 14,
+  IEEE80211_RADIOTAP_TX_FLAGS = 15,
+  IEEE80211_RADIOTAP_RTS_RETRIES = 16,
+  IEEE80211_RADIOTAP_DATA_RETRIES = 17,
+
+  /* valid in every it_present bitmap, even vendor namespaces */
+  IEEE80211_RADIOTAP_RADIOTAP_NAMESPACE = 29,
+  IEEE80211_RADIOTAP_VENDOR_NAMESPACE = 30,
+  IEEE80211_RADIOTAP_EXT = 31
+};
+
+/* Channel flags. */
+#define IEEE80211_CHAN_TURBO    0x0010  /* Turbo channel */
+#define IEEE80211_CHAN_CCK      0x0020  /* CCK channel */
+#define IEEE80211_CHAN_OFDM     0x0040  /* OFDM channel */
+#define IEEE80211_CHAN_2GHZ     0x0080  /* 2 GHz spectrum channel. */
+#define IEEE80211_CHAN_5GHZ     0x0100  /* 5 GHz spectrum channel */
+#define IEEE80211_CHAN_PASSIVE  0x0200  /* Only passive scan allowed */
+#define IEEE80211_CHAN_DYN      0x0400  /* Dynamic CCK-OFDM channel */
+#define IEEE80211_CHAN_GFSK     0x0800  /* GFSK channel (FHSS PHY) */
+
+/* For IEEE80211_RADIOTAP_FLAGS */
+#define IEEE80211_RADIOTAP_F_CFP        0x01    /* sent/received
+                                                 * during CFP
+                                                 */
+#define IEEE80211_RADIOTAP_F_SHORTPRE   0x02    /* sent/received
+                                                 * with short
+                                                 * preamble
+                                                 */
+#define IEEE80211_RADIOTAP_F_WEP        0x04    /* sent/received
+                                                 * with WEP encryption
+                                                 */
+#define IEEE80211_RADIOTAP_F_FRAG       0x08    /* sent/received
+                                                 * with fragmentation
+                                                 */
+#define IEEE80211_RADIOTAP_F_FCS        0x10    /* frame includes FCS */
+#define IEEE80211_RADIOTAP_F_DATAPAD    0x20    /* frame has padding between
+                                                 * 802.11 header and payload
+                                                 * (to 32-bit boundary)
+                                                 */
+#define IEEE80211_RADIOTAP_F_BADFCS     0x40    /* bad FCS */
+
+/* For IEEE80211_RADIOTAP_RX_FLAGS */
+#define IEEE80211_RADIOTAP_F_RX_BADPLCP 0x0002  /* frame has bad PLCP */
+
+/* For IEEE80211_RADIOTAP_TX_FLAGS */
+#define IEEE80211_RADIOTAP_F_TX_FAIL    0x0001  /* failed due to excessive
+                                                 * retries */
+#define IEEE80211_RADIOTAP_F_TX_CTS     0x0002  /* used cts 'protection' */
+#define IEEE80211_RADIOTAP_F_TX_RTS     0x0004  /* used rts/cts handshake */
+
+/* Ugly macro to convert literal channel numbers into their mhz equivalents
+ * There are certianly some conditions that will break this (like feeding it '30')
+ * but they shouldn't arise since nothing talks on channel 30. */
+#define ieee80211chan2mhz(x) \
+  (((x) <= 14) ? \
+   (((x) == 14) ? 2484 : ((x) * 5) + 2407) : \
+   ((x) + 1000) * 5)
+
+/* helpers */
+static inline u16
+get_unaligned_le16 (const u8 *p)
+{
+  return p[0] | p[1] << 8;
+}
+
+
+static inline int
+ieee80211_get_radiotap_len (unsigned char *data)
+{
+  struct ieee80211_radiotap_header *hdr =
+    (struct ieee80211_radiotap_header *) data;
+
+  return get_unaligned_le16 ((const u8 *) &hdr->it_len);
+}
+
+
+#endif /* IEEE80211_RADIOTAP_H */
diff --git a/src/transport/perf_http_peer1.conf b/src/transport/perf_http_peer1.conf
new file mode 100644
index 0000000000000000000000000000000000000000..e97e1628904530813e1af0f9428c7465dc83e0d3
--- /dev/null
+++ b/src/transport/perf_http_peer1.conf
@@ -0,0 +1,37 @@
+@INLINE@ template_cfg_peer1.conf
+[PATHS]
+GNUNET_TEST_HOME = $GNUNET_TMP/test-transport/api-tcp-p1/
+
+[transport]
+PLUGINS = http_client
+
+[nat]
+# Disable IPv6 support
+DISABLEV6 = YES
+# Do we use addresses from localhost address ranges? (::1, 127.0.0.0/8)
+RETURN_LOCAL_ADDRESSES = NO
+
+[hostlist]
+OPTIONS = -b
+SERVERS = http://localhost:9080/
+
+[ats]
+# Network specific inbound/outbound quotas
+UNSPECIFIED_QUOTA_IN = unlimited
+UNSPECIFIED_QUOTA_OUT = unlimited
+# LOOPBACK
+LOOPBACK_QUOTA_IN = unlimited
+LOOPBACK_QUOTA_OUT = unlimited
+# LAN
+LAN_QUOTA_IN = unlimited
+LAN_QUOTA_OUT = unlimited
+# WAN
+WAN_QUOTA_IN = unlimited
+WAN_QUOTA_OUT = unlimited
+# WLAN
+WLAN_QUOTA_IN = unlimited
+WLAN_QUOTA_OUT = unlimited
+# BLUETOOTH
+BLUETOOTH_QUOTA_IN = unlimited
+BLUETOOTH_QUOTA_OUT = unlimited
+# ATS options
diff --git a/src/transport/perf_http_peer2.conf b/src/transport/perf_http_peer2.conf
new file mode 100644
index 0000000000000000000000000000000000000000..a1c83bde5b889ab8a7fefd9f14118ccf1f012f16
--- /dev/null
+++ b/src/transport/perf_http_peer2.conf
@@ -0,0 +1,40 @@
+@INLINE@ template_cfg_peer2.conf
+[PATHS]
+GNUNET_TEST_HOME = $GNUNET_TMP/test-transport/api-tcp-p2/
+
+[transport]
+PLUGINS = http_server
+
+[nat]
+# Disable IPv6 support
+DISABLEV6 = YES
+# Do we use addresses from localhost address ranges? (::1, 127.0.0.0/8)
+RETURN_LOCAL_ADDRESSES = NO
+
+[hostlist]
+HTTPPORT = 9080
+OPTIONS = -p
+BINDTOIPV4 = YES
+BINDTOIP = 127.0.0.1
+
+[ats]
+# Network specific inbound/outbound quotas
+UNSPECIFIED_QUOTA_IN = unlimited
+UNSPECIFIED_QUOTA_OUT = unlimited
+# LOOPBACK
+LOOPBACK_QUOTA_IN = unlimited
+LOOPBACK_QUOTA_OUT = unlimited
+# LAN
+LAN_QUOTA_IN = unlimited
+LAN_QUOTA_OUT = unlimited
+# WAN
+WAN_QUOTA_IN = unlimited
+WAN_QUOTA_OUT = unlimited
+# WLAN
+WLAN_QUOTA_IN = unlimited
+WLAN_QUOTA_OUT = unlimited
+# BLUETOOTH
+BLUETOOTH_QUOTA_IN = unlimited
+BLUETOOTH_QUOTA_OUT = unlimited
+# ATS options
+
diff --git a/src/transport/perf_https_peer1.conf b/src/transport/perf_https_peer1.conf
new file mode 100644
index 0000000000000000000000000000000000000000..e943671c27f462f8559afe53346d977ee633d9d2
--- /dev/null
+++ b/src/transport/perf_https_peer1.conf
@@ -0,0 +1,37 @@
+@INLINE@ template_cfg_peer1.conf
+[PATHS]
+GNUNET_TEST_HOME = $GNUNET_TMP/test-transport/api-tcp-p1/
+
+[transport]
+PLUGINS = https_client
+
+[nat]
+# Disable IPv6 support
+DISABLEV6 = YES
+# Do we use addresses from localhost address ranges? (::1, 127.0.0.0/8)
+RETURN_LOCAL_ADDRESSES = NO
+
+[hostlist]
+OPTIONS = -b
+SERVERS = http://localhost:9080/
+
+[ats]
+# Network specific inbound/outbound quotas
+UNSPECIFIED_QUOTA_IN = unlimited
+UNSPECIFIED_QUOTA_OUT = unlimited
+# LOOPBACK
+LOOPBACK_QUOTA_IN = unlimited
+LOOPBACK_QUOTA_OUT = unlimited
+# LAN
+LAN_QUOTA_IN = unlimited
+LAN_QUOTA_OUT = unlimited
+# WAN
+WAN_QUOTA_IN = unlimited
+WAN_QUOTA_OUT = unlimited
+# WLAN
+WLAN_QUOTA_IN = unlimited
+WLAN_QUOTA_OUT = unlimited
+# BLUETOOTH
+BLUETOOTH_QUOTA_IN = unlimited
+BLUETOOTH_QUOTA_OUT = unlimited
+# ATS options
diff --git a/src/transport/perf_https_peer2.conf b/src/transport/perf_https_peer2.conf
new file mode 100644
index 0000000000000000000000000000000000000000..6e30f9e609d182e98c5ae63440635dc29d6028f6
--- /dev/null
+++ b/src/transport/perf_https_peer2.conf
@@ -0,0 +1,40 @@
+@INLINE@ template_cfg_peer2.conf
+[PATHS]
+GNUNET_TEST_HOME = $GNUNET_TMP/test-transport/api-tcp-p2/
+
+[transport]
+PLUGINS = https_server
+
+[nat]
+# Disable IPv6 support
+DISABLEV6 = YES
+# Do we use addresses from localhost address ranges? (::1, 127.0.0.0/8)
+RETURN_LOCAL_ADDRESSES = NO
+
+[hostlist]
+HTTPPORT = 9080
+OPTIONS = -p
+BINDTOIPV4 = YES
+BINDTOIP = 127.0.0.1
+
+[ats]
+# Network specific inbound/outbound quotas
+UNSPECIFIED_QUOTA_IN = unlimited
+UNSPECIFIED_QUOTA_OUT = unlimited
+# LOOPBACK
+LOOPBACK_QUOTA_IN = unlimited
+LOOPBACK_QUOTA_OUT = unlimited
+# LAN
+LAN_QUOTA_IN = unlimited
+LAN_QUOTA_OUT = unlimited
+# WAN
+WAN_QUOTA_IN = unlimited
+WAN_QUOTA_OUT = unlimited
+# WLAN
+WLAN_QUOTA_IN = unlimited
+WLAN_QUOTA_OUT = unlimited
+# BLUETOOTH
+BLUETOOTH_QUOTA_IN = unlimited
+BLUETOOTH_QUOTA_OUT = unlimited
+# ATS options
+
diff --git a/src/transport/perf_udp_peer1.conf b/src/transport/perf_udp_peer1.conf
new file mode 100644
index 0000000000000000000000000000000000000000..68bf4390827436749fa3b722d819b82e4237a7ff
--- /dev/null
+++ b/src/transport/perf_udp_peer1.conf
@@ -0,0 +1,43 @@
+@INLINE@ template_cfg_peer1.conf
+[PATHS]
+GNUNET_TEST_HOME = $GNUNET_TMP/test-transport/api-tcp-p1/
+
+[transport]
+PLUGINS = udp
+
+[transport-udp]
+BROADCAST = NO
+BROADCAST_RECEIVE = NO
+BROADCAST_INTERVAL = 30 s
+MAX_BPS = 1000000000
+
+[nat]
+# Disable IPv6 support
+DISABLEV6 = YES
+# Do we use addresses from localhost address ranges? (::1, 127.0.0.0/8)
+RETURN_LOCAL_ADDRESSES = NO
+
+[hostlist]
+OPTIONS = -b
+SERVERS = http://localhost:9080/
+
+[ats]
+# Network specific inbound/outbound quotas
+UNSPECIFIED_QUOTA_IN = unlimited
+UNSPECIFIED_QUOTA_OUT = unlimited
+# LOOPBACK
+LOOPBACK_QUOTA_IN = unlimited
+LOOPBACK_QUOTA_OUT = unlimited
+# LAN
+LAN_QUOTA_IN = unlimited
+LAN_QUOTA_OUT = unlimited
+# WAN
+WAN_QUOTA_IN = unlimited
+WAN_QUOTA_OUT = unlimited
+# WLAN
+WLAN_QUOTA_IN = unlimited
+WLAN_QUOTA_OUT = unlimited
+# BLUETOOTH
+BLUETOOTH_QUOTA_IN = unlimited
+BLUETOOTH_QUOTA_OUT = unlimited
+# ATS options
diff --git a/src/transport/perf_udp_peer2.conf b/src/transport/perf_udp_peer2.conf
new file mode 100644
index 0000000000000000000000000000000000000000..efed935f835353810a4f08603584d43c9bf70b26
--- /dev/null
+++ b/src/transport/perf_udp_peer2.conf
@@ -0,0 +1,48 @@
+@INLINE@ template_cfg_peer2.conf
+[PATHS]
+GNUNET_TEST_HOME = $GNUNET_TMP/test-transport/api-tcp-p2/
+
+[transport]
+PLUGINS = udp
+
+
+[transport-udp]
+# Use PORT = 0 to autodetect a port available
+BROADCAST = NO
+BROADCAST_RECEIVE = NO
+BROADCAST_INTERVAL = 30 s
+MAX_BPS = 1000000000
+
+[nat]
+# Disable IPv6 support
+DISABLEV6 = YES
+# Do we use addresses from localhost address ranges? (::1, 127.0.0.0/8)
+RETURN_LOCAL_ADDRESSES = NO
+
+[hostlist]
+HTTPPORT = 9080
+OPTIONS = -p
+BINDTOIPV4 = YES
+BINDTOIP = 127.0.0.1
+
+[ats]
+# Network specific inbound/outbound quotas
+UNSPECIFIED_QUOTA_IN = unlimited
+UNSPECIFIED_QUOTA_OUT = unlimited
+# LOOPBACK
+LOOPBACK_QUOTA_IN = unlimited
+LOOPBACK_QUOTA_OUT = unlimited
+# LAN
+LAN_QUOTA_IN = unlimited
+LAN_QUOTA_OUT = unlimited
+# WAN
+WAN_QUOTA_IN = unlimited
+WAN_QUOTA_OUT = unlimited
+# WLAN
+WLAN_QUOTA_IN = unlimited
+WLAN_QUOTA_OUT = unlimited
+# BLUETOOTH
+BLUETOOTH_QUOTA_IN = unlimited
+BLUETOOTH_QUOTA_OUT = unlimited
+# ATS options
+
diff --git a/src/transport/perf_unix_peer1.conf b/src/transport/perf_unix_peer1.conf
new file mode 100644
index 0000000000000000000000000000000000000000..06cd63fc673a2b73fce6c9ff0ea9d4310781c0e3
--- /dev/null
+++ b/src/transport/perf_unix_peer1.conf
@@ -0,0 +1,52 @@
+@INLINE@ template_cfg_peer1.conf
+[PATHS]
+GNUNET_TEST_HOME = $GNUNET_TMP/test-transport/api-tcp-p1/
+
+[transport]
+PORT = 12001
+UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p1-service-transport.sock
+PLUGINS = unix
+
+[transport-unix]
+UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p1-unix.sock
+
+[arm]
+PORT = 12005
+UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p1-service-arm.sock
+
+[statistics]
+PORT = 12004
+UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p1-service-statistics.sock
+
+[resolver]
+PORT = 12003
+UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p1-service-resolver.sock
+
+[peerinfo]
+PORT = 12002
+UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p1-service-peerinfo.sock
+
+[hostlist]
+OPTIONS = -b
+SERVERS = http://localhost:9080/
+
+[ats]
+# Network specific inbound/outbound quotas
+UNSPECIFIED_QUOTA_IN = unlimited
+UNSPECIFIED_QUOTA_OUT = unlimited
+# LOOPBACK
+LOOPBACK_QUOTA_IN = unlimited
+LOOPBACK_QUOTA_OUT = unlimited
+# LAN
+LAN_QUOTA_IN = unlimited
+LAN_QUOTA_OUT = unlimited
+# WAN
+WAN_QUOTA_IN = unlimited
+WAN_QUOTA_OUT = unlimited
+# WLAN
+WLAN_QUOTA_IN = unlimited
+WLAN_QUOTA_OUT = unlimited
+# BLUETOOTH
+BLUETOOTH_QUOTA_IN = unlimited
+BLUETOOTH_QUOTA_OUT = unlimited
+# ATS options
diff --git a/src/transport/perf_unix_peer2.conf b/src/transport/perf_unix_peer2.conf
new file mode 100644
index 0000000000000000000000000000000000000000..feadb6fecc991e0670c05d56e8a4f01f78808702
--- /dev/null
+++ b/src/transport/perf_unix_peer2.conf
@@ -0,0 +1,56 @@
+@INLINE@ template_cfg_peer2.conf
+[PATHS]
+GNUNET_TEST_HOME = $GNUNET_TMP/test-transport/api-tcp-p2/
+
+[transport]
+PORT = 12010
+PLUGINS = unix
+UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p2-service-transport.sock
+
+
+[transport-unix]
+UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p2-unix.sock
+
+[arm]
+PORT = 12014
+UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p2-service-arm.sock
+
+[statistics]
+PORT = 12013
+UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p2-service-statistics.sock
+
+[resolver]
+PORT = 12012
+UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p2-service-resolver.sock
+
+[peerinfo]
+PORT = 12011
+UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p2-service-peerinfo.sock
+
+[hostlist]
+HTTPPORT = 9080
+OPTIONS = -p
+BINDTOIPV4 = YES
+BINDTOIP = 127.0.0.1
+
+[ats]
+# Network specific inbound/outbound quotas
+UNSPECIFIED_QUOTA_IN = unlimited
+UNSPECIFIED_QUOTA_OUT = unlimited
+# LOOPBACK
+LOOPBACK_QUOTA_IN = unlimited
+LOOPBACK_QUOTA_OUT = unlimited
+# LAN
+LAN_QUOTA_IN = unlimited
+LAN_QUOTA_OUT = unlimited
+# WAN
+WAN_QUOTA_IN = unlimited
+WAN_QUOTA_OUT = unlimited
+# WLAN
+WLAN_QUOTA_IN = unlimited
+WLAN_QUOTA_OUT = unlimited
+# BLUETOOTH
+BLUETOOTH_QUOTA_IN = unlimited
+BLUETOOTH_QUOTA_OUT = unlimited
+# ATS options
+
diff --git a/src/transport/plugin_transport_http.h b/src/transport/plugin_transport_http.h
new file mode 100644
index 0000000000000000000000000000000000000000..a3b59513e3acbcb12c8581eb54cff6bf44f9599c
--- /dev/null
+++ b/src/transport/plugin_transport_http.h
@@ -0,0 +1,579 @@
+/*
+     This file is part of GNUnet
+     Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 GNUnet e.V.
+
+     GNUnet is free software: you can redistribute it and/or modify it
+     under the terms of the GNU Affero General Public License as published
+     by the Free Software Foundation, either version 3 of the License,
+     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
+     Affero General Public License for more details.
+
+     You should have received a copy of the GNU Affero General Public License
+     along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+     SPDX-License-Identifier: AGPL3.0-or-later
+ */
+
+/**
+ * @file transport/plugin_transport_http.h
+ * @brief http transport service plugin
+ * @author Matthias Wachs
+ */
+#ifndef PLUGIN_TRANSPORT_HTTP_H
+#define PLUGIN_TRANSPORT_HTTP_H
+
+#include "platform.h"
+#include "gnunet_common.h"
+#include "gnunet_constants.h"
+#include "gnunet_protocols.h"
+#include "gnunet_connection_lib.h"
+#include "gnunet_service_lib.h"
+#include "gnunet_statistics_service.h"
+#include "gnunet_transport_service.h"
+#include "gnunet_resolver_service.h"
+#include "gnunet_server_lib.h"
+#include "gnunet_container_lib.h"
+#include "gnunet_transport_plugin.h"
+#include "gnunet_os_lib.h"
+#include "gnunet_nat_lib.h"
+#include "microhttpd.h"
+/* Just included for the right curl.h */
+#include "gnunet_curl_lib.h"
+
+
+#define DEBUG_HTTP GNUNET_EXTRA_LOGGING
+#define VERBOSE_SERVER GNUNET_EXTRA_LOGGING
+#define VERBOSE_CLIENT GNUNET_EXTRA_LOGGING
+#define VERBOSE_CURL GNUNET_NO
+
+#if BUILD_HTTPS
+#define LIBGNUNET_PLUGIN_TRANSPORT_INIT libgnunet_plugin_transport_https_init
+#define LIBGNUNET_PLUGIN_TRANSPORT_DONE libgnunet_plugin_transport_https_done
+#else
+#define LIBGNUNET_PLUGIN_TRANSPORT_INIT libgnunet_plugin_transport_http_init
+#define LIBGNUNET_PLUGIN_TRANSPORT_DONE libgnunet_plugin_transport_http_done
+#endif
+
+#define INBOUND  GNUNET_YES
+#define OUTBOUND GNUNET_NO
+
+
+#define HTTP_NOT_VALIDATED_TIMEOUT GNUNET_TIME_relative_multiply ( \
+    GNUNET_TIME_UNIT_SECONDS, 15)
+
+/**
+ * Encapsulation of all of the state of the plugin.
+ */
+struct Plugin
+{
+  /**
+   * Our environment.
+   */
+  struct GNUNET_TRANSPORT_PluginEnvironment *env;
+
+  /**
+   * Head of linked list of open sessions.
+   */
+  struct GNUNET_ATS_Session *head;
+
+  /**
+   * Tail of linked list of open sessions.
+   */
+  struct GNUNET_ATS_Session *tail;
+
+  /**
+   * NAT handle & address management
+   */
+  struct GNUNET_NAT_Handle *nat;
+
+  /**
+   * Our own IPv4 addresses DLL head
+   */
+  struct HttpAddressWrapper *addr_head;
+
+  /**
+   * Our own IPv4 addresses DLL tail
+   */
+  struct HttpAddressWrapper *addr_tail;
+
+  /**
+   * External hostname the plugin can be connected to, can be different to
+   * the host's FQDN, used e.g. for reverse proxying
+   */
+  char *external_hostname;
+
+  /**
+   * External hostname the plugin can be connected to, can be different to
+   * the host's FQDN, used e.g. for reverse proxying
+   */
+  struct HttpAddress *ext_addr;
+
+  /**
+   * External address length
+   */
+  size_t ext_addr_len;
+
+  /**
+   * Task calling transport service about external address
+   */
+  struct GNUNET_SCHEDULER_Task *notify_ext_task;
+
+  /**
+   * Plugin name.
+   * Equals configuration section: transport-http, transport-https
+   */
+  char *name;
+
+  /**
+   * Plugin protocol
+   * http, https
+   */
+  char *protocol;
+
+  /**
+   * Use IPv4? #GNUNET_YES or #GNUNET_NO
+   */
+  int ipv4;
+
+  /**
+   * Use IPv6? #GNUNET_YES or #GNUNET_NO
+   */
+  int ipv6;
+
+  /**
+   * Does plugin just use outbound connections and not accept inbound?
+   */
+  int client_only;
+
+  /**
+   * Port used
+   */
+  uint16_t port;
+
+  /**
+   * Maximum number of sockets the plugin can use
+   * Each http inbound /outbound connections are two connections
+   */
+  int max_connections;
+
+  /**
+   * Number of outbound sessions
+   */
+  unsigned int outbound_sessions;
+
+  /**
+   * Number of inbound sessions
+   */
+  unsigned int inbound_sessions;
+
+  /**
+   * libCurl TLS crypto init string, can be set to enhance performance
+   *
+   * Example:
+   *
+   * Use RC4-128 instead of AES:
+   * NONE:+VERS-TLS1.0:+ARCFOUR-128:+SHA1:+RSA:+COMP-NULL
+   */
+  char *crypto_init;
+
+  /**
+   * TLS key
+   */
+  char *key;
+
+  /**
+   * TLS certificate
+   */
+  char *cert;
+
+  /**
+   * Current number of establishes connections
+   */
+  int cur_connections;
+
+  /**
+   * Last used unique HTTP connection tag
+   */
+  uint32_t last_tag;
+
+  /**
+   * MHD IPv4 daemon
+   */
+  struct MHD_Daemon *server_v4;
+
+  /**
+   * MHD IPv4 task
+   */
+  struct GNUNET_SCHEDULER_Task *server_v4_task;
+
+  /**
+   * The IPv4 server is scheduled to run asap
+   */
+  int server_v4_immediately;
+
+  /**
+   * MHD IPv6 daemon
+   */
+  struct MHD_Daemon *server_v6;
+
+  /**
+   * MHD IPv4 task
+   */
+  struct GNUNET_SCHEDULER_Task *server_v6_task;
+
+  /**
+   * The IPv6 server is scheduled to run asap
+   */
+  int server_v6_immediately;
+
+  /**
+   * IPv4 server socket to bind to
+   */
+  struct sockaddr_in *server_addr_v4;
+
+  /**
+   * IPv6 server socket to bind to
+   */
+  struct sockaddr_in6 *server_addr_v6;
+
+  /**
+   * Head of server semi connections
+   * A full session consists of 2 semi-connections: send and receive
+   * If not both directions are established the server keeps this sessions here
+   */
+  struct GNUNET_ATS_Session *server_semi_head;
+
+  /**
+   * Tail of server semi connections
+   * A full session consists of 2 semi-connections: send and receive
+   * If not both directions are established the server keeps this sessions here
+   */
+  struct GNUNET_ATS_Session *server_semi_tail;
+
+  /**
+   * cURL Multihandle
+   */
+  CURLM *client_mh;
+
+  /**
+   * curl perform task
+   */
+  struct GNUNET_SCHEDULER_Task *client_perform_task;
+};
+
+GNUNET_NETWORK_STRUCT_BEGIN
+
+/**
+ * HTTP addresses including a full URI
+ */
+struct HttpAddress
+{
+  /**
+   * Length of the address following in NBO
+   */
+  uint32_t addr_len GNUNET_PACKED;
+
+  /**
+   * Address following
+   */
+  void *addr GNUNET_PACKED;
+};
+
+/**
+ * IPv4 addresses
+ */
+struct IPv4HttpAddress
+{
+  /**
+   * IPv4 address, in network byte order.
+   */
+  uint32_t ipv4_addr GNUNET_PACKED;
+
+  /**
+   * Port number, in network byte order.
+   */
+  uint16_t u4_port GNUNET_PACKED;
+};
+
+/**
+ * IPv4 addresses
+ */
+struct IPv6HttpAddress
+{
+  /**
+   * IPv6 address.
+   */
+  struct in6_addr ipv6_addr GNUNET_PACKED;
+
+  /**
+   * Port number, in network byte order.
+   */
+  uint16_t u6_port GNUNET_PACKED;
+};
+GNUNET_NETWORK_STRUCT_END
+
+
+struct ServerRequest
+{
+  /**
+   * _RECV or _SEND
+   */
+  int direction;
+
+  /**
+   * Should this connection get disconnected? #GNUNET_YES / #GNUNET_NO
+   */
+  int disconnect;
+
+  /**
+   * The session this server connection belongs to
+   */
+  struct GNUNET_ATS_Session *session;
+
+  /**
+   * The MHD connection
+   */
+  struct MHD_Connection *mhd_conn;
+};
+
+
+/**
+ * Session handle for connections.
+ */
+struct GNUNET_ATS_Session
+{
+  /**
+   * To whom are we talking to
+   */
+  struct GNUNET_PeerIdentity target;
+
+  /**
+   * Stored in a linked list.
+   */
+  struct GNUNET_ATS_Session *next;
+
+  /**
+   * Stored in a linked list.
+   */
+  struct GNUNET_ATS_Session *prev;
+
+  /**
+   * Pointer to the global plugin struct.
+   */
+  struct Plugin *plugin;
+
+  /**
+   * Address
+   */
+  void *addr;
+
+  /**
+   * Address length
+   */
+  size_t addrlen;
+
+  /**
+   * ATS network type in NBO
+   */
+  uint32_t ats_address_network_type;
+
+  /**
+   * next pointer for double linked list
+   */
+  struct HTTP_Message *msg_head;
+
+  /**
+   * previous pointer for double linked list
+   */
+  struct HTTP_Message *msg_tail;
+
+  /**
+   * Message stream tokenizer for incoming data
+   */
+  struct GNUNET_SERVER_MessageStreamTokenizer *msg_tk;
+
+  /**
+   * Absolute time when to receive data again
+   * Used for receive throttling
+   */
+  struct GNUNET_TIME_Absolute next_receive;
+
+  /**
+   * Inbound or outbound connection
+   * Outbound: #GNUNET_NO (client is used to send and receive)
+   * Inbound : #GNUNET_YES (server is used to send and receive)
+   */
+  int inbound;
+
+  /**
+   * Unique HTTP/S connection tag for this connection
+   */
+  uint32_t tag;
+
+  /**
+   * Client send handle
+   */
+  void *client_put;
+
+  /**
+   * Client receive handle
+   */
+  void *client_get;
+
+  /**
+   * Task to wake up client receive handle when receiving is allowed again
+   */
+  struct GNUNET_SCHEDULER_Task *recv_wakeup_task;
+
+  /**
+   * Session timeout task
+   */
+  struct GNUNET_SCHEDULER_Task *timeout_task;
+
+  /**
+   * Is client send handle paused since there are no data to send?
+   * #GNUNET_YES or #GNUNET_NO
+   */
+  int client_put_paused;
+
+  /**
+   * Client send handle
+   */
+  struct ServerRequest *server_recv;
+
+  /**
+   * Client send handle
+   */
+  struct ServerRequest *server_send;
+};
+
+
+/**
+ *  Message to send using http
+ */
+struct HTTP_Message
+{
+  /**
+   * next pointer for double linked list
+   */
+  struct HTTP_Message *next;
+
+  /**
+   * previous pointer for double linked list
+   */
+  struct HTTP_Message *prev;
+
+  /**
+   * buffer containing data to send
+   */
+  char *buf;
+
+  /**
+   * amount of data already sent
+   */
+  size_t pos;
+
+  /**
+   * buffer length
+   */
+  size_t size;
+
+  /**
+   * Continuation function to call once the transmission buffer
+   * has again space available.  NULL if there is no
+   * continuation to call.
+   */
+  GNUNET_TRANSPORT_TransmitContinuation transmit_cont;
+
+  /**
+   * Closure for @e transmit_cont.
+   */
+  void *transmit_cont_cls;
+};
+
+
+struct GNUNET_ATS_Session *
+create_session (struct Plugin *plugin,
+                const struct GNUNET_PeerIdentity *target,
+                const void *addr,
+                size_t addrlen);
+
+
+int
+exist_session (struct Plugin *plugin,
+               struct GNUNET_ATS_Session *s);
+
+
+void
+delete_session (struct GNUNET_ATS_Session *s);
+
+
+int
+exist_session (struct Plugin *plugin,
+               struct GNUNET_ATS_Session *s);
+
+
+struct GNUNET_TIME_Relative
+http_plugin_receive (void *cls,
+                     const struct GNUNET_PeerIdentity *peer,
+                     const struct GNUNET_MessageHeader *message,
+                     struct GNUNET_ATS_Session *session,
+                     const char *sender_address,
+                     uint16_t sender_address_len);
+
+
+const char *
+http_plugin_address_to_string (void *cls,
+                               const void *addr,
+                               size_t addrlen);
+
+
+int
+client_disconnect (struct GNUNET_ATS_Session *s);
+
+
+int
+client_connect (struct GNUNET_ATS_Session *s);
+
+
+int
+client_send (struct GNUNET_ATS_Session *s, struct HTTP_Message *msg);
+
+
+int
+client_start (struct Plugin *plugin);
+
+
+void
+client_stop (struct Plugin *plugin);
+
+
+int
+server_disconnect (struct GNUNET_ATS_Session *s);
+
+
+int
+server_send (struct GNUNET_ATS_Session *s, struct HTTP_Message *msg);
+
+
+int
+server_start (struct Plugin *plugin);
+
+
+void
+server_stop (struct Plugin *plugin);
+
+
+void
+notify_session_end (void *cls,
+                    const struct GNUNET_PeerIdentity *peer,
+                    struct GNUNET_ATS_Session *s);
+
+
+/*#ifndef PLUGIN_TRANSPORT_HTTP_H*/
+#endif
+/* end of plugin_transport_http.h */
diff --git a/src/transport/plugin_transport_http_server.c b/src/transport/plugin_transport_http_server.c
index 514f7fd1f43c565cdaa7a1b26bfe6788d15550a7..d1b21ba9cd3ed13a29d2ca36c624f4e2af761a54 100644
--- a/src/transport/plugin_transport_http_server.c
+++ b/src/transport/plugin_transport_http_server.c
@@ -2188,7 +2188,7 @@ server_load_certificate (struct HTTP_Server_Plugin *plugin)
                 "No usable TLS certificate found, creating certificate\n");
     errno = 0;
     cert_creation =
-      GNUNET_OS_start_process (GNUNET_NO, GNUNET_OS_INHERIT_STD_OUT_AND_ERR,
+      GNUNET_OS_start_process (GNUNET_OS_INHERIT_STD_OUT_AND_ERR,
                                NULL, NULL, NULL,
                                "gnunet-transport-certificate-creation",
                                "gnunet-transport-certificate-creation",
diff --git a/src/transport/plugin_transport_smtp.c b/src/transport/plugin_transport_smtp.c
new file mode 100644
index 0000000000000000000000000000000000000000..f3db4fc5a190312bdd61d514fcdf41e99d008654
--- /dev/null
+++ b/src/transport/plugin_transport_smtp.c
@@ -0,0 +1,750 @@
+/*
+     This file is part of GNUnet
+     Copyright (C) 2003-2013 GNUnet e.V.
+
+     GNUnet is free software: you can redistribute it and/or modify it
+     under the terms of the GNU Affero General Public License as published
+     by the Free Software Foundation, either version 3 of the License,
+     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
+     Affero General Public License for more details.
+
+     You should have received a copy of the GNU Affero General Public License
+     along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+     SPDX-License-Identifier: AGPL3.0-or-later
+ */
+
+/**
+ * @file transport/plugin_transport_smtp.c
+ * @brief Implementation of the SMTP transport service
+ * @author Christian Grothoff
+ * @author Renaldo Ferreira
+ */
+
+#include "platform.h"
+#include "gnunet_util.h"
+#include "gnunet_constants.h"
+#include "gnunet_protocols.h"
+#include "gnunet_transport.h"
+#include "gnunet_stats_service.h"
+#include <libesmtp.h>
+#include <signal.h>
+
+
+/**
+ * The default maximum size of each outbound SMTP message.
+ */
+#define SMTP_MESSAGE_SIZE 65528
+
+#define DEBUG_SMTP GNUNET_EXTRA_LOGGING
+
+#define FILTER_STRING_SIZE 64
+
+/* how long can a line in base64 encoded
+   mime text be? (in characters, excluding "\n") */
+#define MAX_CHAR_PER_LINE 76
+
+#define EBUF_LEN 128
+
+/**
+ * Host-Address in a SMTP network.
+ */
+typedef struct
+{
+  /**
+   * Filter line that every sender must include in the E-mails such
+   * that the receiver can effectively filter out the GNUnet traffic
+   * from the E-mail.
+   */
+  char filter[FILTER_STRING_SIZE];
+
+  /**
+   * Claimed E-mail address of the sender.
+   * Format is "foo@bar.com" with null termination, padded to be
+   * of a multiple of 8 bytes long.
+   */
+  char senderAddress[0];
+} EmailAddress;
+
+GNUNET_NETWORK_STRUCT_BEGIN
+
+/**
+ * Encapsulation of a GNUnet message in the SMTP mail body (before
+ * base64 encoding).
+ */
+typedef struct
+{
+  GNUNET_MessageHeader header;
+
+  /**
+   * What is the identity of the sender (GNUNET_hash of public key)
+   */
+  GNUNET_PeerIdentity sender;
+} SMTPMessage;
+GNUNET_NETWORK_STRUCT_END
+
+/* *********** globals ************* */
+
+/**
+ * apis (our advertised API and the core api )
+ */
+static GNUNET_CoreAPIForTransport *core_api;
+
+static struct GNUNET_GE_Context *ectx;
+
+/**
+ * Thread that listens for inbound messages
+ */
+static struct GNUNET_ThreadHandle *dispatchThread;
+
+/**
+ * Flag to indicate that server has been shut down.
+ */
+static int smtp_shutdown = GNUNET_YES;
+
+/**
+ * Set to the SMTP server hostname (and port) for outgoing messages.
+ */
+static char *smtp_server_name;
+
+static char *pipename;
+
+/**
+ * Lock for uses of libesmtp (not thread-safe).
+ */
+static struct GNUNET_Mutex *lock;
+
+/**
+ * Old handler for SIGPIPE (kept to be able to restore).
+ */
+static struct sigaction old_handler;
+
+static char *email;
+
+static GNUNET_TransportAPI smtpAPI;
+
+static GNUNET_Stats_ServiceAPI *stats;
+
+static int stat_bytesReceived;
+
+static int stat_bytesSent;
+
+static int stat_bytesDropped;
+
+/**
+ * How many e-mails are we allowed to send per hour?
+ */
+static unsigned long long rate_limit;
+
+static GNUNET_CronTime last_transmission;
+
+
+/* ********************* the real stuff ******************* */
+
+#define strAUTOncmp(a, b) strncmp (a, b, strlen (b))
+
+/**
+ * Listen to the pipe, decode messages and send to core.
+ */
+static void *
+listenAndDistribute (void *unused)
+{
+  char *line;
+  unsigned int linesize;
+  SMTPMessage *mp;
+  FILE *fdes;
+  char *retl;
+  char *out;
+  unsigned int size;
+  GNUNET_TransportPacket *coreMP;
+  int fd;
+  unsigned int pos;
+
+  linesize = ((GNUNET_MAX_BUFFER_SIZE * 4 / 3) + 8) * (MAX_CHAR_PER_LINE + 2)
+             / MAX_CHAR_PER_LINE;                                                                       /* maximum size of a line supported */
+  line = GNUNET_malloc (linesize + 2);   /* 2 bytes for off-by-one errors, just to be safe... */
+
+#define READLINE(l, limit) \
+  do { retl = fgets (l, (limit), fdes);                          \
+       if ((retl == NULL) || (smtp_shutdown == GNUNET_YES)) { \
+         goto END; \
+       } \
+       if (core_api->load_monitor != NULL) \
+       GNUNET_network_monitor_notify_transmission (core_api->load_monitor, \
+                                                   GNUNET_ND_DOWNLOAD, \
+                                                   strlen (retl)); \
+  } while (0)
+
+
+  while (smtp_shutdown == GNUNET_NO)
+  {
+    fd = OPEN (pipename, O_RDONLY | O_ASYNC);
+    if (fd == -1)
+    {
+      if (smtp_shutdown == GNUNET_NO)
+        GNUNET_thread_sleep (5 * GNUNET_CRON_SECONDS);
+      continue;
+    }
+    fdes = fdopen (fd, "r");
+    while (smtp_shutdown == GNUNET_NO)
+    {
+      /* skip until end of header */
+      do
+      {
+        READLINE (line, linesize);
+      }
+      while ((line[0] != '\r') && (line[0] != '\n'));     /* expect newline */
+      READLINE (line, linesize);        /* read base64 encoded message; decode, process */
+      pos = 0;
+      while (1)
+      {
+        pos = strlen (line) - 1;        /* ignore new line */
+        READLINE (&line[pos], linesize - pos);      /* read base64 encoded message; decode, process */
+        if ((line[pos] == '\r') || (line[pos] == '\n'))
+          break;                /* empty line => end of message! */
+      }
+      size = GNUNET_STRINGS_base64_decode (line, pos, &out);
+      if (size < sizeof(SMTPMessage))
+      {
+        GNUNET_GE_BREAK (ectx, 0);
+        GNUNET_free (out);
+        goto END;
+      }
+
+      mp = (SMTPMessage *) &out[size - sizeof(SMTPMessage)];
+      if (ntohs (mp->header.size) != size)
+      {
+        GNUNET_GE_LOG (ectx,
+                       GNUNET_GE_WARNING | GNUNET_GE_BULK | GNUNET_GE_USER,
+                       _ ("Received malformed message via %s. Ignored.\n"),
+                       "SMTP");
+#if DEBUG_SMTP
+        GNUNET_GE_LOG (ectx,
+                       GNUNET_GE_DEBUG | GNUNET_GE_REQUEST | GNUNET_GE_USER,
+                       "Size returned by base64=%d, in the msg=%d.\n", size,
+                       ntohl (mp->size));
+#endif
+        GNUNET_free (out);
+        goto END;
+      }
+      if (stats != NULL)
+        stats->change (stat_bytesReceived, size);
+      coreMP = GNUNET_new (GNUNET_TransportPacket);
+      coreMP->msg = out;
+      coreMP->size = size - sizeof(SMTPMessage);
+      coreMP->tsession = NULL;
+      coreMP->sender = mp->sender;
+#if DEBUG_SMTP
+      GNUNET_GE_LOG (ectx, GNUNET_GE_DEBUG | GNUNET_GE_REQUEST | GNUNET_GE_USER,
+                     "SMTP message passed to the core.\n");
+#endif
+
+      core_api->receive (coreMP);
+    }
+END:
+#if DEBUG_SMTP
+    GNUNET_GE_LOG (ectx, GNUNET_GE_DEBUG | GNUNET_GE_REQUEST | GNUNET_GE_USER,
+                   "SMTP message processed.\n");
+#endif
+    if (fdes != NULL)
+      fclose (fdes);
+  }
+  GNUNET_free (line);
+  return NULL;
+}
+
+
+/* *************** API implementation *************** */
+
+/**
+ * Verify that a hello-Message is correct (a node is reachable at that
+ * address). Since the reply will be asynchronous, a method must be
+ * called on success.
+ *
+ * @param hello the hello message to verify
+ *        (the signature/crc have been verified before)
+ * @return GNUNET_OK on success, GNUNET_SYSERR on error
+ */
+static int
+api_verify_hello (const GNUNET_MessageHello *hello)
+{
+  const EmailAddress *maddr;
+
+  maddr = (const EmailAddress *) &hello[1];
+  if ((ntohs (hello->header.size) !=
+       sizeof(GNUNET_MessageHello) + ntohs (hello->senderAddressSize)) ||
+      (maddr->senderAddress
+       [ntohs (hello->senderAddressSize) - 1 - FILTER_STRING_SIZE] != '\0'))
+  {
+    GNUNET_GE_BREAK (ectx, 0);
+    return GNUNET_SYSERR;       /* obviously invalid */
+  }
+  if (NULL == strstr (maddr->filter, ": "))
+    return GNUNET_SYSERR;
+  return GNUNET_OK;
+}
+
+
+/**
+ * Create a hello-Message for the current node. The hello is created
+ * without signature and without a timestamp. The GNUnet core will
+ * GNUNET_RSA_sign the message and add an expiration time.
+ *
+ * @return hello on success, NULL on error
+ */
+static GNUNET_MessageHello *
+api_create_hello ()
+{
+  GNUNET_MessageHello *msg;
+  char *filter;
+  EmailAddress *haddr;
+  int i;
+
+  GNUNET_GC_get_configuration_value_string (core_api->cfg, "SMTP", "FILTER",
+                                            "X-mailer: GNUnet", &filter);
+  if (NULL == strstr (filter, ": "))
+  {
+    GNUNET_GE_LOG (ectx, GNUNET_GE_WARNING | GNUNET_GE_BULK | GNUNET_GE_USER,
+                   _ ("SMTP filter string to invalid, lacks ': '\n"));
+    GNUNET_free (filter);
+    return NULL;
+  }
+
+  if (strlen (filter) > FILTER_STRING_SIZE)
+  {
+    filter[FILTER_STRING_SIZE] = '\0';
+    GNUNET_GE_LOG (ectx, GNUNET_GE_WARNING | GNUNET_GE_BULK | GNUNET_GE_USER,
+                   _ ("SMTP filter string to long, capped to `%s'\n"), filter);
+  }
+  i = (strlen (email) + 8) & (~7);       /* make multiple of 8 */
+  msg =
+    GNUNET_malloc (sizeof(GNUNET_MessageHello) + sizeof(EmailAddress) + i);
+  memset (msg, 0, sizeof(GNUNET_MessageHello) + sizeof(EmailAddress) + i);
+  haddr = (EmailAddress *) &msg[1];
+  memset (&haddr->filter[0], 0, FILTER_STRING_SIZE);
+  strcpy (&haddr->filter[0], filter);
+  GNUNET_memcpy (&haddr->senderAddress[0], email, strlen (email) + 1);
+  msg->senderAddressSize = htons (strlen (email) + 1 + sizeof(EmailAddress));
+  msg->protocol = htons (GNUNET_TRANSPORT_PROTOCOL_NUMBER_SMTP);
+  msg->MTU = htonl (smtpAPI.mtu);
+  msg->header.size = htons (GNUNET_sizeof_hello (msg));
+  if (api_verify_hello (msg) == GNUNET_SYSERR)
+    GNUNET_GE_ASSERT (ectx, 0);
+  GNUNET_free (filter);
+  return msg;
+}
+
+
+struct GetMessageClosure
+{
+  unsigned int esize;
+  unsigned int pos;
+  char *ebody;
+};
+
+static const char *
+get_message (void **buf, int *len, void *cls)
+{
+  struct GetMessageClosure *gmc = cls;
+
+  *buf = NULL;
+  if (len == NULL)
+  {
+    gmc->pos = 0;
+    return NULL;
+  }
+  if (gmc->pos == gmc->esize)
+    return NULL;                /* done */
+  *len = gmc->esize;
+  gmc->pos = gmc->esize;
+  return gmc->ebody;
+}
+
+
+/**
+ * Send a message to the specified remote node.
+ *
+ * @param tsession the GNUNET_MessageHello identifying the remote node
+ * @param msg what to send
+ * @param size the size of the message
+ * @param important is this message important enough to override typical limits?
+ * @return GNUNET_SYSERR on error, GNUNET_OK on success
+ */
+static int
+api_send (GNUNET_TSession *tsession, const void *msg, const unsigned int size,
+          int important)
+{
+  const GNUNET_MessageHello *hello;
+  const EmailAddress *haddr;
+  char *m;
+  char *filter;
+  char *fvalue;
+  SMTPMessage *mp;
+  struct GetMessageClosure gm_cls;
+  smtp_session_t session;
+  smtp_message_t message;
+  smtp_recipient_t recipient;
+
+#define EBUF_LEN 128
+  char ebuf[EBUF_LEN];
+  GNUNET_CronTime now;
+
+  if (smtp_shutdown == GNUNET_YES)
+    return GNUNET_SYSERR;
+  if ((size == 0) || (size > smtpAPI.mtu))
+  {
+    GNUNET_GE_BREAK (ectx, 0);
+    return GNUNET_SYSERR;
+  }
+  now = GNUNET_get_time ();
+  if ((important != GNUNET_YES) &&
+      ( ((now - last_transmission) * rate_limit) < GNUNET_CRON_HOURS) )
+    return GNUNET_NO;           /* rate too high */
+  last_transmission = now;
+
+  hello = (const GNUNET_MessageHello *) tsession->internal;
+  if (hello == NULL)
+    return GNUNET_SYSERR;
+  GNUNET_mutex_lock (lock);
+  session = smtp_create_session ();
+  if (session == NULL)
+  {
+    GNUNET_GE_LOG (ectx,
+                   GNUNET_GE_ERROR | GNUNET_GE_ADMIN | GNUNET_GE_USER
+                   | GNUNET_GE_IMMEDIATE, _ ("SMTP: `%s' failed: %s.\n"),
+                   "smtp_create_session", smtp_strerror (smtp_errno (), ebuf,
+                                                         EBUF_LEN));
+    GNUNET_mutex_unlock (lock);
+    return GNUNET_SYSERR;
+  }
+  if (0 == smtp_set_server (session, smtp_server_name))
+  {
+    GNUNET_GE_LOG (ectx,
+                   GNUNET_GE_ERROR | GNUNET_GE_ADMIN | GNUNET_GE_USER
+                   | GNUNET_GE_IMMEDIATE, _ ("SMTP: `%s' failed: %s.\n"),
+                   "smtp_set_server", smtp_strerror (smtp_errno (), ebuf,
+                                                     EBUF_LEN));
+    smtp_destroy_session (session);
+    GNUNET_mutex_unlock (lock);
+    return GNUNET_SYSERR;
+  }
+  haddr = (const EmailAddress *) &hello[1];
+  message = smtp_add_message (session);
+  if (message == NULL)
+  {
+    GNUNET_GE_LOG (ectx,
+                   GNUNET_GE_WARNING | GNUNET_GE_ADMIN | GNUNET_GE_USER
+                   | GNUNET_GE_BULK, _ ("SMTP: `%s' failed: %s.\n"),
+                   "smtp_add_message", smtp_strerror (smtp_errno (), ebuf,
+                                                      EBUF_LEN));
+    smtp_destroy_session (session);
+    GNUNET_mutex_unlock (lock);
+    return GNUNET_SYSERR;
+  }
+  smtp_set_header (message, "To", NULL, haddr->senderAddress);
+  smtp_set_header (message, "From", NULL, email);
+
+  filter = GNUNET_strdup (haddr->filter);
+  fvalue = strstr (filter, ": ");
+  GNUNET_GE_ASSERT (NULL, NULL != fvalue);
+  fvalue[0] = '\0';
+  fvalue += 2;
+  if (0 == smtp_set_header (message, filter, fvalue))
+  {
+    GNUNET_GE_LOG (ectx,
+                   GNUNET_GE_WARNING | GNUNET_GE_ADMIN | GNUNET_GE_USER
+                   | GNUNET_GE_BULK, _ ("SMTP: `%s' failed: %s.\n"),
+                   "smtp_set_header", smtp_strerror (smtp_errno (), ebuf,
+                                                     EBUF_LEN));
+    smtp_destroy_session (session);
+    GNUNET_mutex_unlock (lock);
+    GNUNET_free (filter);
+    return GNUNET_SYSERR;
+  }
+  GNUNET_free (filter);
+  m = GNUNET_malloc (size + sizeof(SMTPMessage));
+  GNUNET_memcpy (m, msg, size);
+  mp = (SMTPMessage *) &m[size];
+  mp->header.size = htons (size + sizeof(SMTPMessage));
+  mp->header.type = htons (0);
+  mp->sender = *core_api->my_identity;
+  gm_cls.ebody = NULL;
+  gm_cls.pos = 0;
+  gm_cls.esize = GNUNET_STRINGS_base64_encode (m, size + sizeof(SMTPMessage),
+                                               &gm_cls.ebody);
+  GNUNET_free (m);
+  if (0 == smtp_size_set_estimate (message, gm_cls.esize))
+  {
+    GNUNET_GE_LOG (ectx,
+                   GNUNET_GE_WARNING | GNUNET_GE_ADMIN | GNUNET_GE_USER
+                   | GNUNET_GE_BULK, _ ("SMTP: `%s' failed: %s.\n"),
+                   "smtp_size_set_estimate", smtp_strerror (smtp_errno (), ebuf,
+                                                            EBUF_LEN));
+  }
+  if (0 == smtp_set_messagecb (message, &get_message, &gm_cls))
+  {
+    GNUNET_GE_LOG (ectx,
+                   GNUNET_GE_WARNING | GNUNET_GE_ADMIN | GNUNET_GE_USER
+                   | GNUNET_GE_BULK, _ ("SMTP: `%s' failed: %s.\n"),
+                   "smtp_set_messagecb", smtp_strerror (smtp_errno (), ebuf,
+                                                        EBUF_LEN));
+    smtp_destroy_session (session);
+    GNUNET_mutex_unlock (lock);
+    GNUNET_free (gm_cls.ebody);
+    return GNUNET_SYSERR;
+  }
+  recipient = smtp_add_recipient (message, haddr->senderAddress);
+  if (recipient == NULL)
+  {
+    GNUNET_GE_LOG (ectx,
+                   GNUNET_GE_WARNING | GNUNET_GE_ADMIN | GNUNET_GE_USER
+                   | GNUNET_GE_BULK, _ ("SMTP: `%s' failed: %s.\n"),
+                   "smtp_add_recipient", smtp_strerror (smtp_errno (), ebuf,
+                                                        EBUF_LEN));
+    smtp_destroy_session (session);
+    GNUNET_mutex_unlock (lock);
+    return GNUNET_SYSERR;
+  }
+  if (0 == smtp_start_session (session))
+  {
+    GNUNET_GE_LOG (ectx,
+                   GNUNET_GE_WARNING | GNUNET_GE_ADMIN | GNUNET_GE_USER
+                   | GNUNET_GE_BULK, _ ("SMTP: `%s' failed: %s.\n"),
+                   "smtp_start_session", smtp_strerror (smtp_errno (), ebuf,
+                                                        EBUF_LEN));
+    smtp_destroy_session (session);
+    GNUNET_mutex_unlock (lock);
+    GNUNET_free (gm_cls.ebody);
+    return GNUNET_SYSERR;
+  }
+  if (stats != NULL)
+    stats->change (stat_bytesSent, size);
+  if (core_api->load_monitor != NULL)
+    GNUNET_network_monitor_notify_transmission (core_api->load_monitor,
+                                                GNUNET_ND_UPLOAD, gm_cls.esize);
+  smtp_message_reset_status (message);   /* this is needed to plug a 28-byte/message memory leak in libesmtp */
+  smtp_destroy_session (session);
+  GNUNET_mutex_unlock (lock);
+  GNUNET_free (gm_cls.ebody);
+  return GNUNET_OK;
+}
+
+
+/**
+ * Establish a connection to a remote node.
+ * @param hello the hello-Message for the target node
+ * @param tsessionPtr the session handle that is to be set
+ * @param may_reuse can we re-use an existing connection?
+ * @return GNUNET_OK on success, GNUNET_SYSERR if the operation failed
+ */
+static int
+api_connect (const GNUNET_MessageHello *hello, GNUNET_TSession **tsessionPtr,
+             int may_reuse)
+{
+  GNUNET_TSession *tsession;
+
+  tsession = GNUNET_new (GNUNET_TSession);
+  tsession->internal = GNUNET_malloc (GNUNET_sizeof_hello (hello));
+  tsession->peer = hello->senderIdentity;
+  GNUNET_memcpy (tsession->internal, hello, GNUNET_sizeof_hello (hello));
+  tsession->ttype = smtpAPI.protocol_number;
+  (*tsessionPtr) = tsession;
+  return GNUNET_OK;
+}
+
+
+/**
+ * Disconnect from a remote node.
+ *
+ * @param tsession the session that is closed
+ * @return GNUNET_OK on success, GNUNET_SYSERR if the operation failed
+ */
+static int
+api_disconnect (GNUNET_TSession *tsession)
+{
+  if (tsession != NULL)
+  {
+    if (tsession->internal != NULL)
+      GNUNET_free (tsession->internal);
+    GNUNET_free (tsession);
+  }
+  return GNUNET_OK;
+}
+
+
+/**
+ * Start the server process to receive inbound traffic.
+ * @return GNUNET_OK on success, GNUNET_SYSERR if the operation failed
+ */
+static int
+api_start_transport_server ()
+{
+  smtp_shutdown = GNUNET_NO;
+  /* initialize SMTP network */
+  dispatchThread = GNUNET_thread_create (&listenAndDistribute, NULL, 1024 * 4);
+  if (dispatchThread == NULL)
+  {
+    GNUNET_GE_DIE_STRERROR (ectx,
+                            GNUNET_GE_ADMIN | GNUNET_GE_BULK | GNUNET_GE_FATAL,
+                            "pthread_create");
+    return GNUNET_SYSERR;
+  }
+  return GNUNET_OK;
+}
+
+
+/**
+ * Shutdown the server process (stop receiving inbound traffic). Maybe
+ * restarted later!
+ */
+static int
+api_stop_transport_server ()
+{
+  void *unused;
+
+  smtp_shutdown = GNUNET_YES;
+  GNUNET_thread_stop_sleep (dispatchThread);
+  GNUNET_thread_join (dispatchThread, &unused);
+  return GNUNET_OK;
+}
+
+
+/**
+ * Convert SMTP hello to an IP address (always fails).
+ */
+static int
+api_hello_to_address (const GNUNET_MessageHello *hello, void **sa,
+                      unsigned int *sa_len)
+{
+  return GNUNET_SYSERR;
+}
+
+
+/**
+ * Always fails.
+ */
+static int
+api_associate (GNUNET_TSession *tsession)
+{
+  return GNUNET_SYSERR;         /* SMTP connections can never be associated */
+}
+
+
+/**
+ * Always succeeds (for now; we should look at adding
+ * frequency limits to SMTP in the future!).
+ */
+static int
+api_test_would_try (GNUNET_TSession *tsession, unsigned int size,
+                    int important)
+{
+  return GNUNET_OK;             /* we always try... */
+}
+
+
+/**
+ * The exported method. Makes the core api available via a global and
+ * returns the smtp transport API.
+ */
+GNUNET_TransportAPI *
+inittransport_smtp (struct GNUNET_CoreAPIForTransport *core)
+{
+  unsigned long long mtu;
+  struct sigaction sa;
+
+  core_api = core;
+  ectx = core->ectx;
+  if (! GNUNET_GC_have_configuration_value (core_api->cfg, "SMTP", "EMAIL"))
+  {
+    GNUNET_GE_LOG (ectx, GNUNET_GE_ERROR | GNUNET_GE_BULK | GNUNET_GE_USER,
+                   _
+                   (
+                     "No email-address specified, can not start SMTP transport.\n"));
+    return NULL;
+  }
+  GNUNET_GC_get_configuration_value_number (core_api->cfg, "SMTP", "MTU", 1200,
+                                            SMTP_MESSAGE_SIZE,
+                                            SMTP_MESSAGE_SIZE, &mtu);
+  GNUNET_GC_get_configuration_value_number (core_api->cfg, "SMTP", "RATELIMIT",
+                                            0, 0, 1024 * 1024, &rate_limit);
+  stats = core_api->service_request ("stats");
+  if (stats != NULL)
+  {
+    stat_bytesReceived =
+      stats->create (gettext_noop ("# bytes received via SMTP"));
+    stat_bytesSent = stats->create (gettext_noop ("# bytes sent via SMTP"));
+    stat_bytesDropped =
+      stats->create (gettext_noop ("# bytes dropped by SMTP (outgoing)"));
+  }
+  GNUNET_GC_get_configuration_value_filename (core_api->cfg, "SMTP", "PIPE",
+                                              &pipename);
+  unlink (pipename);
+  if (0 != mkfifo (pipename, S_IWUSR | S_IRUSR | S_IWGRP | S_IWOTH))
+  {
+    GNUNET_GE_LOG_STRERROR (ectx,
+                            GNUNET_GE_ADMIN | GNUNET_GE_BULK | GNUNET_GE_FATAL,
+                            "mkfifo");
+    GNUNET_free (pipename);
+    core_api->service_release (stats);
+    stats = NULL;
+    return NULL;
+  }
+  /* we need to allow the mailer program to send us messages;
+   * easiest done by giving it write permissions (see Mantis #1142) */
+  if (0 != chmod (pipename, S_IWUSR | S_IRUSR | S_IWGRP | S_IWOTH))
+    GNUNET_GE_LOG_STRERROR (ectx,
+                            GNUNET_GE_ADMIN | GNUNET_GE_BULK
+                            | GNUNET_GE_WARNING, "chmod");
+  GNUNET_GC_get_configuration_value_string (core_api->cfg, "SMTP", "EMAIL",
+                                            NULL,
+                                            &email);
+  lock = GNUNET_mutex_create (GNUNET_NO);
+  GNUNET_GC_get_configuration_value_string (core_api->cfg, "SMTP", "SERVER",
+                                            "localhost:25", &smtp_server_name);
+  sa.sa_handler = SIG_IGN;
+  sigemptyset (&sa.sa_mask);
+  sa.sa_flags = 0;
+  sigaction (SIGPIPE, &sa, &old_handler);
+
+  smtpAPI.protocol_number = GNUNET_TRANSPORT_PROTOCOL_NUMBER_SMTP;
+  smtpAPI.mtu = mtu - sizeof(SMTPMessage);
+  smtpAPI.cost = 50;
+  smtpAPI.hello_verify = &api_verify_hello;
+  smtpAPI.hello_create = &api_create_hello;
+  smtpAPI.connect = &api_connect;
+  smtpAPI.send = &api_send;
+  smtpAPI.associate = &api_associate;
+  smtpAPI.disconnect = &api_disconnect;
+  smtpAPI.server_start = &api_start_transport_server;
+  smtpAPI.server_stop = &api_stop_transport_server;
+  smtpAPI.hello_to_address = &api_hello_to_address;
+  smtpAPI.send_now_test = &api_test_would_try;
+  return &smtpAPI;
+}
+
+
+void
+donetransport_smtp ()
+{
+  sigaction (SIGPIPE, &old_handler, NULL);
+  GNUNET_free (smtp_server_name);
+  if (stats != NULL)
+  {
+    core_api->service_release (stats);
+    stats = NULL;
+  }
+  GNUNET_mutex_destroy (lock);
+  lock = NULL;
+  unlink (pipename);
+  GNUNET_free (pipename);
+  pipename = NULL;
+  GNUNET_free (email);
+  email = NULL;
+}
+
+
+/* end of smtp.c */
diff --git a/src/transport/profile_transport.sh b/src/transport/profile_transport.sh
new file mode 100755
index 0000000000000000000000000000000000000000..0e6935fc7f593321958a56a1dfb4669e3c5c0e5c
--- /dev/null
+++ b/src/transport/profile_transport.sh
@@ -0,0 +1,18 @@
+#!/bin/sh
+
+C_ITERATIONS=5
+C_MESSAGE_DELTA=10
+C_MESSAGE_START=10
+C_MESSAGE_END=2000
+
+#for i in {$C_MESSAGE_START..$C_MESSAGE_END..$C_MESSAGE_DELTA}
+#  do
+#     echo "Welcome $i times"
+# done
+
+
+for $((cur=$C_MESSAGE_START; cur<=$C_MESSAGE_END; cur = cur + $C_MESSAGE_DELTA))
+{
+	./gnunet-transport-profiler -p  NSGWRTMHG2YJK9KZSTEWKJ5TK20AGRDBWHFA1ZNKKZ7T360MZ8S0 -s -c perf_https_peer1.conf -n 20240 -m $cur -i 4
+	sleep 1
+}
diff --git a/src/transport/test_communicator_basic.c b/src/transport/test_communicator_basic.c
index 290167960e0bf699a583974fad8b5c56f90bfdd4..e3573ac2c42d7d9ce35572034bc9028c295369e8 100644
--- a/src/transport/test_communicator_basic.c
+++ b/src/transport/test_communicator_basic.c
@@ -124,6 +124,25 @@ communicator_available_cb (void *cls,
        address_prefix);
 }
 
+static void
+open_queue (void *cls)
+{
+  char *address = cls;
+
+  if (NULL != tc_hs[PEER_A]->c_mq)
+  {
+    queue_est = GNUNET_YES;
+    GNUNET_TRANSPORT_TESTING_transport_communicator_open_queue (tc_hs[PEER_A],
+                                                                &peer_id[PEER_B],
+                                                                address);
+  }
+  else
+  {
+    GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_SECONDS,
+                                  &open_queue,
+                                  address);
+  }
+}
 
 static void
 add_address_cb (void *cls,
@@ -144,10 +163,7 @@ add_address_cb (void *cls,
   if ((0 == strcmp ((char*) cls, cfg_peers_name[PEER_B])) &&
       (GNUNET_NO == queue_est))
   {
-    queue_est = GNUNET_YES;
-    GNUNET_TRANSPORT_TESTING_transport_communicator_open_queue (tc_hs[PEER_A],
-                                                                &peer_id[PEER_B],
-                                                                address);
+    open_queue (address);
   }
 }
 
@@ -205,7 +221,7 @@ make_payload (size_t payload_size)
   GNUNET_assert (payload_size >= 8); // So that out timestamp fits
   ts = GNUNET_TIME_absolute_get ();
   ts_n = GNUNET_TIME_absolute_hton (ts);
-  memset (payload, 0, payload_size);
+  memset (payload, 'a', payload_size);
   memcpy (payload, &ts_n, sizeof (struct GNUNET_TIME_AbsoluteNBO));
   return payload;
 }
@@ -224,8 +240,8 @@ latency_timeout (void *cls)
   }
 
   LOG (GNUNET_ERROR_TYPE_ERROR,
-              "Latency too high. Test failed. (Phase: %d. Sent: %lu, Received: %lu)\n",
-              phase, num_sent, num_received);
+       "Latency too high. Test failed. (Phase: %d. Sent: %lu, Received: %lu)\n",
+       phase, num_sent, num_received);
   ret = 2;
   GNUNET_SCHEDULER_shutdown ();
 }
@@ -351,8 +367,9 @@ add_queue_cb (void *cls,
        "Queue established, starting test...\n");
   start_short = GNUNET_TIME_absolute_get ();
   my_tc = tc_h;
-  if (0 != mtu)
-    long_message_size = mtu - 4; /* Dummy message header overhead */
+  if (0 != mtu) /* Message header overhead */
+    long_message_size = mtu - sizeof(struct GNUNET_TRANSPORT_SendMessageTo)
+                        - sizeof(struct GNUNET_MessageHeader);
   else
     long_message_size = LONG_MESSAGE_SIZE;
   phase = TP_BURST_SHORT;
@@ -403,7 +420,7 @@ incoming_message_cb (void *cls,
   if (0 != strcmp ((char*) cls, cfg_peers_name[NUM_PEERS - 1]))
   {
     LOG (GNUNET_ERROR_TYPE_WARNING,
-                "unexpected receiver...\n");
+         "unexpected receiver...\n");
     return;
   }
   /* Reset timeout */
@@ -422,18 +439,18 @@ incoming_message_cb (void *cls,
       if (num_received == BURST_PACKETS)
       {
         LOG (GNUNET_ERROR_TYPE_MESSAGE,
-                    "Short size packet test done.\n");
+             "Short size packet test done.\n");
         char *goodput = GNUNET_STRINGS_byte_size_fancy ((SHORT_MESSAGE_SIZE
                                                          * num_received * 1000
                                                          * 1000)
                                                         / duration.rel_value_us);
         LOG (GNUNET_ERROR_TYPE_MESSAGE,
-                    "%lu/%lu packets in %llu us (%s/s) -- avg latency: %llu us\n",
-                    (unsigned long) num_received,
-                    (unsigned long) num_sent,
-                    (unsigned long long) duration.rel_value_us,
-                    goodput,
-                    (unsigned long long) avg_latency);
+             "%lu/%lu packets in %llu us (%s/s) -- avg latency: %llu us\n",
+             (unsigned long) num_received,
+             (unsigned long) num_sent,
+             (unsigned long long) duration.rel_value_us,
+             goodput,
+             (unsigned long long) avg_latency);
         GNUNET_free (goodput);
         start_long = GNUNET_TIME_absolute_get ();
         phase = TP_BURST_LONG;
@@ -449,7 +466,7 @@ incoming_message_cb (void *cls,
       if (long_message_size != payload_len)
       {
         LOG (GNUNET_ERROR_TYPE_WARNING,
-                    "Ignoring packet with wrong length\n");
+             "Ignoring packet with wrong length\n");
         return; // Ignore
       }
       num_received++;
@@ -458,19 +475,19 @@ incoming_message_cb (void *cls,
       if (num_received == BURST_PACKETS)
       {
         LOG (GNUNET_ERROR_TYPE_MESSAGE,
-                    "Long size packet test done.\n");
+             "Long size packet test done.\n");
         char *goodput = GNUNET_STRINGS_byte_size_fancy ((long_message_size
                                                          * num_received * 1000
                                                          * 1000)
                                                         / duration.rel_value_us);
 
         LOG (GNUNET_ERROR_TYPE_MESSAGE,
-                    "%lu/%lu packets in %llu us (%s/s) -- avg latency: %llu us\n",
-                    (unsigned long) num_received,
-                    (unsigned long) num_sent,
-                    (unsigned long long) duration.rel_value_us,
-                    goodput,
-                    (unsigned long long) avg_latency);
+             "%lu/%lu packets in %llu us (%s/s) -- avg latency: %llu us\n",
+             (unsigned long) num_received,
+             (unsigned long) num_sent,
+             (unsigned long long) duration.rel_value_us,
+             goodput,
+             (unsigned long long) avg_latency);
         GNUNET_free (goodput);
         ack = 0;
         phase = TP_SIZE_CHECK;
@@ -493,12 +510,12 @@ incoming_message_cb (void *cls,
       if (num_received >= (max_size) / 10)
       {
         LOG (GNUNET_ERROR_TYPE_MESSAGE,
-                    "Size packet test done.\n");
+             "Size packet test done.\n");
         LOG (GNUNET_ERROR_TYPE_MESSAGE,
-                    "%lu/%lu packets -- avg latency: %llu us\n",
-                    (unsigned long) num_received,
-                    (unsigned long) num_sent,
-                    (unsigned long long) avg_latency);
+             "%lu/%lu packets -- avg latency: %llu us\n",
+             (unsigned long) num_received,
+             (unsigned long) num_sent,
+             (unsigned long long) avg_latency);
         num_received = 0;
         num_sent = 0;
         avg_latency = 0;
@@ -511,7 +528,7 @@ incoming_message_cb (void *cls,
           break;
         }
         LOG (GNUNET_ERROR_TYPE_DEBUG,
-                    "Finished\n");
+             "Finished\n");
         GNUNET_SCHEDULER_shutdown ();
       }
       break;
@@ -587,6 +604,7 @@ main (int argc,
   GNUNET_asprintf (&communicator_binary,
                    "gnunet-communicator-%s",
                    communicator_name);
+
   if (GNUNET_OK !=
       GNUNET_log_setup ("test_communicator_basic",
                         "DEBUG",
@@ -640,11 +658,26 @@ main (int argc,
                                         &peer_id[i].public_key);
     GNUNET_free (private_key);
     LOG (GNUNET_ERROR_TYPE_INFO,
-                "Identity of peer %u is %s\n",
-                i,
-                GNUNET_i2s_full (&peer_id[i]));
+         "Identity of peer %u is %s\n",
+         i,
+         GNUNET_i2s_full (&peer_id[i]));
   }
   LOG (GNUNET_ERROR_TYPE_MESSAGE, "Starting test...\n");
+  LOG (GNUNET_ERROR_TYPE_DEBUG,
+       "argv[0]: %s\n",
+       argv[0]);
+  LOG (GNUNET_ERROR_TYPE_DEBUG,
+       "test_name: %s\n",
+       test_name);
+
+  LOG (GNUNET_ERROR_TYPE_DEBUG,
+       "communicator_name: %s\n",
+       communicator_name);
+
+  LOG (GNUNET_ERROR_TYPE_DEBUG,
+       "communicator_binary: %s\n",
+       communicator_binary);
+
   GNUNET_SCHEDULER_run (&run,
                         NULL);
   return ret;
diff --git a/src/transport/test_communicator_tcp_basic_peer1.conf b/src/transport/test_communicator_tcp_basic_peer1.conf
index d0293ff512532514ea35d2808d3316dd86e1d33f..c08737b7b5d3e7b35364e4907cfea428ba9e43f1 100644
--- a/src/transport/test_communicator_tcp_basic_peer1.conf
+++ b/src/transport/test_communicator_tcp_basic_peer1.conf
@@ -19,10 +19,15 @@ UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-service-transport_test_1.sock
 [nat]
 UNIXPATH = $GNUNET_TMP/test-communicator-unix-1/nat.sock
 
+[peerstore]
+UNIXPATH = $GNUNET_TMP/test-communicator-unix-1/peerstore.sock
+
 [communicator-unix]
 UNIXPATH = $GNUNET_RUNTIME_DIR/test_gnunet-communicator-unix_1.sock
 
 [communicator-tcp]
+#PREFIX = xterm -geometry 100x85 -T peer1 -e gdb --args
+#PREFIX = valgrind --leak-check=full --track-origins=yes
 BINDTO = 60002
 DISABLE_V6 = NO
 
diff --git a/src/transport/test_communicator_tcp_basic_peer2.conf b/src/transport/test_communicator_tcp_basic_peer2.conf
index 5b90505472c8376e70b4484ab2ecd23e765856ea..45b7e7844214dde2b80314723cd786f5c162753f 100644
--- a/src/transport/test_communicator_tcp_basic_peer2.conf
+++ b/src/transport/test_communicator_tcp_basic_peer2.conf
@@ -20,10 +20,15 @@ UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-service-transport_test_2.sock
 [nat]
 UNIXPATH = $GNUNET_TMP/test-communicator-unix-2/nat.sock
 
+[peerstore]
+UNIXPATH = $GNUNET_TMP/test-communicator-unix-2/peerstore.sock
+
 [communicator-unix]
 UNIXPATH = $GNUNET_RUNTIME_DIR/test_gnunet-communicator-unix_2.sock
 
 [communicator-tcp]
+#PREFIX = xterm -geometry 100x85 -T peer2 -e gdb --args
+#PREFIX = valgrind --leak-check=full --track-origins=yes 
 BINDTO = 60003
 DISABLE_V6 = NO
 
diff --git a/src/transport/test_communicator_tcp_rekey_peer1.conf b/src/transport/test_communicator_tcp_rekey_peer1.conf
index 18028cd4842c14b287744bf31ad186c6e83e62dd..901f415ef403eb828b28057ccc0941bcfe702065 100644
--- a/src/transport/test_communicator_tcp_rekey_peer1.conf
+++ b/src/transport/test_communicator_tcp_rekey_peer1.conf
@@ -20,10 +20,19 @@ UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-service-transport_test_1.sock
 UNIXPATH = $GNUNET_TMP/test-communicator-unix-1/nat.sock
 ENABLE_IPSCAN = YES
 
+[peerstore]
+UNIXPATH = $GNUNET_TMP/test-communicator-unix-1/peerstore.sock
+
+[resolver]
+PORT = 62089
+UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-service-resolver_test_1.sock
+
 [communicator-unix]
 UNIXPATH = $GNUNET_RUNTIME_DIR/test_gnunet-communicator-unix_1.sock
 
 [communicator-tcp]
+#PREFIX = xterm -geometry 100x85 -T peer1 -e gdb --args
+#PREFIX = valgrind --leak-check=full --track-origins=yes
 BINDTO = 60002
 DISABLE_V6 = YES
 REKEY_INTERVAL = 100ms
diff --git a/src/transport/test_communicator_tcp_rekey_peer2.conf b/src/transport/test_communicator_tcp_rekey_peer2.conf
index 7d7179578ff309cf9b153c6d2df452ad6aea40d6..643b037b24972f7ddc336e7666743561f87ed0a2 100644
--- a/src/transport/test_communicator_tcp_rekey_peer2.conf
+++ b/src/transport/test_communicator_tcp_rekey_peer2.conf
@@ -20,12 +20,21 @@ UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-service-transport_test_2.sock
 [nat]
 UNIXPATH = $GNUNET_TMP/test-communicator-unix-2/nat.sock
 
+[peerstore]
+UNIXPATH = $GNUNET_TMP/test-communicator-unix-2/peerstore.sock
+
+[resolver]
+PORT = 62090
+UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-service-resolver_test_2.sock
+
 [communicator-unix]
 UNIXPATH = $GNUNET_RUNTIME_DIR/test_gnunet-communicator-unix_2.sock
 
 [communicator-tcp]
+#PREFIX = xterm -geometry 100x85 -T peer2 -e gdb --args
+#PREFIX = valgrind --leak-check=full --track-origins=yes
 BINDTO = 60003
-DISABLE_V6 = YES
+DISABLE_V6 = NO
 REKEY_INTERVAL = 100ms
 
 [communicator-udp]
diff --git a/src/transport/test_communicator_udp_backchannel_peer1.conf b/src/transport/test_communicator_udp_backchannel_peer1.conf
index 0c595b77b1da723bbea3dd566a8aaa5d272932ce..b99a76d6c7e88fd25f15a50ccfef2b46f597fa82 100644
--- a/src/transport/test_communicator_udp_backchannel_peer1.conf
+++ b/src/transport/test_communicator_udp_backchannel_peer1.conf
@@ -20,6 +20,13 @@ UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-service-transport_test_1.sock
 UNIXPATH = $GNUNET_TMP/test-communicator-unix-1/nat.sock
 ENABLE_IPSCAN = YES
 
+[peerstore]
+UNIXPATH = $GNUNET_TMP/test-communicator-unix-1/peerstore.sock
+
+[resolver]
+PORT = 62089
+UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-service-resolver_test_1.sock
+
 [communicator-unix]
 UNIXPATH = $GNUNET_RUNTIME_DIR/test_gnunet-communicator-unix_1.sock
 
diff --git a/src/transport/test_communicator_udp_backchannel_peer2.conf b/src/transport/test_communicator_udp_backchannel_peer2.conf
index d29f37ec91181ad1fa519798fe1be5ae70bfb0c5..48bd54c8baaa5e887b65f7acf678ba82bd5b34ba 100644
--- a/src/transport/test_communicator_udp_backchannel_peer2.conf
+++ b/src/transport/test_communicator_udp_backchannel_peer2.conf
@@ -20,6 +20,13 @@ UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-service-transport_test_2.sock
 [nat]
 UNIXPATH = $GNUNET_TMP/test-communicator-unix-2/nat.sock
 
+[peerstore]
+UNIXPATH = $GNUNET_TMP/test-communicator-unix-2/peerstore.sock
+
+[resolver]
+PORT = 62090
+UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-service-resolver_test_2.sock
+
 [communicator-unix]
 UNIXPATH = $GNUNET_RUNTIME_DIR/test_gnunet-communicator-unix_2.sock
 
diff --git a/src/transport/test_communicator_udp_basic_peer1.conf b/src/transport/test_communicator_udp_basic_peer1.conf
index 4cfb6f72f73d93c42f1d9703b47d28f6acd89bb1..d53a55210620d0c6d3e82ee45f21b23aae2b2218 100644
--- a/src/transport/test_communicator_udp_basic_peer1.conf
+++ b/src/transport/test_communicator_udp_basic_peer1.conf
@@ -20,6 +20,13 @@ UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-service-transport_test_1.sock
 UNIXPATH = $GNUNET_TMP/test-communicator-unix-1/nat.sock
 ENABLE_IPSCAN = YES
 
+[peerstore]
+UNIXPATH = $GNUNET_TMP/test-communicator-unix-1/peerstore.sock
+
+[resolver]
+PORT = 62089
+UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-service-resolver_test_1.sock
+
 [communicator-udp]
 BINDTO = 60002
 DISABLE_V6 = YES
diff --git a/src/transport/test_communicator_udp_basic_peer2.conf b/src/transport/test_communicator_udp_basic_peer2.conf
index b9bed27563052805060a35af4fd774df52725c81..f05ebc5cb68051359d9bb00b36272cffd1666af9 100644
--- a/src/transport/test_communicator_udp_basic_peer2.conf
+++ b/src/transport/test_communicator_udp_basic_peer2.conf
@@ -20,6 +20,14 @@ UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-service-transport_test_2.sock
 [nat]
 UNIXPATH = $GNUNET_TMP/test-communicator-unix-2/nat.sock
 
+
+[peerstore]
+UNIXPATH = $GNUNET_TMP/test-communicator-unix-2/peerstore.sock
+
+[resolver]
+PORT = 62090
+UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-service-resolver_test_2.sock
+
 [communicator-udp]
 BINDTO = 60003
 DISABLE_V6 = YES
diff --git a/src/transport/test_communicator_udp_rekey_peer1.conf b/src/transport/test_communicator_udp_rekey_peer1.conf
index 18028cd4842c14b287744bf31ad186c6e83e62dd..e7161e488a0405d6558f23a62c44a01ac0604c70 100644
--- a/src/transport/test_communicator_udp_rekey_peer1.conf
+++ b/src/transport/test_communicator_udp_rekey_peer1.conf
@@ -20,6 +20,13 @@ UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-service-transport_test_1.sock
 UNIXPATH = $GNUNET_TMP/test-communicator-unix-1/nat.sock
 ENABLE_IPSCAN = YES
 
+[peerstore]
+UNIXPATH = $GNUNET_TMP/test-communicator-unix-1/peerstore.sock
+
+[resolver]
+PORT = 62089
+UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-service-resolver_test_1.sock
+
 [communicator-unix]
 UNIXPATH = $GNUNET_RUNTIME_DIR/test_gnunet-communicator-unix_1.sock
 
diff --git a/src/transport/test_communicator_udp_rekey_peer2.conf b/src/transport/test_communicator_udp_rekey_peer2.conf
index 7d7179578ff309cf9b153c6d2df452ad6aea40d6..8f175a4054d19e14a180df7f535a209cb89101cb 100644
--- a/src/transport/test_communicator_udp_rekey_peer2.conf
+++ b/src/transport/test_communicator_udp_rekey_peer2.conf
@@ -20,6 +20,13 @@ UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-service-transport_test_2.sock
 [nat]
 UNIXPATH = $GNUNET_TMP/test-communicator-unix-2/nat.sock
 
+[peerstore]
+UNIXPATH = $GNUNET_TMP/test-communicator-unix-2/peerstore.sock
+
+[resolver]
+PORT = 62090
+UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-service-resolver_test_2.sock
+
 [communicator-unix]
 UNIXPATH = $GNUNET_RUNTIME_DIR/test_gnunet-communicator-unix_2.sock
 
diff --git a/src/transport/test_communicator_unix_basic_peer1.conf b/src/transport/test_communicator_unix_basic_peer1.conf
index d5058800713054359811107099ae7a4fd794b713..8e9700108b779108a5cf05e3beb9fc01ee5bfb2a 100644
--- a/src/transport/test_communicator_unix_basic_peer1.conf
+++ b/src/transport/test_communicator_unix_basic_peer1.conf
@@ -20,7 +20,16 @@ UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-service-transport_test_1.sock
 UNIXPATH = $GNUNET_TMP/communicator-unix-1/nat.sock
 ENABLE_IPSCAN = YES
 
+[peerstore]
+UNIXPATH = $GNUNET_TMP/test-communicator-unix-1/peerstore.sock
+
+[resolver]
+PORT = 62089
+UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-service-resolver_test_1.sock
+
 [communicator-unix]
+#PREFIX = xterm -geometry 100x85 -T peer1 -e gdb --args
+#PREFIX = valgrind --leak-check=full --track-origins=yes
 UNIXPATH = $GNUNET_RUNTIME_DIR/communicator-unix-1.sock
 
 [communicator-tcp]
diff --git a/src/transport/test_communicator_unix_basic_peer2.conf b/src/transport/test_communicator_unix_basic_peer2.conf
index fe27ef1a690150ff1f5125b62407d8fdc634406d..c12cc91111b82fb0f25f1637a350f36c57c63823 100644
--- a/src/transport/test_communicator_unix_basic_peer2.conf
+++ b/src/transport/test_communicator_unix_basic_peer2.conf
@@ -20,7 +20,16 @@ UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-service-transport_test_2.sock
 [nat]
 UNIXPATH = $GNUNET_TMP/communicator-unix-2/nat.sock
 
+[peerstore]
+UNIXPATH = $GNUNET_TMP/test-communicator-unix-2/peerstore.sock
+
+[resolver]
+PORT = 62090
+UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-service-resolver_test_2.sock
+
 [communicator-unix]
+#PREFIX = xterm -geometry 100x85 -T peer2 -e gdb --args
+#PREFIX = valgrind --leak-check=full --track-origins=yes
 UNIXPATH = $GNUNET_RUNTIME_DIR/communicator-unix-2.sock
 
 [communicator-tcp]
diff --git a/src/transport/test_transport_address_switch_http_peer1.conf b/src/transport/test_transport_address_switch_http_peer1.conf
new file mode 100644
index 0000000000000000000000000000000000000000..b48c5f47f4f913644cfd203f4e86ceedf41bb853
--- /dev/null
+++ b/src/transport/test_transport_address_switch_http_peer1.conf
@@ -0,0 +1,26 @@
+@INLINE@ template_cfg_peer1.conf
+[PATHS]
+GNUNET_TEST_HOME = $GNUNET_TMP/test-transport/api-tcp-p1/
+
+[ats]
+UNSPECIFIED_QUOTA_IN = 8 KiB
+UNSPECIFIED_QUOTA_OUT = 8 KiB
+# LOOPBACK
+LOOPBACK_QUOTA_IN = 8 KiB
+LOOPBACK_QUOTA_OUT = 8 KiB
+# LAN
+LAN_QUOTA_IN = 8 KiB
+LAN_QUOTA_OUT = 8 KiB
+# WAN
+WAN_QUOTA_IN = 8 KiB
+WAN_QUOTA_OUT = 8 KiB
+# WLAN
+WLAN_QUOTA_IN = 8 KiB
+WLAN_QUOTA_OUT = 8 KiB
+# BLUETOOTH
+BLUETOOTH_QUOTA_IN = 8 KiB
+BLUETOOTH_QUOTA_OUT = 8 KiB
+
+[transport]
+PLUGINS = http_server http_client
+
diff --git a/src/transport/test_transport_address_switch_http_peer2.conf b/src/transport/test_transport_address_switch_http_peer2.conf
new file mode 100644
index 0000000000000000000000000000000000000000..be8fb506c6c97f1e751c0eb009d868430a7c6956
--- /dev/null
+++ b/src/transport/test_transport_address_switch_http_peer2.conf
@@ -0,0 +1,26 @@
+@INLINE@ template_cfg_peer2.conf
+[PATHS]
+GNUNET_TEST_HOME = $GNUNET_TMP/test-transport/api-tcp-p2/
+
+[ats]
+UNSPECIFIED_QUOTA_IN = 8 KiB
+UNSPECIFIED_QUOTA_OUT = 8 KiB
+# LOOPBACK
+LOOPBACK_QUOTA_IN = 8 KiB
+LOOPBACK_QUOTA_OUT = 8 KiB
+# LAN
+LAN_QUOTA_IN = 8 KiB
+LAN_QUOTA_OUT = 8 KiB
+# WAN
+WAN_QUOTA_IN = 8 KiB
+WAN_QUOTA_OUT = 8 KiB
+# WLAN
+WLAN_QUOTA_IN = 8 KiB
+WLAN_QUOTA_OUT = 8 KiB
+# BLUETOOTH
+BLUETOOTH_QUOTA_IN = 8 KiB
+BLUETOOTH_QUOTA_OUT = 8 KiB
+
+[transport]
+PLUGINS = http_client http_server
+
diff --git a/src/transport/test_transport_address_switch_https_peer1.conf b/src/transport/test_transport_address_switch_https_peer1.conf
new file mode 100644
index 0000000000000000000000000000000000000000..1f921013037ae3fc542c15bffb08c5936cd117c2
--- /dev/null
+++ b/src/transport/test_transport_address_switch_https_peer1.conf
@@ -0,0 +1,44 @@
+@INLINE@ template_cfg_peer1.conf
+[PATHS]
+GNUNET_TEST_HOME = $GNUNET_TMP/test-transport/api-tcp-p1/
+
+[ats]
+UNSPECIFIED_QUOTA_IN = 8 KiB
+UNSPECIFIED_QUOTA_OUT = 8 KiB
+# LOOPBACK
+LOOPBACK_QUOTA_IN = 8 KiB
+LOOPBACK_QUOTA_OUT = 8 KiB
+# LAN
+LAN_QUOTA_IN = 8 KiB
+LAN_QUOTA_OUT = 8 KiB
+# WAN
+WAN_QUOTA_IN = 8 KiB
+WAN_QUOTA_OUT = 8 KiB
+# WLAN
+WLAN_QUOTA_IN = 8 KiB
+WLAN_QUOTA_OUT = 8 KiB
+# BLUETOOTH
+BLUETOOTH_QUOTA_IN = 8 KiB
+BLUETOOTH_QUOTA_OUT = 8 KiB
+
+[arm]
+PORT = 12005
+UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p1-service-arm.sock
+
+[statistics]
+PORT = 12004
+UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p1-service-statistics.sock
+
+[resolver]
+PORT = 12003
+UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p1-service-resolver.sock
+
+[peerinfo]
+PORT = 12002
+UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p1-service-peerinfo.sock
+
+[transport]
+PORT = 12001
+UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p1-service-transport.sock
+PLUGINS = https_client https_server
+
diff --git a/src/transport/test_transport_address_switch_https_peer2.conf b/src/transport/test_transport_address_switch_https_peer2.conf
new file mode 100644
index 0000000000000000000000000000000000000000..c58839868d30e00a1079423fcf629ca6dd48b8d8
--- /dev/null
+++ b/src/transport/test_transport_address_switch_https_peer2.conf
@@ -0,0 +1,44 @@
+@INLINE@ template_cfg_peer2.conf
+[PATHS]
+GNUNET_TEST_HOME = $GNUNET_TMP/test-transport/api-tcp-p2/
+
+[ats]
+UNSPECIFIED_QUOTA_IN = 8 KiB
+UNSPECIFIED_QUOTA_OUT = 8 KiB
+# LOOPBACK
+LOOPBACK_QUOTA_IN = 8 KiB
+LOOPBACK_QUOTA_OUT = 8 KiB
+# LAN
+LAN_QUOTA_IN = 8 KiB
+LAN_QUOTA_OUT = 8 KiB
+# WAN
+WAN_QUOTA_IN = 8 KiB
+WAN_QUOTA_OUT = 8 KiB
+# WLAN
+WLAN_QUOTA_IN = 8 KiB
+WLAN_QUOTA_OUT = 8 KiB
+# BLUETOOTH
+BLUETOOTH_QUOTA_IN = 8 KiB
+BLUETOOTH_QUOTA_OUT = 8 KiB
+
+[arm]
+PORT = 12014
+UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p2-service-arm.sock
+
+[statistics]
+PORT = 12013
+UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p2-service-statistics.sock
+
+[resolver]
+PORT = 12012
+UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p2-service-resolver.sock
+
+[peerinfo]
+PORT = 12011
+UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p2-service-peerinfo.sock
+
+[transport]
+PORT = 12010
+PLUGINS = https_client https_server
+UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p2-service-transport.sock
+
diff --git a/src/transport/test_transport_address_switch_tcp_peer1.conf b/src/transport/test_transport_address_switch_tcp_peer1.conf
new file mode 100644
index 0000000000000000000000000000000000000000..cfcbfe41c29ce70857d7ad0597a68814e71fa276
--- /dev/null
+++ b/src/transport/test_transport_address_switch_tcp_peer1.conf
@@ -0,0 +1,48 @@
+@INLINE@ template_cfg_peer1.conf
+[PATHS]
+GNUNET_TEST_HOME = $GNUNET_TMP/test-transport/api-tcp-p1/
+
+[ats]
+UNSPECIFIED_QUOTA_IN = 8 KiB
+UNSPECIFIED_QUOTA_OUT = 8 KiB
+# LOOPBACK
+LOOPBACK_QUOTA_IN = 8 KiB
+LOOPBACK_QUOTA_OUT = 8 KiB
+# LAN
+LAN_QUOTA_IN = 8 KiB
+LAN_QUOTA_OUT = 8 KiB
+# WAN
+WAN_QUOTA_IN = 8 KiB
+WAN_QUOTA_OUT = 8 KiB
+# WLAN
+WLAN_QUOTA_IN = 8 KiB
+WLAN_QUOTA_OUT = 8 KiB
+# BLUETOOTH
+BLUETOOTH_QUOTA_IN = 8 KiB
+BLUETOOTH_QUOTA_OUT = 8 KiB
+
+[transport-tcp]
+PORT = 12000
+TIMEOUT = 5 s
+
+[arm]
+PORT = 12005
+UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p1-service-arm.sock
+
+[statistics]
+PORT = 12004
+UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p1-service-statistics.sock
+
+[resolver]
+PORT = 12003
+UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p1-service-resolver.sock
+
+[peerinfo]
+PORT = 12002
+UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p1-service-peerinfo.sock
+
+[transport]
+PORT = 12001
+UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p1-service-transport.sock
+PLUGINS = tcp
+
diff --git a/src/transport/test_transport_address_switch_tcp_peer2.conf b/src/transport/test_transport_address_switch_tcp_peer2.conf
new file mode 100644
index 0000000000000000000000000000000000000000..bda2354b6533daf55125ab48445ffb591772a1ac
--- /dev/null
+++ b/src/transport/test_transport_address_switch_tcp_peer2.conf
@@ -0,0 +1,48 @@
+@INLINE@ template_cfg_peer2.conf
+[PATHS]
+GNUNET_TEST_HOME = $GNUNET_TMP/test-transport/api-tcp-p2/
+
+[ats]
+UNSPECIFIED_QUOTA_IN = 8 KiB
+UNSPECIFIED_QUOTA_OUT = 8 KiB
+# LOOPBACK
+LOOPBACK_QUOTA_IN = 8 KiB
+LOOPBACK_QUOTA_OUT = 8 KiB
+# LAN
+LAN_QUOTA_IN = 8 KiB
+LAN_QUOTA_OUT = 8 KiB
+# WAN
+WAN_QUOTA_IN = 8 KiB
+WAN_QUOTA_OUT = 8 KiB
+# WLAN
+WLAN_QUOTA_IN = 8 KiB
+WLAN_QUOTA_OUT = 8 KiB
+# BLUETOOTH
+BLUETOOTH_QUOTA_IN = 8 KiB
+BLUETOOTH_QUOTA_OUT = 8 KiB
+
+[transport-tcp]
+PORT = 12015
+TIMEOUT = 5 s
+
+[arm]
+PORT = 12014
+UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p2-service-arm.sock
+
+[statistics]
+PORT = 12013
+UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p2-service-statistics.sock
+
+[resolver]
+PORT = 12012
+UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p2-service-resolver.sock
+
+[peerinfo]
+PORT = 12011
+UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p2-service-peerinfo.sock
+
+[transport]
+PORT = 12010
+PLUGINS = tcp
+UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p2-service-transport.sock
+
diff --git a/src/transport/test_transport_address_switch_udp_peer1.conf b/src/transport/test_transport_address_switch_udp_peer1.conf
new file mode 100644
index 0000000000000000000000000000000000000000..bdc3a2253cc68df02a64c4ba1929cf00182a8146
--- /dev/null
+++ b/src/transport/test_transport_address_switch_udp_peer1.conf
@@ -0,0 +1,48 @@
+@INLINE@ template_cfg_peer1.conf
+[PATHS]
+GNUNET_TEST_HOME = $GNUNET_TMP/test-transport/api-tcp-p1/
+
+[ats]
+UNSPECIFIED_QUOTA_IN = 8 KiB
+UNSPECIFIED_QUOTA_OUT = 8 KiB
+# LOOPBACK
+LOOPBACK_QUOTA_IN = 8 KiB
+LOOPBACK_QUOTA_OUT = 8 KiB
+# LAN
+LAN_QUOTA_IN = 8 KiB
+LAN_QUOTA_OUT = 8 KiB
+# WAN
+WAN_QUOTA_IN = 8 KiB
+WAN_QUOTA_OUT = 8 KiB
+# WLAN
+WLAN_QUOTA_IN = 8 KiB
+WLAN_QUOTA_OUT = 8 KiB
+# BLUETOOTH
+BLUETOOTH_QUOTA_IN = 8 KiB
+BLUETOOTH_QUOTA_OUT = 8 KiB
+
+[transport-tcp]
+PORT = 12000
+TIMEOUT = 5 s
+
+[arm]
+PORT = 12005
+UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p1-service-arm.sock
+
+[statistics]
+PORT = 12004
+UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p1-service-statistics.sock
+
+[resolver]
+PORT = 12003
+UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p1-service-resolver.sock
+
+[peerinfo]
+PORT = 12002
+UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p1-service-peerinfo.sock
+
+[transport]
+PORT = 12001
+UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p1-service-transport.sock
+PLUGINS = udp
+
diff --git a/src/transport/test_transport_address_switch_udp_peer2.conf b/src/transport/test_transport_address_switch_udp_peer2.conf
new file mode 100644
index 0000000000000000000000000000000000000000..ae6397db441c2f73577a6a76a03bc3399df7b87d
--- /dev/null
+++ b/src/transport/test_transport_address_switch_udp_peer2.conf
@@ -0,0 +1,48 @@
+@INLINE@ template_cfg_peer2.conf
+[PATHS]
+GNUNET_TEST_HOME = $GNUNET_TMP/test-transport/api-tcp-p2/
+
+[ats]
+UNSPECIFIED_QUOTA_IN = 8 KiB
+UNSPECIFIED_QUOTA_OUT = 8 KiB
+# LOOPBACK
+LOOPBACK_QUOTA_IN = 8 KiB
+LOOPBACK_QUOTA_OUT = 8 KiB
+# LAN
+LAN_QUOTA_IN = 8 KiB
+LAN_QUOTA_OUT = 8 KiB
+# WAN
+WAN_QUOTA_IN = 8 KiB
+WAN_QUOTA_OUT = 8 KiB
+# WLAN
+WLAN_QUOTA_IN = 8 KiB
+WLAN_QUOTA_OUT = 8 KiB
+# BLUETOOTH
+BLUETOOTH_QUOTA_IN = 8 KiB
+BLUETOOTH_QUOTA_OUT = 8 KiB
+
+[transport-tcp]
+PORT = 12015
+TIMEOUT = 5 s
+
+[arm]
+PORT = 12014
+UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p2-service-arm.sock
+
+[statistics]
+PORT = 12013
+UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p2-service-statistics.sock
+
+[resolver]
+PORT = 12012
+UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p2-service-resolver.sock
+
+[peerinfo]
+PORT = 12011
+UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p2-service-peerinfo.sock
+
+[transport]
+PORT = 12010
+PLUGINS = udp
+UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p2-service-transport.sock
+
diff --git a/src/transport/test_transport_api_unreliability_bluetooth_peer1.conf b/src/transport/test_transport_api_unreliability_bluetooth_peer1.conf
new file mode 100644
index 0000000000000000000000000000000000000000..3f86ee94026d738f388320767f459699066e42b4
--- /dev/null
+++ b/src/transport/test_transport_api_unreliability_bluetooth_peer1.conf
@@ -0,0 +1,30 @@
+@INLINE@ template_cfg_peer1.conf
+[PATHS]
+GNUNET_TEST_HOME = $GNUNET_TMP/test-transport/api-bluetooth-p1/
+
+[transport-bluetooth]
+INTERFACE = hci0
+TESTMODE = 1
+
+[arm]
+PORT = 12164
+UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p1-service-arm.sock
+
+[statistics]
+PORT = 12163
+UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p1-service-statistics.sock
+
+[resolver]
+PORT = 12162
+UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p1-service-resolver.sock
+
+[peerinfo]
+PORT = 12161
+UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p1-service-peerinfo.sock
+
+[transport]
+PORT = 12160
+PLUGINS = bluetooth
+UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p1-service-transport.sock
+
+
diff --git a/src/transport/test_transport_api_unreliability_bluetooth_peer2.conf b/src/transport/test_transport_api_unreliability_bluetooth_peer2.conf
new file mode 100644
index 0000000000000000000000000000000000000000..5fc178395593246686bcc1b8f47d15592942946c
--- /dev/null
+++ b/src/transport/test_transport_api_unreliability_bluetooth_peer2.conf
@@ -0,0 +1,29 @@
+@INLINE@ template_cfg_peer2.conf
+[PATHS]
+GNUNET_TEST_HOME = $GNUNET_TMP/test-transport/api-bluetooth-p2/
+
+[transport-bluetooth]
+INTERFACE = hci1
+TESTMODE = 2
+
+[arm]
+PORT = 12174
+UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p2-service-arm.sock
+
+[statistics]
+PORT = 12173
+UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p2-service-statistics.sock
+
+[resolver]
+PORT = 12172
+UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p2-service-resolver.sock
+
+[peerinfo]
+PORT = 12171
+UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p2-service-peerinfo.sock
+
+[transport]
+PORT = 12170
+PLUGINS = bluetooth
+UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p2-service-transport.sock
+
diff --git a/src/transport/test_transport_api_unreliability_constant_udp_peer1.conf b/src/transport/test_transport_api_unreliability_constant_udp_peer1.conf
new file mode 100644
index 0000000000000000000000000000000000000000..9f63c0cedba10f340f2ff37564f84be2fe59b1fc
--- /dev/null
+++ b/src/transport/test_transport_api_unreliability_constant_udp_peer1.conf
@@ -0,0 +1,30 @@
+@INLINE@ template_cfg_peer1.conf
+[PATHS]
+GNUNET_TEST_HOME = $GNUNET_TMP/test-transport/api-udp-p1/
+
+[transport-udp]
+PORT = 12040
+MAX_BPS = 1073741824
+
+[arm]
+PORT = 12045
+UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p1-service-arm.sock
+
+[statistics]
+PORT = 12044
+UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p1-service-statistics.sock
+
+[resolver]
+PORT = 12043
+UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p1-service-resolver.sock
+
+[peerinfo]
+PORT = 12042
+UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p1-service-peerinfo.sock
+
+[transport]
+PORT = 12041
+PLUGINS = udp
+UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p1-service-transport.sock
+
+
diff --git a/src/transport/test_transport_api_unreliability_constant_udp_peer2.conf b/src/transport/test_transport_api_unreliability_constant_udp_peer2.conf
new file mode 100644
index 0000000000000000000000000000000000000000..cdf3d7bb43eda07c3dbed5a458743cc4b0ea32ed
--- /dev/null
+++ b/src/transport/test_transport_api_unreliability_constant_udp_peer2.conf
@@ -0,0 +1,30 @@
+@INLINE@ template_cfg_peer2.conf
+[PATHS]
+GNUNET_TEST_HOME = $GNUNET_TMP/test-transport/api-udp-p2/
+
+[transport-udp]
+PORT = 12050
+MAX_BPS = 1073741824
+
+[arm]
+PORT = 12055
+UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p2-service-arm.sock
+
+[statistics]
+PORT = 12054
+UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p2-service-statistics.sock
+
+[resolver]
+PORT = 12053
+UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p2-service-resolver.sock
+
+[peerinfo]
+PORT = 12052
+UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p2-service-peerinfo.sock
+
+[transport]
+PORT = 12051
+PLUGINS = udp
+UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p2-service-transport.sock
+
+
diff --git a/src/transport/test_transport_test_transport_address_switch_tcp_peer1.conf b/src/transport/test_transport_test_transport_address_switch_tcp_peer1.conf
new file mode 100644
index 0000000000000000000000000000000000000000..920e8d1998ad3e0536cf24fef55dafdccea01ca8
--- /dev/null
+++ b/src/transport/test_transport_test_transport_address_switch_tcp_peer1.conf
@@ -0,0 +1,29 @@
+@INLINE@ template_cfg_peer1.conf
+
+[ats]
+UNSPECIFIED_QUOTA_IN = 8 KiB
+UNSPECIFIED_QUOTA_OUT = 8 KiB
+# LOOPBACK
+LOOPBACK_QUOTA_IN = 8 KiB
+LOOPBACK_QUOTA_OUT = 8 KiB
+# LAN
+LAN_QUOTA_IN = 8 KiB
+LAN_QUOTA_OUT = 8 KiB
+# WAN
+WAN_QUOTA_IN = 8 KiB
+WAN_QUOTA_OUT = 8 KiB
+# WLAN
+WLAN_QUOTA_IN = 8 KiB
+WLAN_QUOTA_OUT = 8 KiB
+# BLUETOOTH
+BLUETOOTH_QUOTA_IN = 8 KiB
+BLUETOOTH_QUOTA_OUT = 8 KiB
+
+[PATHS]
+GNUNET_TEST_HOME = $GNUNET_TMP/test-transport/quota-tcp-p1/
+
+[transport]
+PLUGINS = tcp
+
+
+
diff --git a/src/transport/test_transport_test_transport_address_switch_tcp_peer2.conf b/src/transport/test_transport_test_transport_address_switch_tcp_peer2.conf
new file mode 100644
index 0000000000000000000000000000000000000000..6855cd00d701cb597ed8e953311a8442a5f75f6b
--- /dev/null
+++ b/src/transport/test_transport_test_transport_address_switch_tcp_peer2.conf
@@ -0,0 +1,29 @@
+@INLINE@ template_cfg_peer2.conf
+
+[ats]
+UNSPECIFIED_QUOTA_IN = 8 KiB
+UNSPECIFIED_QUOTA_OUT = 8 KiB
+# LOOPBACK
+LOOPBACK_QUOTA_IN = 8 KiB
+LOOPBACK_QUOTA_OUT = 8 KiB
+# LAN
+LAN_QUOTA_IN = 8 KiB
+LAN_QUOTA_OUT = 8 KiB
+# WAN
+WAN_QUOTA_IN = 8 KiB
+WAN_QUOTA_OUT = 8 KiB
+# WLAN
+WLAN_QUOTA_IN = 8 KiB
+WLAN_QUOTA_OUT = 8 KiB
+# BLUETOOTH
+BLUETOOTH_QUOTA_IN = 8 KiB
+BLUETOOTH_QUOTA_OUT = 8 KiB
+
+
+[PATHS]
+GNUNET_TEST_HOME = $GNUNET_TMP/test-transport/api-tcp-p2/
+
+[transport]
+PLUGINS = tcp
+
+
diff --git a/src/transport/transport-testing2.c b/src/transport/transport-testing2.c
index 0dc1bb33156fd59b91b310ed94c0724341525b74..98cfd5e2993a4dbd6f527d8c4e671ad077d1301e 100644
--- a/src/transport/transport-testing2.c
+++ b/src/transport/transport-testing2.c
@@ -58,140 +58,6 @@ struct MyClient
 
 };
 
-/**
- * @brief Handle to a transport communicator
- */
-struct GNUNET_TRANSPORT_TESTING_TransportCommunicatorHandle
-{
-  /**
-   * Clients
-   */
-  struct MyClient *client_head;
-  struct MyClient *client_tail;
-
-  /**
-  * @brief Handle to the client
-  */
-  struct GNUNET_MQ_Handle *c_mq;
-
-  /**
-    * @brief Handle to the configuration
-    */
-  struct GNUNET_CONFIGURATION_Handle *cfg;
-
-  /**
-   * @brief File name of configuration file
-   */
-  char *cfg_filename;
-
-  struct GNUNET_PeerIdentity peer_id;
-
-  /**
-   * @brief Handle to the transport service
-   */
-  struct GNUNET_SERVICE_Handle *tsh;
-
-  /**
-   * @brief Task that will be run on shutdown to stop and clean transport
-   * service
-   */
-  struct GNUNET_SCHEDULER_Task *ts_shutdown_task;
-
-
-  /**
-   * @brief Process of the communicator
-   */
-  struct GNUNET_OS_Process *c_proc;
-
-  /**
-   * NAT process
-   */
-  struct GNUNET_OS_Process *nat_proc;
-
-  /**
-   * resolver service process
-   */
-  struct GNUNET_OS_Process *resolver_proc;
-
-  /**
-   * @brief Task that will be run on shutdown to stop and clean communicator
-   */
-  struct GNUNET_SCHEDULER_Task *c_shutdown_task;
-
-  /**
-   * @brief Characteristics of the communicator
-   */
-  enum GNUNET_TRANSPORT_CommunicatorCharacteristics c_characteristics;
-
-  /**
-   * @brief Specifies supported addresses
-   */
-  char *c_addr_prefix;
-
-  /**
-   * @brief Specifies supported addresses
-   */
-  char *c_address;
-
-  /**
-   * @brief Head of the DLL of queues associated with this communicator
-   */
-  struct GNUNET_TRANSPORT_TESTING_TransportCommunicatorQueue *queue_head;
-
-  /**
-   * @brief Tail of the DLL of queues associated with this communicator
-   */
-  struct GNUNET_TRANSPORT_TESTING_TransportCommunicatorQueue *queue_tail;
-
-  /* Callbacks + Closures */
-  /**
-   * @brief Callback called when a new communicator connects
-   */
-  GNUNET_TRANSPORT_TESTING_CommunicatorAvailableCallback
-    communicator_available_cb;
-
-  /**
-   * @brief Callback called when a new communicator connects
-   */
-  GNUNET_TRANSPORT_TESTING_AddAddressCallback add_address_cb;
-
-  /**
-   * @brief Callback called when a new communicator connects
-   */
-  GNUNET_TRANSPORT_TESTING_QueueCreateReplyCallback queue_create_reply_cb;
-
-  /**
-   * @brief Callback called when a new communicator connects
-   */
-  GNUNET_TRANSPORT_TESTING_AddQueueCallback add_queue_cb;
-
-  /**
-   * @brief Callback called when a new communicator connects
-   */
-  GNUNET_TRANSPORT_TESTING_IncomingMessageCallback incoming_msg_cb;
-
-  /**
-   * @brief Backchannel callback
-   */
-  GNUNET_TRANSPORT_TESTING_BackchannelCallback bc_cb;
-
-  /**
-   * Our service handle
-   */
-  struct GNUNET_SERVICE_Handle *sh;
-
-  /**
-   * @brief Closure to the callback
-   */
-  void *cb_cls;
-
-  /**
-   * Backchannel supported
-   */
-  int bc_enabled;
-};
-
-
 /**
  * @brief Queue of a communicator and some context
  */
@@ -671,8 +537,8 @@ handle_update_queue_message (void *cls,
   struct GNUNET_TRANSPORT_TESTING_TransportCommunicatorQueue *tc_queue;
 
   LOG (GNUNET_ERROR_TYPE_DEBUG,
-       "Received queue update message for %u with q_len %"PRIu64"\n",
-       msg->qid, GNUNET_ntohll(msg->q_len));
+       "Received queue update message for %u with q_len %" PRIu64 "\n",
+       msg->qid, GNUNET_ntohll (msg->q_len));
   tc_queue = tc_h->queue_head;
   if (NULL != tc_queue)
   {
@@ -702,6 +568,9 @@ shutdown_service (void *cls)
 {
   struct GNUNET_SERVICE_Handle *h = cls;
 
+  LOG (GNUNET_ERROR_TYPE_DEBUG,
+       "Shutting down service!\n");
+
   GNUNET_SERVICE_stop (h);
 }
 
@@ -892,6 +761,12 @@ shutdown_process (struct GNUNET_OS_Process *proc)
   GNUNET_OS_process_destroy (proc);
 }
 
+static void
+shutdown_peerstore (void *cls)
+{
+  struct GNUNET_OS_Process *proc = cls;
+  shutdown_process (proc);
+}
 
 static void
 shutdown_communicator (void *cls)
@@ -912,19 +787,30 @@ communicator_start (
   const char *binary_name)
 {
   char *binary;
+  char *loprefix;
+  char *section_name;
 
   LOG (GNUNET_ERROR_TYPE_DEBUG, "communicator_start\n");
+
+  section_name = strchr (binary_name, '-');
+  section_name++;
+
+  if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_string (tc_h->cfg,
+                                                          section_name,
+                                                          "PREFIX",
+                                                          &loprefix))
+    loprefix = GNUNET_strdup ("");
+
+
   binary = GNUNET_OS_get_libexec_binary_path (binary_name);
-  tc_h->c_proc = GNUNET_OS_start_process (GNUNET_YES,
-                                          GNUNET_OS_INHERIT_STD_OUT_AND_ERR,
-                                          NULL,
-                                          NULL,
-                                          NULL,
-                                          binary,
-                                          binary_name,
-                                          "-c",
-                                          tc_h->cfg_filename,
-                                          NULL);
+  tc_h->c_proc = GNUNET_OS_start_process_s (GNUNET_OS_INHERIT_STD_OUT_AND_ERR,
+                                            NULL,
+                                            loprefix,
+                                            binary,
+                                            binary_name,
+                                            "-c",
+                                            tc_h->cfg_filename,
+                                            NULL);
   if (NULL == tc_h->c_proc)
   {
     GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Failed to start communicator!");
@@ -947,6 +833,7 @@ shutdown_nat (void *cls)
   shutdown_process (proc);
 }
 
+
 /**
  * @brief Task run at shutdown to kill the resolver process
  *
@@ -959,6 +846,7 @@ shutdown_resolver (void *cls)
   shutdown_process (proc);
 }
 
+
 static void
 resolver_start (struct
                 GNUNET_TRANSPORT_TESTING_TransportCommunicatorHandle *tc_h)
@@ -967,16 +855,17 @@ resolver_start (struct
 
   LOG (GNUNET_ERROR_TYPE_DEBUG, "resolver_start\n");
   binary = GNUNET_OS_get_libexec_binary_path ("gnunet-service-resolver");
-  tc_h->resolver_proc = GNUNET_OS_start_process (GNUNET_YES,
-                                                 GNUNET_OS_INHERIT_STD_OUT_AND_ERR,
-                                                 NULL,
-                                                 NULL,
-                                                 NULL,
-                                                 binary,
-                                                 "gnunet-service-resolver",
-                                                 "-c",
-                                                 tc_h->cfg_filename,
-                                                 NULL);
+  tc_h->resolver_proc = GNUNET_OS_start_process (
+    GNUNET_OS_INHERIT_STD_OUT_AND_ERR
+    | GNUNET_OS_USE_PIPE_CONTROL,
+    NULL,
+    NULL,
+    NULL,
+    binary,
+    "gnunet-service-resolver",
+    "-c",
+    tc_h->cfg_filename,
+    NULL);
   if (NULL == tc_h->resolver_proc)
   {
     GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Failed to start resolver service!");
@@ -987,6 +876,36 @@ resolver_start (struct
 
 }
 
+
+/**
+ * @brief Start Peerstore
+ *
+ */
+static void
+peerstore_start (
+  struct GNUNET_TRANSPORT_TESTING_TransportCommunicatorHandle *tc_h)
+{
+  char *binary;
+
+  binary = GNUNET_OS_get_libexec_binary_path ("gnunet-service-peerstore");
+  tc_h->ps_proc = GNUNET_OS_start_process (GNUNET_OS_INHERIT_STD_OUT_AND_ERR,
+                                           NULL,
+                                           NULL,
+                                           NULL,
+                                           binary,
+                                           "gnunet-service-peerstore",
+                                           "-c",
+                                           tc_h->cfg_filename,
+                                           NULL);
+  if (NULL == tc_h->ps_proc)
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Failed to start Peerstore!");
+    return;
+  }
+  LOG (GNUNET_ERROR_TYPE_INFO, "started Peerstore\n");
+  GNUNET_free (binary);
+}
+
 /**
  * @brief Start NAT
  *
@@ -999,8 +918,8 @@ nat_start (
 
   LOG (GNUNET_ERROR_TYPE_DEBUG, "nat_start\n");
   binary = GNUNET_OS_get_libexec_binary_path ("gnunet-service-nat");
-  tc_h->nat_proc = GNUNET_OS_start_process (GNUNET_YES,
-                                            GNUNET_OS_INHERIT_STD_OUT_AND_ERR,
+  tc_h->nat_proc = GNUNET_OS_start_process (GNUNET_OS_INHERIT_STD_OUT_AND_ERR
+                                            | GNUNET_OS_USE_PIPE_CONTROL,
                                             NULL,
                                             NULL,
                                             NULL,
@@ -1083,6 +1002,8 @@ GNUNET_TRANSPORT_TESTING_transport_communicator_service_start (
   nat_start (tc_h);
   /* Start resolver service */
   resolver_start (tc_h);
+  /* Start peerstore service */
+  peerstore_start (tc_h);
   /* Schedule start communicator */
   communicator_start (tc_h,
                       binary_name);
@@ -1098,6 +1019,7 @@ GNUNET_TRANSPORT_TESTING_transport_communicator_service_stop (
   shutdown_service (tc_h->sh);
   shutdown_nat (tc_h->nat_proc);
   shutdown_resolver (tc_h->resolver_proc);
+  shutdown_peerstore (tc_h->ps_proc);
   GNUNET_CONFIGURATION_destroy (tc_h->cfg);
   GNUNET_free (tc_h);
 }
@@ -1144,6 +1066,8 @@ GNUNET_TRANSPORT_TESTING_transport_communicator_open_queue (
   memcpy (&msg[1], address, alen);
   if (NULL != tc_h->c_mq)
   {
+    LOG (GNUNET_ERROR_TYPE_DEBUG,
+         "Sending queue create immediately\n");
     GNUNET_MQ_send (tc_h->c_mq, env);
   }
   else
diff --git a/src/transport/transport-testing2.h b/src/transport/transport-testing2.h
index b77125e826f541ecbb62d9eaeeac6965cf9e443f..04f75fc88cd9d12c3dcdaa98f9cbcdfa1261399e 100644
--- a/src/transport/transport-testing2.h
+++ b/src/transport/transport-testing2.h
@@ -29,13 +29,6 @@
 #include "gnunet_ats_transport_service.h"
 #include "transport.h"
 
-
-/**
- * @brief Handle to a transport communicator
- */
-struct GNUNET_TRANSPORT_TESTING_TransportCommunicatorHandle;
-
-
 /**
  * @brief Queue of a communicator and some context
  */
@@ -151,6 +144,143 @@ typedef void
                                                     const char*payload,
                                                     size_t payload_len);
 
+/**
+ * @brief Handle to a transport communicator
+ */
+struct GNUNET_TRANSPORT_TESTING_TransportCommunicatorHandle
+{
+  /**
+   * Clients
+   */
+  struct MyClient *client_head;
+  struct MyClient *client_tail;
+
+  /**
+  * @brief Handle to the client
+  */
+  struct GNUNET_MQ_Handle *c_mq;
+
+  /**
+    * @brief Handle to the configuration
+    */
+  struct GNUNET_CONFIGURATION_Handle *cfg;
+
+  /**
+   * @brief File name of configuration file
+   */
+  char *cfg_filename;
+
+  struct GNUNET_PeerIdentity peer_id;
+
+  /**
+   * @brief Handle to the transport service
+   */
+  struct GNUNET_SERVICE_Handle *tsh;
+
+  /**
+   * @brief Task that will be run on shutdown to stop and clean transport
+   * service
+   */
+  struct GNUNET_SCHEDULER_Task *ts_shutdown_task;
+
+
+  /**
+   * @brief Process of the communicator
+   */
+  struct GNUNET_OS_Process *c_proc;
+
+  /**
+   * NAT process
+   */
+  struct GNUNET_OS_Process *nat_proc;
+
+  /**
+   * resolver service process
+   */
+  struct GNUNET_OS_Process *resolver_proc;
+
+  /**
+   * peerstore service process
+   */
+  struct GNUNET_OS_Process *ps_proc;
+
+  /**
+   * @brief Task that will be run on shutdown to stop and clean communicator
+   */
+  struct GNUNET_SCHEDULER_Task *c_shutdown_task;
+
+  /**
+   * @brief Characteristics of the communicator
+   */
+  enum GNUNET_TRANSPORT_CommunicatorCharacteristics c_characteristics;
+
+  /**
+   * @brief Specifies supported addresses
+   */
+  char *c_addr_prefix;
+
+  /**
+   * @brief Specifies supported addresses
+   */
+  char *c_address;
+
+  /**
+   * @brief Head of the DLL of queues associated with this communicator
+   */
+  struct GNUNET_TRANSPORT_TESTING_TransportCommunicatorQueue *queue_head;
+
+  /**
+   * @brief Tail of the DLL of queues associated with this communicator
+   */
+  struct GNUNET_TRANSPORT_TESTING_TransportCommunicatorQueue *queue_tail;
+
+  /* Callbacks + Closures */
+  /**
+   * @brief Callback called when a new communicator connects
+   */
+  GNUNET_TRANSPORT_TESTING_CommunicatorAvailableCallback
+    communicator_available_cb;
+
+  /**
+   * @brief Callback called when a new communicator connects
+   */
+  GNUNET_TRANSPORT_TESTING_AddAddressCallback add_address_cb;
+
+  /**
+   * @brief Callback called when a new communicator connects
+   */
+  GNUNET_TRANSPORT_TESTING_QueueCreateReplyCallback queue_create_reply_cb;
+
+  /**
+   * @brief Callback called when a new communicator connects
+   */
+  GNUNET_TRANSPORT_TESTING_AddQueueCallback add_queue_cb;
+
+  /**
+   * @brief Callback called when a new communicator connects
+   */
+  GNUNET_TRANSPORT_TESTING_IncomingMessageCallback incoming_msg_cb;
+
+  /**
+   * @brief Backchannel callback
+   */
+  GNUNET_TRANSPORT_TESTING_BackchannelCallback bc_cb;
+
+  /**
+   * Our service handle
+   */
+  struct GNUNET_SERVICE_Handle *sh;
+
+  /**
+   * @brief Closure to the callback
+   */
+  void *cb_cls;
+
+  /**
+   * Backchannel supported
+   */
+  int bc_enabled;
+};
 
 /**
  * @brief Start communicator part of transport service and communicator
diff --git a/src/transport/transport.h b/src/transport/transport.h
index a64ffd5c6f93ab31a6c6f99d8e18b4e637d26a67..dbae4ecfb8eeb3778d3163d77110731f67d0e005 100644
--- a/src/transport/transport.h
+++ b/src/transport/transport.h
@@ -903,7 +903,6 @@ struct GNUNET_TRANSPORT_UpdateQueueMessage
 };
 
 
-
 /**
  * Remove queue, it is no longer available.
  */
diff --git a/src/transport/transport_api2_communication.c b/src/transport/transport_api2_communication.c
index cfa144415cb55c5ebaefcae3cd72c65cf62efde2..b048ad8517581c4701f878a5813d88f7b6b1a3d1 100644
--- a/src/transport/transport_api2_communication.c
+++ b/src/transport/transport_api2_communication.c
@@ -420,6 +420,7 @@ send_add_queue (struct GNUNET_TRANSPORT_QueueHandle *qh)
   GNUNET_MQ_send (qh->ch->mq, env);
 }
 
+
 /**
  * Send message to the transport service about queue @a qh
  * updated.
@@ -446,7 +447,6 @@ send_update_queue (struct GNUNET_TRANSPORT_QueueHandle *qh)
 }
 
 
-
 /**
  * Send message to the transport service about queue @a qh
  * being no longer available.
@@ -1033,7 +1033,6 @@ GNUNET_TRANSPORT_communicator_mq_update (
 }
 
 
-
 /**
  * Notify transport service that an MQ became unavailable due to a
  * disconnect or timeout.
@@ -1082,7 +1081,6 @@ GNUNET_TRANSPORT_communicator_address_add (
   return ai;
 }
 
-
 /**
  * Notify transport service about an address that this communicator no
  * longer provides for this peer.
@@ -1101,6 +1099,20 @@ GNUNET_TRANSPORT_communicator_address_remove (
   GNUNET_free (ai);
 }
 
+/**
+ * Notify transport service that this communicator no longer provides all its addresses for this peer.
+ *
+ * @param ch The communicator handle.
+ */
+void
+GNUNET_TRANSPORT_communicator_address_remove_all (
+                                              struct GNUNET_TRANSPORT_CommunicatorHandle *ch)
+{
+  for (struct GNUNET_TRANSPORT_AddressIdentifier *ai = ch->ai_head; NULL != ai;
+       ai = ai->next)
+    GNUNET_TRANSPORT_communicator_address_remove (ai);
+}
+
 
 /* ************************* Backchannel *************************** */
 
diff --git a/src/util/.gitignore b/src/util/.gitignore
new file mode 100644
index 0000000000000000000000000000000000000000..8556ee7b84cb09fcf161be2019dd5fc14595db9f
--- /dev/null
+++ b/src/util/.gitignore
@@ -0,0 +1,82 @@
+test_common_logging_dummy
+gnunet-config
+gnunet-config-diff
+gnunet-crypto-tvg
+gnunet-ecc
+gnunet-qr
+gnunet-resolver
+gnunet-scrypt
+gnunet-service-resolver
+gnunet-uri
+test_bio
+test_client.nc
+test_client_unix.nc
+test_common_allocation
+test_common_endian
+test_common_logging
+test_common_logging_runtime_loglevels
+test_configuration
+test_connection.nc
+test_connection_addressing.nc
+test_connection_receive_cancel.nc
+test_connection_timeout.nc
+test_connection_timeout_no_connect.nc
+test_connection_transmit_cancel.nc
+test_container_bloomfilter
+test_container_dll
+test_container_heap
+test_container_meta_data
+test_container_multihashmap
+test_container_multihashmap32
+test_container_multipeermap
+test_crypto_crc
+test_crypto_ecc_dlog
+test_crypto_ecdh_ecdsa
+test_crypto_ecdh_eddsa
+test_crypto_ecdhe
+test_crypto_ecdsa
+test_crypto_eddsa
+test_crypto_hash
+test_crypto_hash_context
+test_crypto_hkdf
+test_crypto_kdf
+test_crypto_paillier
+test_crypto_random
+test_crypto_rsa
+test_crypto_symmetric
+test_disk
+test_getopt
+test_mq
+test_os_network
+test_os_start_process
+test_peer
+test_plugin
+test_program
+test_resolver_api.nc
+test_scheduler
+test_scheduler_delay
+test_server.nc
+test_server_disconnect.nc
+test_server_mst_interrupt.nc
+test_server_with_client.nc
+test_server_with_client_unix
+test_service
+test_speedup
+test_strings
+test_strings_to_data
+test_time
+test_socks.nc
+perf_crypto_asymmetric
+perf_crypto_hash
+perf_crypto_symmetric
+perf_crypto_rsa
+perf_crypto_ecc_dlog
+test_hexcoder
+test_regex
+test_tun
+test_uri
+gnunet-timeout
+python27_location
+perf_malloc
+perf_mq
+perf_scheduler
diff --git a/src/util/Makefile.am b/src/util/Makefile.am
index 83b3b9c3d28d946c6a5462b0241a03230c532181..c5059bbb12c104acb624030282b99ea41663346e 100644
--- a/src/util/Makefile.am
+++ b/src/util/Makefile.am
@@ -96,6 +96,7 @@ libgnunetutil_la_SOURCES = \
   strings.c \
   time.c \
   tun.c \
+  uri.c \
   speedup.c speedup.h \
   proc_compat.c
 
@@ -302,6 +303,7 @@ check_PROGRAMS = \
  test_speedup \
  test_time \
  test_tun \
+ test_uri \
  $(BENCHMARKS) \
  test_os_start_process \
  test_common_logging_runtime_loglevels
@@ -573,6 +575,11 @@ test_speedup_SOURCES = \
 test_speedup_LDADD = \
  libgnunetutil.la
 
+test_uri_SOURCES = \
+ test_uri.c
+test_uri_LDADD = \
+ libgnunetutil.la
+
 perf_crypto_hash_SOURCES = \
  perf_crypto_hash.c
 perf_crypto_hash_LDADD = \
diff --git a/src/util/bio.c b/src/util/bio.c
index b272302403f6a8f6bb3b98bc0609c02f1bd7a0ae..39050bb87e6846685f4f1d4a180af6e62adcc434 100644
--- a/src/util/bio.c
+++ b/src/util/bio.c
@@ -260,7 +260,7 @@ read_from_buffer (struct GNUNET_BIO_ReadHandle *h,
                   char *result,
                   size_t len)
 {
-  if (h->size < len || h->size - h->pos < len)
+  if ((h->size < len) || (h->size - h->pos < len))
   {
     GNUNET_asprintf (&h->emsg,
                      _ ("Error while reading `%s' from buffer: %s"),
@@ -431,6 +431,7 @@ GNUNET_BIO_read_meta_data (struct GNUNET_BIO_ReadHandle *h,
   return GNUNET_OK;
 }
 
+
 /**
  * Read a float.
  *
@@ -439,9 +440,9 @@ GNUNET_BIO_read_meta_data (struct GNUNET_BIO_ReadHandle *h,
  * @param f address of float to read
  */
 int
-GNUNET_BIO_read_float(struct GNUNET_BIO_ReadHandle *h,
-                      const char *what,
-                      float *f)
+GNUNET_BIO_read_float (struct GNUNET_BIO_ReadHandle *h,
+                       const char *what,
+                       float *f)
 {
   int32_t *i = (int32_t *) f;
   return GNUNET_BIO_read_int32 (h, what, i);
@@ -456,9 +457,9 @@ GNUNET_BIO_read_float(struct GNUNET_BIO_ReadHandle *h,
  * @param f address of double to read
  */
 int
-GNUNET_BIO_read_double(struct GNUNET_BIO_ReadHandle *h,
-                       const char *what,
-                       double *f)
+GNUNET_BIO_read_double (struct GNUNET_BIO_ReadHandle *h,
+                        const char *what,
+                        double *f)
 {
   int64_t *i = (int64_t *) f;
   return GNUNET_BIO_read_int64 (h, what, i);
@@ -692,7 +693,7 @@ GNUNET_BIO_get_buffer_contents (struct GNUNET_BIO_WriteHandle *h,
 {
   if (IO_BUFFER != h->type)
     return GNUNET_SYSERR;
-  if (NULL == contents || NULL == size)
+  if ((NULL == contents) || (NULL == size))
     return GNUNET_SYSERR;
   int ret = (NULL != h->emsg) ? GNUNET_SYSERR : GNUNET_OK;
   if (NULL != emsg)
@@ -897,9 +898,9 @@ GNUNET_BIO_write_meta_data (struct GNUNET_BIO_WriteHandle *h,
  * @param f float to write
  */
 int
-GNUNET_BIO_write_float(struct GNUNET_BIO_WriteHandle *h,
-                       const char *what,
-                       float f)
+GNUNET_BIO_write_float (struct GNUNET_BIO_WriteHandle *h,
+                        const char *what,
+                        float f)
 {
   int32_t i = f;
   return GNUNET_BIO_write_int32 (h, what, i);
@@ -914,9 +915,9 @@ GNUNET_BIO_write_float(struct GNUNET_BIO_WriteHandle *h,
  * @param f double to write
  */
 int
-GNUNET_BIO_write_double(struct GNUNET_BIO_WriteHandle *h,
-                        const char *what,
-                        double f)
+GNUNET_BIO_write_double (struct GNUNET_BIO_WriteHandle *h,
+                         const char *what,
+                         double f)
 {
   int64_t i = f;
   return GNUNET_BIO_write_int64 (h, what, i);
@@ -1196,7 +1197,7 @@ GNUNET_BIO_read_spec_int64 (const char *what,
  * @param f address of float to read
  */
 struct GNUNET_BIO_ReadSpec
-GNUNET_BIO_read_spec_float(const char *what, float *f)
+GNUNET_BIO_read_spec_float (const char *what, float *f)
 {
   struct GNUNET_BIO_ReadSpec rs = {
     .rh = &read_spec_handler_int32,
@@ -1216,7 +1217,7 @@ GNUNET_BIO_read_spec_float(const char *what, float *f)
  * @param f address of double to read
  */
 struct GNUNET_BIO_ReadSpec
-GNUNET_BIO_read_spec_double(const char *what, double *f)
+GNUNET_BIO_read_spec_double (const char *what, double *f)
 {
   struct GNUNET_BIO_ReadSpec rs = {
     .rh = &read_spec_handler_int64,
@@ -1243,7 +1244,7 @@ GNUNET_BIO_read_spec_commit (struct GNUNET_BIO_ReadHandle *h,
 {
   int ret = GNUNET_OK;
 
-  for (size_t i=0; NULL!=rs[i].rh; ++i)
+  for (size_t i = 0; NULL!=rs[i].rh; ++i)
   {
     ret = rs[i].rh (rs[i].cls, h, rs[i].what, rs[i].target, rs[i].size);
     if (GNUNET_OK != ret)
@@ -1490,7 +1491,7 @@ GNUNET_BIO_write_spec_int64 (const char *what,
  * @return the write spec
  */
 struct GNUNET_BIO_WriteSpec
-GNUNET_BIO_write_spec_float(const char *what, float *f)
+GNUNET_BIO_write_spec_float (const char *what, float *f)
 {
   struct GNUNET_BIO_WriteSpec ws = {
     .wh = &write_spec_handler_int32,
@@ -1512,7 +1513,7 @@ GNUNET_BIO_write_spec_float(const char *what, float *f)
  * @return the write spec
  */
 struct GNUNET_BIO_WriteSpec
-GNUNET_BIO_write_spec_double(const char *what, double *f)
+GNUNET_BIO_write_spec_double (const char *what, double *f)
 {
   struct GNUNET_BIO_WriteSpec ws = {
     .wh = &write_spec_handler_int64,
@@ -1540,7 +1541,7 @@ GNUNET_BIO_write_spec_commit (struct GNUNET_BIO_WriteHandle *h,
 {
   int ret = GNUNET_OK;
 
-  for (size_t i=0; NULL!=ws[i].wh; ++i)
+  for (size_t i = 0; NULL!=ws[i].wh; ++i)
   {
     ret = ws[i].wh (ws[i].cls, h, ws[i].what, ws[i].source, ws[i].source_size);
     if (GNUNET_OK != ret)
diff --git a/src/util/buffer.c b/src/util/buffer.c
index d0261889e6aca4a6471698e5b80b020a9f0f45ea..662e4d0f2c85e5f5de331aac710483d47b91b088 100644
--- a/src/util/buffer.c
+++ b/src/util/buffer.c
@@ -32,7 +32,8 @@
  * @param capacity the capacity (in bytes) to allocate for @a buf
  */
 void
-GNUNET_buffer_prealloc (struct GNUNET_Buffer *buf, size_t capacity)
+GNUNET_buffer_prealloc (struct GNUNET_Buffer *buf,
+                        size_t capacity)
 {
   /* Buffer should be zero-initialized */
   GNUNET_assert (0 == buf->mem);
@@ -248,3 +249,35 @@ GNUNET_buffer_write_vfstr (struct GNUNET_Buffer *buf,
   buf->position += res;
   GNUNET_assert (buf->position <= buf->capacity);
 }
+
+
+/**
+ * Write data encoded via #GNUNET_STRINGS_data_to_string to the buffer.
+ *
+ * Grows the buffer if necessary.
+ *
+ * @param buf buffer to write to
+ * @param data data to read from
+ * @param data_len number of bytes to copy from @a data to @a buf
+ */
+void
+GNUNET_buffer_write_data_encoded (struct GNUNET_Buffer *buf,
+                                  const void *data,
+                                  size_t data_len)
+{
+  size_t outlen = data_len * 8;
+
+  if (outlen % 5 > 0)
+    outlen += 5 - outlen % 5;
+  outlen /= 5;
+  GNUNET_buffer_ensure_remaining (buf,
+                                  outlen);
+  GNUNET_assert (NULL !=
+                 GNUNET_STRINGS_data_to_string (data,
+                                                data_len,
+                                                (buf->mem
+                                                 + buf->position),
+                                                outlen));
+  buf->position += outlen;
+  GNUNET_assert (buf->position <= buf->capacity);
+}
diff --git a/src/util/common_allocation.c b/src/util/common_allocation.c
index 4aad4977794ca8a4e419c18f47fcc95356e60d49..a404a1627fe220a990914fc46a6c105effd3daaf 100644
--- a/src/util/common_allocation.c
+++ b/src/util/common_allocation.c
@@ -538,9 +538,9 @@ GNUNET_copy_message (const struct GNUNET_MessageHeader *msg)
  * @param a pointer to @a n bytes which should be tested for the
  *          entire memory being zero'ed out.
  * @param n number of bytes in @a to be tested
- * @return 0 if a is zero, non-zero otherwise
+ * @return GNUNET_YES if a is zero, GNUNET_NO otherwise
  */
-int
+enum GNUNET_GenericReturnValue
 GNUNET_is_zero_ (const void *a,
                  size_t n)
 {
@@ -548,8 +548,8 @@ GNUNET_is_zero_ (const void *a,
 
   for (size_t i = 0; i < n; i++)
     if (b[i])
-      return 1;
-  return 0;
+      return GNUNET_NO;
+  return GNUNET_YES;
 }
 
 
diff --git a/src/util/configuration.c b/src/util/configuration.c
index 34ecc9e7357efdeaec2d774eb814814f58132ab7..26beacaff82ebe16399e976a82cb7572ab57b102 100644
--- a/src/util/configuration.c
+++ b/src/util/configuration.c
@@ -1810,4 +1810,45 @@ GNUNET_CONFIGURATION_load_from (struct GNUNET_CONFIGURATION_Handle *cfg,
 }
 
 
+/**
+ * Return GNUnet's default configuration.  A new configuration is allocated
+ * each time and it's up to the caller to destroy it when done.  This function
+ * returns GNUnet's configuration even when #GNUNET_OS_init has been called
+ * with a value different from #GNUNET_OS_project_data_default.
+ *
+ * @return a freshly allocated configuration
+ */
+struct GNUNET_CONFIGURATION_Handle *
+GNUNET_CONFIGURATION_default (void)
+{
+  const struct GNUNET_OS_ProjectData *pd = GNUNET_OS_project_data_get ();
+  const struct GNUNET_OS_ProjectData *dpd = GNUNET_OS_project_data_default ();
+
+  GNUNET_OS_init (dpd);
+
+  struct GNUNET_CONFIGURATION_Handle *cfg = GNUNET_CONFIGURATION_create ();
+  const char *xdg = getenv ("XDG_CONFIG_HOME");
+  char *cfgname = NULL;
+
+  if (NULL != xdg)
+    GNUNET_asprintf (&cfgname, "%s/%s", xdg, pd->config_file);
+  else
+    cfgname = GNUNET_strdup (pd->user_config_file);
+
+  if (GNUNET_OK != GNUNET_CONFIGURATION_load (cfg, cfgname))
+  {
+    GNUNET_OS_init (pd);
+    GNUNET_CONFIGURATION_destroy (cfg);
+    GNUNET_free (cfgname);
+    return NULL;
+  }
+
+  GNUNET_free (cfgname);
+
+  GNUNET_OS_init (pd);
+
+  return cfg;
+}
+
+
 /* end of configuration.c */
diff --git a/src/util/crypto_abe.c b/src/util/crypto_abe.c
new file mode 100644
index 0000000000000000000000000000000000000000..c089b29db8be836560654962f90a821beed2e157
--- /dev/null
+++ b/src/util/crypto_abe.c
@@ -0,0 +1,438 @@
+/*
+     This file is part of GNUnet.  Copyright (C) 2001-2014 Christian Grothoff
+     (and other contributing authors)
+
+     GNUnet is free software: you can redistribute it and/or modify it
+     under the terms of the GNU Affero General Public License as published
+     by the Free Software Foundation, either version 3 of the License,
+     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
+     Affero General Public License for more details.
+
+     You should have received a copy of the GNU Affero General Public License
+     along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+     SPDX-License-Identifier: AGPL3.0-or-later
+
+ */
+
+/**
+ * @file util/crypto_random.c
+ * @brief functions to gather random numbers
+ * @author Christian Grothoff
+ */
+
+
+#include "platform.h"
+#include <pbc/pbc.h>
+#include <gabe.h>
+
+#include "gnunet_crypto_lib.h"
+
+struct GNUNET_CRYPTO_AbeMasterKey
+{
+  gabe_pub_t*pub;
+  gabe_msk_t*msk;
+};
+
+struct GNUNET_CRYPTO_AbeKey
+{
+  gabe_pub_t*pub;
+  gabe_prv_t*prv;
+};
+
+static int
+init_aes (element_t k, int enc,
+          gcry_cipher_hd_t*handle,
+          struct GNUNET_CRYPTO_SymmetricSessionKey *key,
+          unsigned char*iv)
+{
+  int rc;
+  int key_len;
+  unsigned char*key_buf;
+
+  key_len = element_length_in_bytes (k) < 33 ? 3 : element_length_in_bytes (k);
+  key_buf = (unsigned char *) malloc (key_len);
+  element_to_bytes (key_buf, k);
+
+  GNUNET_memcpy (key->aes_key,
+                 key_buf,
+                 GNUNET_CRYPTO_AES_KEY_LENGTH);
+  GNUNET_assert (0 ==
+                 gcry_cipher_open (handle, GCRY_CIPHER_AES256,
+                                   GCRY_CIPHER_MODE_CFB, 0));
+  rc = gcry_cipher_setkey (*handle,
+                           key->aes_key,
+                           sizeof(key->aes_key));
+  GNUNET_assert ((0 == rc) || ((char) rc == GPG_ERR_WEAK_KEY));
+  memset (iv, 0, 16);  // TODO make reasonable
+  rc = gcry_cipher_setiv (*handle,
+                          iv,
+                          16);
+  GNUNET_assert ((0 == rc) || ((char) rc == GPG_ERR_WEAK_KEY));
+
+  free (key_buf);
+  return rc;
+}
+
+
+static int
+aes_128_cbc_encrypt (char*pt,
+                     int size,
+                     element_t k,
+                     char **ct)
+{
+  gcry_cipher_hd_t handle;
+  struct GNUNET_CRYPTO_SymmetricSessionKey skey;
+  unsigned char iv[16];
+  char*buf;
+  int padding;
+  int buf_size;
+  uint8_t len[4];
+
+  init_aes (k, 1, &handle, &skey, iv);
+
+  /* TODO make less crufty */
+
+  /* stuff in real length (big endian) before padding */
+  len[0] = (size & 0xff000000) >> 24;
+  len[1] = (size & 0xff0000) >> 16;
+  len[2] = (size & 0xff00) >> 8;
+  len[3] = (size & 0xff) >> 0;
+  padding = 16 - ((4 + size) % 16);
+  buf_size = 4 + size + padding;
+  buf = GNUNET_malloc (buf_size);
+  GNUNET_memcpy (buf, len, 4);
+  GNUNET_memcpy (buf + 4, pt, size);
+  *ct = GNUNET_malloc (buf_size);
+
+  GNUNET_assert (0 == gcry_cipher_encrypt (handle, *ct, buf_size, buf,
+                                           buf_size));
+  gcry_cipher_close (handle);
+  // AES_cbc_encrypt(pt->data, ct->data, pt->len, &key, iv, AES_ENCRYPT);
+  GNUNET_free (buf);
+  return buf_size;
+}
+
+
+static int
+aes_128_cbc_decrypt (char*ct,
+                     int size,
+                     element_t k,
+                     char **pt)
+{
+  struct GNUNET_CRYPTO_SymmetricSessionKey skey;
+  gcry_cipher_hd_t handle;
+  unsigned char iv[16];
+  char*tmp;
+  uint32_t len;
+
+  init_aes (k, 1, &handle, &skey, iv);
+
+  tmp = GNUNET_malloc (size);
+
+  // AES_cbc_encrypt(ct->data, pt->data, ct->len, &key, iv, AES_DECRYPT);
+  GNUNET_assert (0 == gcry_cipher_decrypt (handle, tmp, size, ct, size));
+  gcry_cipher_close (handle);
+  /* TODO make less crufty */
+
+  /* get real length */
+  len = 0;
+  len = len
+        | ((tmp[0]) << 24) | ((tmp[1]) << 16)
+        | ((tmp[2]) << 8) | ((tmp[3]) << 0);
+  /* truncate any garbage from the padding */
+  *pt = GNUNET_malloc (len);
+  GNUNET_memcpy (*pt, tmp + 4, len);
+  GNUNET_free (tmp);
+  return len;
+}
+
+
+struct GNUNET_CRYPTO_AbeMasterKey*
+GNUNET_CRYPTO_cpabe_create_master_key (void)
+{
+  struct GNUNET_CRYPTO_AbeMasterKey*key;
+
+  key = GNUNET_new (struct GNUNET_CRYPTO_AbeMasterKey);
+  gabe_setup (&key->pub, &key->msk);
+  GNUNET_assert (NULL != key->pub);
+  GNUNET_assert (NULL != key->msk);
+  return key;
+}
+
+
+void
+GNUNET_CRYPTO_cpabe_delete_master_key (struct GNUNET_CRYPTO_AbeMasterKey *key)
+{
+  gabe_msk_free (key->msk);
+  gabe_pub_free (key->pub);
+  // GNUNET_free (key->msk);
+  // gabe_msk_free (key->msk); //For some reason free of pub implicit?
+  GNUNET_free (key);
+}
+
+
+struct GNUNET_CRYPTO_AbeKey*
+GNUNET_CRYPTO_cpabe_create_key (struct GNUNET_CRYPTO_AbeMasterKey *key,
+                                char **attrs)
+{
+  struct GNUNET_CRYPTO_AbeKey *prv_key;
+  int size;
+  char *tmp;
+
+  prv_key = GNUNET_new (struct GNUNET_CRYPTO_AbeKey);
+  prv_key->prv = gabe_keygen (key->pub, key->msk, attrs);
+  size = gabe_pub_serialize (key->pub, &tmp);
+  prv_key->pub = gabe_pub_unserialize (tmp, size);
+  GNUNET_free (tmp);
+  GNUNET_assert (NULL != prv_key->prv);
+  return prv_key;
+}
+
+
+void
+GNUNET_CRYPTO_cpabe_delete_key (struct GNUNET_CRYPTO_AbeKey *key,
+                                int delete_pub)
+{
+  // Memory management in gabe is buggy
+  gabe_prv_free (key->prv);
+  if (GNUNET_YES == delete_pub)
+    gabe_pub_free (key->pub);
+  GNUNET_free (key);
+}
+
+
+ssize_t
+write_cpabe (void **result,
+             uint32_t file_len,
+             char*cph_buf,
+             int cph_buf_len,
+             char*aes_buf,
+             int aes_buf_len)
+{
+  char *ptr;
+  uint32_t *len;
+
+  *result = GNUNET_malloc (12 + cph_buf_len + aes_buf_len);
+  ptr = *result;
+  len = (uint32_t *) ptr;
+  *len = htonl (file_len);
+  ptr += 4;
+  len = (uint32_t *) ptr;
+  *len = htonl (aes_buf_len);
+  ptr += 4;
+  GNUNET_memcpy (ptr, aes_buf, aes_buf_len);
+  ptr += aes_buf_len;
+  len = (uint32_t *) ptr;
+  *len = htonl (cph_buf_len);
+  ptr += 4;
+  GNUNET_memcpy (ptr, cph_buf, cph_buf_len);
+  return 12 + cph_buf_len + aes_buf_len;
+}
+
+
+ssize_t
+read_cpabe (const void *data,
+            char**cph_buf,
+            int *cph_buf_len,
+            char**aes_buf,
+            int *aes_buf_len)
+{
+  int buf_len;
+  char *ptr;
+  uint32_t *len;
+
+  ptr = (char *) data;
+  len = (uint32_t *) ptr;
+  buf_len = ntohl (*len);
+  ptr += 4;
+  len = (uint32_t *) ptr;
+  *aes_buf_len = ntohl (*len);
+  ptr += 4;
+  *aes_buf = GNUNET_malloc (*aes_buf_len);
+  GNUNET_memcpy (*aes_buf, ptr, *aes_buf_len);
+  ptr += *aes_buf_len;
+  len = (uint32_t *) ptr;
+  *cph_buf_len = ntohl (*len);
+  ptr += 4;
+  *cph_buf = GNUNET_malloc (*cph_buf_len);
+  GNUNET_memcpy (*cph_buf, ptr, *cph_buf_len);
+
+  return buf_len;
+}
+
+
+ssize_t
+GNUNET_CRYPTO_cpabe_encrypt (const void *block,
+                             size_t size,
+                             const char *policy,
+                             const struct GNUNET_CRYPTO_AbeMasterKey *key,
+                             void **result)
+{
+  gabe_cph_t*cph;
+  char*plt;
+  char*cph_buf;
+  char*aes_buf;
+  element_t m;
+  int cph_buf_len;
+  int aes_buf_len;
+  ssize_t result_len;
+
+  if (! (cph = gabe_enc (key->pub, m, (char *) policy)))
+    return GNUNET_SYSERR;
+  cph_buf_len = gabe_cph_serialize (cph,
+                                    &cph_buf);
+  gabe_cph_free (cph);
+  GNUNET_free (cph);
+  plt = GNUNET_memdup (block, size);
+  aes_buf_len = aes_128_cbc_encrypt (plt, size, m, &aes_buf);
+  GNUNET_free (plt);
+  element_clear (m);
+  result_len = write_cpabe (result, size, cph_buf, cph_buf_len, aes_buf,
+                            aes_buf_len);
+  GNUNET_free (cph_buf);
+  GNUNET_free (aes_buf);
+  return result_len;
+}
+
+
+ssize_t
+GNUNET_CRYPTO_cpabe_decrypt (const void *block,
+                             size_t size,
+                             const struct GNUNET_CRYPTO_AbeKey *key,
+                             void **result)
+{
+  char*aes_buf;
+  char*cph_buf;
+  gabe_cph_t*cph;
+  element_t m;
+  int cph_buf_size;
+  int aes_buf_size;
+  int plt_len;
+
+  read_cpabe (block, &cph_buf, &cph_buf_size, &aes_buf, &aes_buf_size);
+  cph = gabe_cph_unserialize (key->pub, cph_buf, cph_buf_size);
+  if (! gabe_dec (key->pub, key->prv, cph, m))
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                "%s\n", gabe_error ());
+    GNUNET_free (aes_buf);
+    GNUNET_free (cph_buf);
+    gabe_cph_free (cph);
+    GNUNET_free (cph);
+    element_clear (m);
+    return GNUNET_SYSERR;
+  }
+  gabe_cph_free (cph);
+  GNUNET_free (cph);
+  plt_len = aes_128_cbc_decrypt (aes_buf, aes_buf_size, m, (char **) result);
+  GNUNET_free (cph_buf);
+  GNUNET_free (aes_buf);
+  element_clear (m);
+  // freeing is buggy in gabe
+  // gabe_prv_free (prv);
+  // gabe_pub_free (pub);
+  return plt_len;
+}
+
+
+ssize_t
+GNUNET_CRYPTO_cpabe_serialize_key (const struct GNUNET_CRYPTO_AbeKey *key,
+                                   void **result)
+{
+  ssize_t len;
+  char *pub;
+  char *prv;
+  int pub_len;
+  int prv_len;
+
+  pub_len = gabe_pub_serialize (key->pub, &pub);
+  prv_len = gabe_prv_serialize (key->prv, &prv);
+
+  len = pub_len + prv_len + 12;
+  write_cpabe (result, len, pub, pub_len, prv, prv_len);
+
+  GNUNET_free (pub);
+  GNUNET_free (prv);
+
+  return len;
+}
+
+
+struct GNUNET_CRYPTO_AbeKey*
+GNUNET_CRYPTO_cpabe_deserialize_key (const void *data,
+                                     size_t len)
+{
+  struct GNUNET_CRYPTO_AbeKey *key;
+  char *pub;
+  char *prv;
+  int prv_len;
+  int pub_len;
+
+  key = GNUNET_new (struct GNUNET_CRYPTO_AbeKey);
+  read_cpabe (data,
+              &pub,
+              &pub_len,
+              &prv,
+              &prv_len);
+  key->pub = gabe_pub_unserialize (pub, pub_len);
+  key->prv = gabe_prv_unserialize (key->pub, prv, prv_len);
+
+  GNUNET_free (pub);
+  GNUNET_free (prv);
+  return key;
+}
+
+
+ssize_t
+GNUNET_CRYPTO_cpabe_serialize_master_key (const struct
+                                          GNUNET_CRYPTO_AbeMasterKey *key,
+                                          void **result)
+{
+  ssize_t len;
+  char *pub;
+  char *msk;
+  int pub_len;
+  int msk_len;
+
+  pub_len = gabe_pub_serialize (key->pub, &pub);
+  msk_len = gabe_msk_serialize (key->msk, &msk);
+
+  len = pub_len + msk_len + 12;
+  write_cpabe (result, len, pub, pub_len, msk, msk_len);
+
+  GNUNET_free (pub);
+  GNUNET_free (msk);
+
+  return len;
+}
+
+
+struct GNUNET_CRYPTO_AbeMasterKey*
+GNUNET_CRYPTO_cpabe_deserialize_master_key (const void *data,
+                                            size_t len)
+{
+  struct GNUNET_CRYPTO_AbeMasterKey *key;
+  char *msk;
+  char *pub;
+  int msk_len;
+  int pub_len;
+
+  key = GNUNET_new (struct GNUNET_CRYPTO_AbeMasterKey);
+  read_cpabe (data,
+              &pub,
+              &pub_len,
+              &msk,
+              &msk_len);
+  key->pub = gabe_pub_unserialize (pub, pub_len);
+  key->msk = gabe_msk_unserialize (key->pub, msk, msk_len);
+
+  GNUNET_free (pub);
+  GNUNET_free (msk);
+
+  return key;
+}
diff --git a/src/util/crypto_ecc.c b/src/util/crypto_ecc.c
index e1608ae551d5cfb25735af8dbd0ae2ce1a7f488f..019dbe94ea4aab6750515c3e481456ea127476ab 100644
--- a/src/util/crypto_ecc.c
+++ b/src/util/crypto_ecc.c
@@ -141,7 +141,7 @@ decode_private_ecdsa_key (const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv)
   int rc;
   uint8_t d[32];
 
-  for (size_t i=0; i<32; i++)
+  for (size_t i = 0; i<32; i++)
     d[i] = priv->d[31 - i];
 
   rc = gcry_sexp_build (&result,
@@ -195,7 +195,7 @@ GNUNET_CRYPTO_eddsa_key_get_public (
   struct GNUNET_CRYPTO_EddsaPublicKey *pub)
 {
   unsigned char pk[crypto_sign_PUBLICKEYBYTES];
-  unsigned char sk[crypto_sign_SECRETKEYBYTES]; 
+  unsigned char sk[crypto_sign_SECRETKEYBYTES];
 
   BENCHMARK_START (eddsa_key_get_public);
   GNUNET_assert (0 == crypto_sign_seed_keypair (pk, sk, priv->d));
@@ -929,7 +929,7 @@ GNUNET_CRYPTO_ecdsa_private_key_derive (
 
   h = derive_h (&pub, label, context);
   /* Convert to big endian for libgcrypt */
-  for (size_t i=0; i < 32; i++)
+  for (size_t i = 0; i < 32; i++)
     dc[i] = priv->d[31 - i];
   GNUNET_CRYPTO_mpi_scan_unsigned (&x, dc, sizeof(dc));
   d = gcry_mpi_new (256);
@@ -941,9 +941,9 @@ GNUNET_CRYPTO_ecdsa_private_key_derive (
   ret = GNUNET_new (struct GNUNET_CRYPTO_EcdsaPrivateKey);
   GNUNET_CRYPTO_mpi_print_unsigned (dc, sizeof(dc), d);
   /* Convert to big endian for libgcrypt */
-  for (size_t i=0; i < 32; i++)
+  for (size_t i = 0; i < 32; i++)
     ret->d[i] = dc[31 - i];
-  sodium_memzero(dc, sizeof(dc));
+  sodium_memzero (dc, sizeof(dc));
   gcry_mpi_release (d);
   return ret;
 }
diff --git a/src/util/crypto_hash.c b/src/util/crypto_hash.c
index 62295347688cffec91218e869a627ea93f7113bd..94b6f50999a13d5b834ebe0a93b841fb1b08eec4 100644
--- a/src/util/crypto_hash.c
+++ b/src/util/crypto_hash.c
@@ -94,7 +94,7 @@ GNUNET_CRYPTO_hash_to_enc (const struct GNUNET_HashCode *block,
  * @param result where to store the hash code
  * @return #GNUNET_OK on success, #GNUNET_SYSERR if result has the wrong encoding
  */
-int
+enum GNUNET_GenericReturnValue
 GNUNET_CRYPTO_hash_from_string2 (const char *enc,
                                  size_t enclen,
                                  struct GNUNET_HashCode *result)
@@ -250,12 +250,13 @@ GNUNET_CRYPTO_hash_to_aes_key (const struct GNUNET_HashCode *hc,
  */
 int
 GNUNET_CRYPTO_hash_get_bit_ltr (const struct GNUNET_HashCode *code,
-                            unsigned int bit)
+                                unsigned int bit)
 {
   GNUNET_assert (bit < 8 * sizeof(struct GNUNET_HashCode));
   return (((unsigned char *) code)[bit >> 3] & (128 >> (bit & 7))) > 0;
 }
 
+
 /**
  * Obtain a bit from a hashcode.
  * @param code the GNUNET_CRYPTO_hash to index bit-wise
@@ -272,7 +273,6 @@ GNUNET_CRYPTO_hash_get_bit_rtl (const struct GNUNET_HashCode *code,
 }
 
 
-
 /**
  * Determine how many low order bits match in two
  * `struct GNUNET_HashCode`s.  i.e. - 010011 and 011111 share
diff --git a/src/util/crypto_kdf.c b/src/util/crypto_kdf.c
index 1b3bd686f76680a30f5fdd02d6930f258e9e6ffc..4f3830308399d32b3d2a734927cbc3393b620524 100644
--- a/src/util/crypto_kdf.c
+++ b/src/util/crypto_kdf.c
@@ -62,7 +62,8 @@ GNUNET_CRYPTO_kdf_v (void *result,
    * hash function."
    *
    * http://eprint.iacr.org/2010/264
-   */return GNUNET_CRYPTO_hkdf_v (result,
+   *///
+  return GNUNET_CRYPTO_hkdf_v (result,
                                out_len,
                                GCRY_MD_SHA512,
                                GCRY_MD_SHA256,
@@ -142,7 +143,6 @@ GNUNET_CRYPTO_kdf_mod_mpi (gcry_mpi_t *r,
   {
     /* Ain't clear if n is always divisible by 8 */
     uint8_t buf[ (nbits - 1) / 8 + 1 ];
-
     uint16_t ctr_nbo = htons (ctr);
 
     rc = GNUNET_CRYPTO_kdf (buf,
diff --git a/src/util/crypto_mpi.c b/src/util/crypto_mpi.c
index 0999216116b4ebc3bc254fd734fbdbbe962cb60e..6df47c7e14e8fce53ad89c022fd05f2982c7bb63 100644
--- a/src/util/crypto_mpi.c
+++ b/src/util/crypto_mpi.c
@@ -157,8 +157,8 @@ GNUNET_CRYPTO_mpi_scan_unsigned (gcry_mpi_t *result,
  */
 void
 GNUNET_CRYPTO_mpi_scan_unsigned_le (gcry_mpi_t *result,
-                                 const void *data,
-                                 size_t size)
+                                    const void *data,
+                                    size_t size)
 {
   int rc;
 
diff --git a/src/util/crypto_pow.c b/src/util/crypto_pow.c
index cfa0676d06051e5c6efeb59d46bcb5c5b65b81e2..051a0c209f32cff96247c7580a707c25a3be2e0a 100644
--- a/src/util/crypto_pow.c
+++ b/src/util/crypto_pow.c
@@ -38,12 +38,11 @@
  * @param result where to write the resulting hash
  */
 void
-GNUNET_CRYPTO_pow_hash (const char *salt,
+GNUNET_CRYPTO_pow_hash (const struct GNUNET_CRYPTO_PowSalt *salt,
                         const void *buf,
                         size_t buf_len,
                         struct GNUNET_HashCode *result)
 {
-  GNUNET_assert (strlen (salt) == crypto_pwhash_argon2id_SALTBYTES);
   /* Threads hardcoded at 1 in libsodium */
   GNUNET_break (0 ==
                 crypto_pwhash_argon2id ((unsigned char *) result,
diff --git a/src/util/disk.c b/src/util/disk.c
index cdead59d2e6ceb53e6541ab6700cc6e437eddf96..c95e9753cfc31ffa33496901fd6d26de53885bc6 100644
--- a/src/util/disk.c
+++ b/src/util/disk.c
@@ -1377,14 +1377,13 @@ GNUNET_DISK_file_map (const struct GNUNET_DISK_FileHandle *h,
                       enum GNUNET_DISK_MapType access,
                       size_t len)
 {
+  int prot;
+
   if (NULL == h)
   {
     errno = EINVAL;
     return NULL;
   }
-
-  int prot;
-
   prot = 0;
   if (access & GNUNET_DISK_MAP_TYPE_READ)
     prot = PROT_READ;
@@ -1405,22 +1404,21 @@ GNUNET_DISK_file_map (const struct GNUNET_DISK_FileHandle *h,
 
 /**
  * Unmap a file
+ *
  * @param h mapping handle
- * @return GNUNET_OK on success, GNUNET_SYSERR otherwise
+ * @return #GNUNET_OK on success, #GNUNET_SYSERR otherwise
  */
 int
 GNUNET_DISK_file_unmap (struct GNUNET_DISK_MapHandle *h)
 {
   int ret;
 
-  if (h == NULL)
+  if (NULL == h)
   {
     errno = EINVAL;
     return GNUNET_SYSERR;
   }
-
   ret = munmap (h->addr, h->len) != -1 ? GNUNET_OK : GNUNET_SYSERR;
-
   GNUNET_free (h);
   return ret;
 }
@@ -1429,7 +1427,7 @@ GNUNET_DISK_file_unmap (struct GNUNET_DISK_MapHandle *h)
 /**
  * Write file changes to disk
  * @param h handle to an open file
- * @return GNUNET_OK on success, GNUNET_SYSERR otherwise
+ * @return #GNUNET_OK on success, #GNUNET_SYSERR otherwise
  */
 int
 GNUNET_DISK_file_sync (const struct GNUNET_DISK_FileHandle *h)
@@ -1451,33 +1449,23 @@ GNUNET_DISK_file_sync (const struct GNUNET_DISK_FileHandle *h)
 /**
  * Creates an interprocess channel
  *
- * @param blocking_read creates an asynchronous pipe for reading if set to GNUNET_NO
- * @param blocking_write creates an asynchronous pipe for writing if set to GNUNET_NO
- * @param inherit_read inherit the parent processes stdin (only for windows)
- * @param inherit_write inherit the parent processes stdout (only for windows)
+ * @param pf how to configure the pipe
  * @return handle to the new pipe, NULL on error
  */
 struct GNUNET_DISK_PipeHandle *
-GNUNET_DISK_pipe (int blocking_read,
-                  int blocking_write,
-                  int inherit_read,
-                  int inherit_write)
+GNUNET_DISK_pipe (enum GNUNET_DISK_PipeFlags pf)
 {
   int fd[2];
-  int ret;
-  int eno;
 
-  (void) inherit_read;
-  (void) inherit_write;
-  ret = pipe (fd);
-  if (ret == -1)
+  if (-1 == pipe (fd))
   {
-    eno = errno;
+    int eno = errno;
+
     LOG_STRERROR (GNUNET_ERROR_TYPE_ERROR, "pipe");
     errno = eno;
     return NULL;
   }
-  return GNUNET_DISK_pipe_from_fd (blocking_read, blocking_write, fd);
+  return GNUNET_DISK_pipe_from_fd (pf, fd);
 }
 
 
@@ -1485,29 +1473,26 @@ GNUNET_DISK_pipe (int blocking_read,
  * Creates a pipe object from a couple of file descriptors.
  * Useful for wrapping existing pipe FDs.
  *
- * @param blocking_read creates an asynchronous pipe for reading if set to GNUNET_NO
- * @param blocking_write creates an asynchronous pipe for writing if set to GNUNET_NO
+ * @param pf how to configure the pipe
  * @param fd an array of two fd values. One of them may be -1 for read-only or write-only pipes
  *
  * @return handle to the new pipe, NULL on error
  */
 struct GNUNET_DISK_PipeHandle *
-GNUNET_DISK_pipe_from_fd (int blocking_read, int blocking_write, int fd[2])
+GNUNET_DISK_pipe_from_fd (enum GNUNET_DISK_PipeFlags pf,
+                          int fd[2])
 {
   struct GNUNET_DISK_PipeHandle *p;
-
-  p = GNUNET_new (struct GNUNET_DISK_PipeHandle);
-
-  int ret;
+  int ret = 0;
   int flags;
   int eno = 0; /* make gcc happy */
 
-  ret = 0;
+  p = GNUNET_new (struct GNUNET_DISK_PipeHandle);
   if (fd[0] >= 0)
   {
     p->fd[0] = GNUNET_new (struct GNUNET_DISK_FileHandle);
     p->fd[0]->fd = fd[0];
-    if (! blocking_read)
+    if (0 == (GNUNET_DISK_PF_BLOCKING_READ & pf))
     {
       flags = fcntl (fd[0], F_GETFL);
       flags |= O_NONBLOCK;
@@ -1530,7 +1515,7 @@ GNUNET_DISK_pipe_from_fd (int blocking_read, int blocking_write, int fd[2])
   {
     p->fd[1] = GNUNET_new (struct GNUNET_DISK_FileHandle);
     p->fd[1]->fd = fd[1];
-    if (! blocking_write)
+    if (0 == (GNUNET_DISK_PF_BLOCKING_WRITE & pf))
     {
       flags = fcntl (fd[1], F_GETFL);
       flags |= O_NONBLOCK;
@@ -1562,7 +1547,6 @@ GNUNET_DISK_pipe_from_fd (int blocking_read, int blocking_write, int fd[2])
     errno = eno;
     return NULL;
   }
-
   return p;
 }
 
@@ -1572,7 +1556,7 @@ GNUNET_DISK_pipe_from_fd (int blocking_read, int blocking_write, int fd[2])
  *
  * @param p pipe to close
  * @param end which end of the pipe to close
- * @return GNUNET_OK on success, GNUNET_SYSERR otherwise
+ * @return #GNUNET_OK on success, #GNUNET_SYSERR otherwise
  */
 int
 GNUNET_DISK_pipe_close_end (struct GNUNET_DISK_PipeHandle *p,
@@ -1644,7 +1628,7 @@ GNUNET_DISK_pipe_detach_end (struct GNUNET_DISK_PipeHandle *p,
  * Closes an interprocess channel
  *
  * @param p pipe to close
- * @return GNUNET_OK on success, GNUNET_SYSERR otherwise
+ * @return #GNUNET_OK on success, #GNUNET_SYSERR otherwise
  */
 int
 GNUNET_DISK_pipe_close (struct GNUNET_DISK_PipeHandle *p)
diff --git a/src/util/gnunet-qr.c b/src/util/gnunet-qr.c
index cd23c3a9ccb4489e5277e8103bc36988d75dabb9..451d61d4073a1eabcc7b1e5a73da32d1d255ed7c 100644
--- a/src/util/gnunet-qr.c
+++ b/src/util/gnunet-qr.c
@@ -31,12 +31,12 @@
 
 #define LOG(fmt, ...)  \
   if (verbose) \
-    printf (fmt, ## __VA_ARGS__)
+  printf (fmt, ## __VA_ARGS__)
 
 /**
  * Video device to capture from. Sane default for GNU/Linux systems.
  */
-static char *device = "/dev/video0";
+static char *device;
 
 /**
  * --verbose option
@@ -51,7 +51,7 @@ static int silent = false;
 /**
  * Handler exit code
  */
-static long unsigned int exit_code = 1;
+static long unsigned int exit_code = 0;
 
 /**
  * Helper process we started.
@@ -161,10 +161,7 @@ gnunet_uri (void *cls,
     return;
   }
   GNUNET_free (subsystem);
-  sigpipe = GNUNET_DISK_pipe (GNUNET_NO,
-                              GNUNET_NO,
-                              GNUNET_NO,
-                              GNUNET_NO);
+  sigpipe = GNUNET_DISK_pipe (GNUNET_DISK_PF_NONE);
   GNUNET_assert (NULL != sigpipe);
   rt = GNUNET_SCHEDULER_add_read_file (
     GNUNET_TIME_UNIT_FOREVER_REL,
@@ -192,8 +189,7 @@ gnunet_uri (void *cls,
     GNUNET_array_append (argv,
                          argc,
                          NULL);
-    p = GNUNET_OS_start_process_vap (GNUNET_NO,
-                                     GNUNET_OS_INHERIT_STD_ALL,
+    p = GNUNET_OS_start_process_vap (GNUNET_OS_INHERIT_STD_ALL,
                                      NULL,
                                      NULL,
                                      NULL,
@@ -232,6 +228,8 @@ get_symbol (zbar_processor_t *proc)
   }
 
   /* initialize the Processor */
+  if (NULL == device)
+    device = GNUNET_strdup ("/dev/video0");
   if (0 != (rc = zbar_processor_init (proc, device, 1)))
   {
     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
@@ -310,6 +308,7 @@ run_zbar ()
   ret = GNUNET_strdup (data);
   /* clean up */
   zbar_processor_destroy (proc);
+  GNUNET_free (device);
   return ret;
 }
 
diff --git a/src/util/gnunet-scrypt.c b/src/util/gnunet-scrypt.c
index aa64144a88d59ade2f2150b31d28e1f226098a9b..136c6debb44fee3fb266816de8807d5832515ed4 100644
--- a/src/util/gnunet-scrypt.c
+++ b/src/util/gnunet-scrypt.c
@@ -26,6 +26,13 @@
 #include "gnunet_util_lib.h"
 #include <gcrypt.h>
 
+
+/**
+ * Salt for PoW calcualations.
+ */
+static struct GNUNET_CRYPTO_PowSalt salt = { "gnunet-nse-proof" };
+
+
 /**
  * Amount of work required (W-bit collisions) for NSE proofs, in collision-bits.
  */
@@ -117,7 +124,7 @@ find_proof (void *cls)
   while ((counter != UINT64_MAX) && (i < ROUND_SIZE))
   {
     GNUNET_memcpy (buf, &counter, sizeof(uint64_t));
-    GNUNET_CRYPTO_pow_hash ("gnunet-nse-proof",
+    GNUNET_CRYPTO_pow_hash (&salt,
                             buf,
                             sizeof(buf),
                             &result);
diff --git a/src/util/gnunet-uri.c b/src/util/gnunet-uri.c
index 48c46ee49eaddb69319b611dec480508e1302868..de0ff1f925742b252a5cada1dc38de29bf1ab368 100644
--- a/src/util/gnunet-uri.c
+++ b/src/util/gnunet-uri.c
@@ -29,7 +29,7 @@
 /**
  * Handler exit code
  */
-static long unsigned int exit_code = 1;
+static long unsigned int exit_code = 0;
 
 /**
  * Helper process we started.
@@ -115,8 +115,7 @@ run (void *cls,
     GNUNET_DISK_pipe_handle (sigpipe, GNUNET_DISK_PIPE_END_READ),
     &maint_child_death,
     NULL);
-  p = GNUNET_OS_start_process (GNUNET_NO,
-                               0,
+  p = GNUNET_OS_start_process (GNUNET_OS_INHERIT_STD_NONE,
                                NULL,
                                NULL,
                                NULL,
@@ -168,7 +167,7 @@ main (int argc, char *const *argv)
 
   if (GNUNET_OK != GNUNET_STRINGS_get_utf8_args (argc, argv, &argc, &argv))
     return 2;
-  sigpipe = GNUNET_DISK_pipe (GNUNET_NO, GNUNET_NO, GNUNET_NO, GNUNET_NO);
+  sigpipe = GNUNET_DISK_pipe (GNUNET_DISK_PF_NONE);
   GNUNET_assert (sigpipe != NULL);
   shc_chld =
     GNUNET_SIGNAL_handler_install (GNUNET_SIGCHLD, &sighandler_child_death);
diff --git a/src/util/helper.c b/src/util/helper.c
index 8c8fb7b6a14cc2fdcb01acfce35e57366470c003..7360b7d4b7a59e765548d76888ce844e2bfc21a7 100644
--- a/src/util/helper.c
+++ b/src/util/helper.c
@@ -401,9 +401,9 @@ static void
 start_helper (struct GNUNET_HELPER_Handle *h)
 {
   h->helper_in =
-    GNUNET_DISK_pipe (GNUNET_YES, GNUNET_YES, GNUNET_YES, GNUNET_NO);
+    GNUNET_DISK_pipe (GNUNET_DISK_PF_BLOCKING_RW);
   h->helper_out =
-    GNUNET_DISK_pipe (GNUNET_YES, GNUNET_YES, GNUNET_NO, GNUNET_YES);
+    GNUNET_DISK_pipe (GNUNET_DISK_PF_BLOCKING_RW);
   if ((h->helper_in == NULL) || (h->helper_out == NULL))
   {
     /* out of file descriptors? try again later... */
@@ -422,8 +422,10 @@ start_helper (struct GNUNET_HELPER_Handle *h)
     GNUNET_DISK_pipe_handle (h->helper_out, GNUNET_DISK_PIPE_END_READ);
   h->fh_to_helper =
     GNUNET_DISK_pipe_handle (h->helper_in, GNUNET_DISK_PIPE_END_WRITE);
-  h->helper_proc = GNUNET_OS_start_process_vap (h->with_control_pipe,
-                                                GNUNET_OS_INHERIT_STD_ERR,
+  h->helper_proc = GNUNET_OS_start_process_vap (h->with_control_pipe
+                                                ? GNUNET_OS_INHERIT_STD_ERR
+                                                | GNUNET_OS_USE_PIPE_CONTROL
+                                                : GNUNET_OS_INHERIT_STD_ERR,
                                                 h->helper_in,
                                                 h->helper_out,
                                                 NULL,
diff --git a/src/util/mq.c b/src/util/mq.c
index 302b310dee0d24d5d66134890ea350ce4377a8c3..29ead02a4b1480d85347e1e1015c6423efd61caa 100644
--- a/src/util/mq.c
+++ b/src/util/mq.c
@@ -273,7 +273,7 @@ GNUNET_MQ_handle_message (const struct GNUNET_MQ_MessageHandler *handlers,
       break;
     }
   }
-done:
+  done:
   if (GNUNET_NO == handled)
   {
     LOG (GNUNET_ERROR_TYPE_INFO,
@@ -355,6 +355,10 @@ void
 GNUNET_MQ_send (struct GNUNET_MQ_Handle *mq,
                 struct GNUNET_MQ_Envelope *ev)
 {
+  if (NULL == mq)
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                "mq is NUll when sending message of type %u\n",
+                (unsigned int) ntohs (ev->mh->type));
   GNUNET_assert (NULL != mq);
   GNUNET_assert (NULL == ev->parent_queue);
 
diff --git a/src/util/os_priority.c b/src/util/os_priority.c
index 5799d893bf7f803181fb82cbed5edd5d58863ccf..8d045c72b23af29f18975290ace955f0350a8f6c 100644
--- a/src/util/os_priority.c
+++ b/src/util/os_priority.c
@@ -326,7 +326,6 @@ open_dev_null (int target_fd, int flags)
 /**
  * Start a process.
  *
- * @param pipe_control should a pipe be used to send signals to the child?
  * @param std_inheritance a set of GNUNET_OS_INHERIT_STD_* flags controlling which
  *        std handles of the parent are inherited by the child.
  *        pipe_stdin and pipe_stdout take priority over std_inheritance
@@ -341,8 +340,7 @@ open_dev_null (int target_fd, int flags)
  * @return process ID of the new process, -1 on error
  */
 static struct GNUNET_OS_Process *
-start_process (int pipe_control,
-               enum GNUNET_OS_InheritStdioFlags std_inheritance,
+start_process (enum GNUNET_OS_InheritStdioFlags std_inheritance,
                struct GNUNET_DISK_PipeHandle *pipe_stdin,
                struct GNUNET_DISK_PipeHandle *pipe_stdout,
                struct GNUNET_DISK_PipeHandle *pipe_stderr,
@@ -373,12 +371,12 @@ start_process (int pipe_control,
   if (GNUNET_SYSERR ==
       GNUNET_OS_check_helper_binary (filename, GNUNET_NO, NULL))
     return NULL; /* not executable */
-  if (GNUNET_YES == pipe_control)
+  if (0 != (std_inheritance & GNUNET_OS_USE_PIPE_CONTROL))
   {
     struct GNUNET_DISK_PipeHandle *childpipe;
     int dup_childpipe_read_fd = -1;
 
-    childpipe = GNUNET_DISK_pipe (GNUNET_NO, GNUNET_NO, GNUNET_YES, GNUNET_NO);
+    childpipe = GNUNET_DISK_pipe (GNUNET_DISK_PF_NONE);
     if (NULL == childpipe)
       return NULL;
     childpipe_read =
@@ -486,7 +484,7 @@ start_process (int pipe_control,
     gnunet_proc = GNUNET_new (struct GNUNET_OS_Process);
     gnunet_proc->pid = ret;
     gnunet_proc->control_pipe = childpipe_write;
-    if (GNUNET_YES == pipe_control)
+    if (0 != (std_inheritance & GNUNET_OS_USE_PIPE_CONTROL))
     {
       close (childpipe_read_fd);
     }
@@ -594,7 +592,6 @@ start_process (int pipe_control,
 /**
  * Start a process.
  *
- * @param pipe_control should a pipe be used to send signals to the child?
  * @param std_inheritance a set of GNUNET_OS_INHERIT_STD_* flags
  * @param pipe_stdin pipe to use to send input to child process (or NULL)
  * @param pipe_stdout pipe to use to get output from child process (or NULL)
@@ -604,16 +601,14 @@ start_process (int pipe_control,
  * @return pointer to process structure of the new process, NULL on error
  */
 struct GNUNET_OS_Process *
-GNUNET_OS_start_process_vap (int pipe_control,
-                             enum GNUNET_OS_InheritStdioFlags std_inheritance,
+GNUNET_OS_start_process_vap (enum GNUNET_OS_InheritStdioFlags std_inheritance,
                              struct GNUNET_DISK_PipeHandle *pipe_stdin,
                              struct GNUNET_DISK_PipeHandle *pipe_stdout,
                              struct GNUNET_DISK_PipeHandle *pipe_stderr,
                              const char *filename,
                              char *const argv[])
 {
-  return start_process (pipe_control,
-                        std_inheritance,
+  return start_process (std_inheritance,
                         pipe_stdin,
                         pipe_stdout,
                         pipe_stderr,
@@ -626,7 +621,6 @@ GNUNET_OS_start_process_vap (int pipe_control,
 /**
  * Start a process.
  *
- * @param pipe_control should a pipe be used to send signals to the child?
  * @param std_inheritance a set of GNUNET_OS_INHERIT_STD_* flags
  * @param pipe_stdin pipe to use to send input to child process (or NULL)
  * @param pipe_stdout pipe to use to get output from child process (or NULL)
@@ -636,8 +630,7 @@ GNUNET_OS_start_process_vap (int pipe_control,
  * @return pointer to process structure of the new process, NULL on error
  */
 struct GNUNET_OS_Process *
-GNUNET_OS_start_process_va (int pipe_control,
-                            enum GNUNET_OS_InheritStdioFlags std_inheritance,
+GNUNET_OS_start_process_va (enum GNUNET_OS_InheritStdioFlags std_inheritance,
                             struct GNUNET_DISK_PipeHandle *pipe_stdin,
                             struct GNUNET_DISK_PipeHandle *pipe_stdout,
                             struct GNUNET_DISK_PipeHandle *pipe_stderr,
@@ -660,8 +653,7 @@ GNUNET_OS_start_process_va (int pipe_control,
   while (NULL != (argv[argc] = va_arg (ap, char *)))
     argc++;
   va_end (ap);
-  ret = GNUNET_OS_start_process_vap (pipe_control,
-                                     std_inheritance,
+  ret = GNUNET_OS_start_process_vap (std_inheritance,
                                      pipe_stdin,
                                      pipe_stdout,
                                      pipe_stderr,
@@ -675,7 +667,6 @@ GNUNET_OS_start_process_va (int pipe_control,
 /**
  * Start a process.
  *
- * @param pipe_control should a pipe be used to send signals to the child?
  * @param std_inheritance a set of GNUNET_OS_INHERIT_STD_* flags
  * @param pipe_stdin pipe to use to send input to child process (or NULL)
  * @param pipe_stdout pipe to use to get output from child process (or NULL)
@@ -684,8 +675,7 @@ GNUNET_OS_start_process_va (int pipe_control,
  * @return pointer to process structure of the new process, NULL on error
  */
 struct GNUNET_OS_Process *
-GNUNET_OS_start_process (int pipe_control,
-                         enum GNUNET_OS_InheritStdioFlags std_inheritance,
+GNUNET_OS_start_process (enum GNUNET_OS_InheritStdioFlags std_inheritance,
                          struct GNUNET_DISK_PipeHandle *pipe_stdin,
                          struct GNUNET_DISK_PipeHandle *pipe_stdout,
                          struct GNUNET_DISK_PipeHandle *pipe_stderr,
@@ -696,8 +686,7 @@ GNUNET_OS_start_process (int pipe_control,
   va_list ap;
 
   va_start (ap, filename);
-  ret = GNUNET_OS_start_process_va (pipe_control,
-                                    std_inheritance,
+  ret = GNUNET_OS_start_process_va (std_inheritance,
                                     pipe_stdin,
                                     pipe_stdout,
                                     pipe_stderr,
@@ -711,7 +700,6 @@ GNUNET_OS_start_process (int pipe_control,
 /**
  * Start a process.
  *
- * @param pipe_control should a pipe be used to send signals to the child?
  * @param std_inheritance a set of GNUNET_OS_INHERIT_STD_* flags controlling which
  *        std handles of the parent are inherited by the child.
  *        pipe_stdin and pipe_stdout take priority over std_inheritance
@@ -723,14 +711,12 @@ GNUNET_OS_start_process (int pipe_control,
  * @return process ID of the new process, -1 on error
  */
 struct GNUNET_OS_Process *
-GNUNET_OS_start_process_v (int pipe_control,
-                           enum GNUNET_OS_InheritStdioFlags std_inheritance,
+GNUNET_OS_start_process_v (enum GNUNET_OS_InheritStdioFlags std_inheritance,
                            const int *lsocks,
                            const char *filename,
                            char *const argv[])
 {
-  return start_process (pipe_control,
-                        std_inheritance,
+  return start_process (std_inheritance,
                         NULL,
                         NULL,
                         NULL,
@@ -747,7 +733,6 @@ GNUNET_OS_start_process_v (int pipe_control,
  * in the order they appear.  Arguments containing spaces can be used by
  * quoting them with @em ".
  *
- * @param pipe_control should a pipe be used to send signals to the child?
  * @param std_inheritance a set of GNUNET_OS_INHERIT_STD_* flags
  * @param lsocks array of listen sockets to dup systemd-style (or NULL);
  *         must be NULL on platforms where dup is not supported
@@ -759,8 +744,7 @@ GNUNET_OS_start_process_v (int pipe_control,
  * @return pointer to process structure of the new process, NULL on error
  */
 struct GNUNET_OS_Process *
-GNUNET_OS_start_process_s (int pipe_control,
-                           unsigned int std_inheritance,
+GNUNET_OS_start_process_s (enum GNUNET_OS_InheritStdioFlags std_inheritance,
                            const int *lsocks,
                            const char *filename,
                            ...)
@@ -869,8 +853,7 @@ GNUNET_OS_start_process_s (int pipe_control,
     }
   }
   binary_path = argv[0];
-  proc = GNUNET_OS_start_process_v (pipe_control,
-                                    std_inheritance,
+  proc = GNUNET_OS_start_process_v (std_inheritance,
                                     lsocks,
                                     binary_path,
                                     argv);
@@ -1169,13 +1152,18 @@ GNUNET_OS_command_run (GNUNET_OS_LineProcessor proc,
   struct GNUNET_DISK_PipeHandle *opipe;
   va_list ap;
 
-  opipe = GNUNET_DISK_pipe (GNUNET_YES, GNUNET_YES, GNUNET_NO, GNUNET_YES);
+  opipe = GNUNET_DISK_pipe (GNUNET_DISK_PF_BLOCKING_RW);
   if (NULL == opipe)
     return NULL;
   va_start (ap, binary);
   /* redirect stdout, don't inherit stderr/stdin */
   eip =
-    GNUNET_OS_start_process_va (GNUNET_NO, 0, NULL, opipe, NULL, binary, ap);
+    GNUNET_OS_start_process_va (GNUNET_OS_INHERIT_STD_NONE,
+                                NULL,
+                                opipe,
+                                NULL,
+                                binary,
+                                ap);
   va_end (ap);
   if (NULL == eip)
   {
diff --git a/src/util/perf_malloc.c b/src/util/perf_malloc.c
index 6582505c8e9ee009713b5e8810975f68898bf9aa..1c91402da6f54d66707084929a2c0b1cb1f39e1c 100644
--- a/src/util/perf_malloc.c
+++ b/src/util/perf_malloc.c
@@ -56,11 +56,11 @@ perf_realloc ()
     ptr = GNUNET_malloc (i);
     memset (ptr, 1, i);
     ptr = GNUNET_realloc (ptr, i + 5);
-    for (size_t j=0;j<i;j++)
+    for (size_t j = 0; j<i; j++)
       GNUNET_assert (1 == ptr[j]);
     memset (ptr, 6, i + 5);
     ptr = GNUNET_realloc (ptr, i - 5);
-    for (size_t j=0;j<i-5;j++)
+    for (size_t j = 0; j<i - 5; j++)
       GNUNET_assert (6 == ptr[j]);
     GNUNET_free (ptr);
   }
diff --git a/src/util/perf_scheduler.c b/src/util/perf_scheduler.c
index 3ea76e24cd308445bc12fdaf0a2572800f8be73f..4d4d0a228bfc17a82bd74382e5356bc875c94336 100644
--- a/src/util/perf_scheduler.c
+++ b/src/util/perf_scheduler.c
@@ -94,8 +94,8 @@ main (int argc, char *argv[])
             GNUNET_YES));
   GAUGER ("UTIL", "Scheduler",
           tasks / 1024 / (1
-                       + GNUNET_TIME_absolute_get_duration
-                         (start).rel_value_us / 1000LL), "tasks/ms");
+                          + GNUNET_TIME_absolute_get_duration
+                            (start).rel_value_us / 1000LL), "tasks/ms");
   return 0;
 }
 
diff --git a/src/util/scheduler.c b/src/util/scheduler.c
index 93393bd7c975bc1ecd0c1dffabe5f32ee9de46f2..b5ce202548a1f2d15fb57febd218a7cd5de45ba9 100644
--- a/src/util/scheduler.c
+++ b/src/util/scheduler.c
@@ -2214,10 +2214,7 @@ GNUNET_SCHEDULER_driver_init (const struct GNUNET_SCHEDULER_Driver *driver)
   GNUNET_assert (NULL == shutdown_pipe_handle);
   /* general set-up */
   sh = GNUNET_new (struct GNUNET_SCHEDULER_Handle);
-  shutdown_pipe_handle = GNUNET_DISK_pipe (GNUNET_NO,
-                                           GNUNET_NO,
-                                           GNUNET_NO,
-                                           GNUNET_NO);
+  shutdown_pipe_handle = GNUNET_DISK_pipe (GNUNET_DISK_PF_NONE);
   GNUNET_assert (NULL != shutdown_pipe_handle);
   pr = GNUNET_DISK_pipe_handle (shutdown_pipe_handle,
                                 GNUNET_DISK_PIPE_END_READ);
diff --git a/src/util/service.c b/src/util/service.c
index 1b80c8d138b6ba3cc4b7cd5106aa6239de9ee746..ddd31181d4e9af17846013c4fd5872cbdbf2782f 100644
--- a/src/util/service.c
+++ b/src/util/service.c
@@ -473,7 +473,7 @@ check_ipv6_listed (const struct GNUNET_STRINGS_IPv6NetworkPolicy *list,
     return GNUNET_NO;
   i = 0;
 NEXT:
-  while (0 != GNUNET_is_zero (&list[i].network))
+  while (GNUNET_NO == GNUNET_is_zero (&list[i].network))
   {
     for (unsigned int j = 0; j < sizeof(struct in6_addr) / sizeof(int); j++)
       if (((((int *) ip)[j] & ((int *) &list[i].netmask)[j])) !=
@@ -2021,8 +2021,8 @@ GNUNET_SERVICE_run_ (int argc,
   sh.disconnect_cb = disconnect_cb;
   sh.cb_cls = cls;
   sh.handlers = (NULL == pd->agpl_url)
-    ? GNUNET_MQ_copy_handlers (handlers)
-    : GNUNET_MQ_copy_handlers2 (handlers, &return_agpl, NULL);
+                ? GNUNET_MQ_copy_handlers (handlers)
+                : GNUNET_MQ_copy_handlers2 (handlers, &return_agpl, NULL);
   sh.service_name = service_name;
   sh.ret = 0;
   /* setup subsystems */
diff --git a/src/util/socks.c b/src/util/socks.c
new file mode 100644
index 0000000000000000000000000000000000000000..7ab2972726dee981f3bbf47019b3365b54c2ba77
--- /dev/null
+++ b/src/util/socks.c
@@ -0,0 +1,689 @@
+/*
+     This file is part of GNUnet.
+     Copyright (C) 2009-2013 GNUnet e.V.
+
+     GNUnet is free software: you can redistribute it and/or modify it
+     under the terms of the GNU Affero General Public License as published
+     by the Free Software Foundation, either version 3 of the License,
+     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
+     Affero General Public License for more details.
+
+     You should have received a copy of the GNU Affero General Public License
+     along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+     SPDX-License-Identifier: AGPL3.0-or-later
+ */
+
+/**
+ * @file util/socks.c
+ * @brief  SOCKS5 connection support
+ * @author Jeffrey Burdges
+ *
+ * These routines should be called only on newly active connections.
+ */
+#include "platform.h"
+#include "gnunet_util_lib.h"
+
+
+#define LOG(kind, ...) GNUNET_log_from (kind, "util-socks", __VA_ARGS__)
+
+#define LOG_STRERROR(kind, syscall) \
+  GNUNET_log_from_strerror (kind, "util-socks", syscall)
+
+
+/* SOCKS5 authentication methods */
+#define SOCKS5_AUTH_REJECT 0xFF /* No acceptable auth method */
+#define SOCKS5_AUTH_NOAUTH 0x00 /* without authentication */
+#define SOCKS5_AUTH_GSSAPI 0x01 /* GSSAPI */
+#define SOCKS5_AUTH_USERPASS 0x02 /* User/Password */
+#define SOCKS5_AUTH_CHAP 0x03 /* Challenge-Handshake Auth Proto. */
+#define SOCKS5_AUTH_EAP 0x05 /* Extensible Authentication Proto. */
+#define SOCKS5_AUTH_MAF 0x08 /* Multi-Authentication Framework */
+
+
+/* SOCKS5 connection responces */
+#define SOCKS5_REP_SUCCEEDED 0x00 /* succeeded */
+#define SOCKS5_REP_FAIL 0x01 /* general SOCKS serer failure */
+#define SOCKS5_REP_NALLOWED 0x02 /* connection not allowed by ruleset */
+#define SOCKS5_REP_NUNREACH 0x03 /* Network unreachable */
+#define SOCKS5_REP_HUNREACH 0x04 /* Host unreachable */
+#define SOCKS5_REP_REFUSED 0x05 /* connection refused */
+#define SOCKS5_REP_EXPIRED 0x06 /* TTL expired */
+#define SOCKS5_REP_CNOTSUP 0x07 /* Command not supported */
+#define SOCKS5_REP_ANOTSUP 0x08 /* Address not supported */
+#define SOCKS5_REP_INVADDR 0x09 /* Inalid address */
+
+const char *
+SOCKS5_REP_names (int rep)
+{
+  switch (rep)
+  {
+  case SOCKS5_REP_SUCCEEDED:
+    return "succeeded";
+
+  case SOCKS5_REP_FAIL:
+    return "general SOCKS server failure";
+
+  case SOCKS5_REP_NALLOWED:
+    return "connection not allowed by ruleset";
+
+  case SOCKS5_REP_NUNREACH:
+    return "Network unreachable";
+
+  case SOCKS5_REP_HUNREACH:
+    return "Host unreachable";
+
+  case SOCKS5_REP_REFUSED:
+    return "connection refused";
+
+  case SOCKS5_REP_EXPIRED:
+    return "TTL expired";
+
+  case SOCKS5_REP_CNOTSUP:
+    return "Command not supported";
+
+  case SOCKS5_REP_ANOTSUP:
+    return "Address not supported";
+
+  case SOCKS5_REP_INVADDR:
+    return "Invalid address";
+
+  default:
+    return NULL;
+  }
+};
+
+
+/**
+ * Encode a string for the SOCKS5 protocol by prefixing it a byte stating its
+ * length and stripping the trailing zero byte.  Truncates any string longer
+ * than 255 bytes.
+ *
+ * @param b buffer to contain the encoded string
+ * @param s string to encode
+ * @return pointer to the end of the encoded string in the buffer
+ */
+unsigned char *
+SOCK5_proto_string (unsigned char *b, const char *s)
+{
+  size_t l = strlen (s);
+
+  if (l > 255)
+  {
+    LOG (GNUNET_ERROR_TYPE_WARNING,
+         "SOCKS5 cannot handle hostnames, usernames, or passwords over 255 bytes, truncating.\n");
+    l = 255;
+  }
+  *(b++) = (unsigned char) l;
+  memcpy (b, s, l);
+  return b + l;
+}
+
+
+#define SOCKS5_step_greet 0
+#define SOCKS5_step_auth 1
+#define SOCKS5_step_cmd 2
+#define SOCKS5_step_done 3
+
+/**
+ * State of the SOCKS5 handshake.
+ */
+struct GNUNET_SOCKS_Handshake
+{
+  /**
+   * Connection handle used for SOCKS5
+   */
+  struct GNUNET_CONNECTION_Handle *socks5_connection;
+
+  /**
+   * Connection handle initially returned to client
+   */
+  struct GNUNET_CONNECTION_Handle *target_connection;
+
+  /**
+   * Transmission handle on socks5_connection.
+   */
+  struct GNUNET_CONNECTION_TransmitHandle *th;
+
+  /**
+   * Our stage in the SOCKS5 handshake
+   */
+  int step;
+
+  /**
+   * Precomputed SOCKS5 handshake ouput buffer
+   */
+  unsigned char outbuf[1024];
+
+  /**
+   * Pointers delineating protoocol steps in the outbut buffer
+   */
+  unsigned char *(outstep[4]);
+
+  /**
+   * SOCKS5 handshake input buffer
+   */
+  unsigned char inbuf[1024];
+
+  /**
+   * Pointers delimiting the current step in the input buffer
+   */
+  unsigned char *instart;
+  unsigned char *inend;
+};
+
+
+/* Regitering prototypes */
+
+void
+register_reciever (struct GNUNET_SOCKS_Handshake *ih, int want);
+
+/* In fact, the client sends first rule in GNUnet suggests one could take
+ * large mac read sizes without fear of screwing up the proxied protocol,
+ * but we make a proper SOCKS5 client. */
+#define register_reciever_wants(ih) ((SOCKS5_step_cmd == ih->step) ? 10 : 2)
+
+
+struct GNUNET_CONNECTION_TransmitHandle *
+register_sender (struct GNUNET_SOCKS_Handshake *ih);
+
+
+/**
+ * Conclude the SOCKS5 handshake successfully.
+ *
+ * @param ih SOCKS5 handshake, consumed here.
+ * @param c open unused connection, consumed here.
+ * @return Connection handle that becomes usable when the handshake completes.
+ */
+void
+SOCKS5_handshake_done (struct GNUNET_SOCKS_Handshake *ih)
+{
+  GNUNET_CONNECTION_acivate_proxied (ih->target_connection);
+}
+
+
+/**
+ * Read one step in the SOCKS5 handshake.
+ *
+ * @param ih SOCKS5 Handshake
+ */
+void
+SOCKS5_handshake_step (struct GNUNET_SOCKS_Handshake *ih)
+{
+  unsigned char *b = ih->instart;
+  size_t available = ih->inend - b;
+
+  int want = register_reciever_wants (ih);
+
+  if (available < want)
+  {
+    register_reciever (ih, want - available);
+    return;
+  }
+  GNUNET_assert (SOCKS5_step_done > ih->step && ih->step >= 0);
+  switch (ih->step)
+  {
+  case SOCKS5_step_greet:   /* SOCKS5 server's greeting */
+    if (b[0] != 5)
+    {
+      LOG (GNUNET_ERROR_TYPE_ERROR, "Not a SOCKS5 server\n");
+      GNUNET_assert (0);
+    }
+    switch (b[1])
+    {
+    case SOCKS5_AUTH_NOAUTH:
+      ih->step = SOCKS5_step_cmd;     /* no authentication to do */
+      break;
+
+    case SOCKS5_AUTH_USERPASS:
+      ih->step = SOCKS5_step_auth;
+      break;
+
+    case SOCKS5_AUTH_REJECT:
+      LOG (GNUNET_ERROR_TYPE_ERROR, "No authentication method accepted\n");
+      return;
+
+    default:
+      LOG (GNUNET_ERROR_TYPE_ERROR,
+           "Not a SOCKS5 server / Nonsensical authentication\n");
+      return;
+    }
+    b += 2;
+    break;
+
+  case SOCKS5_step_auth:   /* SOCKS5 server's responce to authentication */
+    if (b[1] != 0)
+    {
+      LOG (GNUNET_ERROR_TYPE_ERROR, "SOCKS5 authentication failed\n");
+      GNUNET_assert (0);
+    }
+    ih->step = SOCKS5_step_cmd;
+    b += 2;
+    break;
+
+  case SOCKS5_step_cmd:   /* SOCKS5 server's responce to command */
+    if (b[0] != 5)
+    {
+      LOG (GNUNET_ERROR_TYPE_ERROR, "SOCKS5 protocol error\n");
+      GNUNET_assert (0);
+    }
+    if (0 != b[1])
+    {
+      LOG (GNUNET_ERROR_TYPE_ERROR,
+           "SOCKS5 connection error : %s\n",
+           SOCKS5_REP_names (b[1]));
+      return;
+    }
+    b += 3;
+    /* There is no reason to verify host and port afaik. */
+    switch (*(b++))
+    {
+    case 1:     /* IPv4 */
+      b += sizeof(struct in_addr);     /* 4 */
+      break;
+
+    case 4:     /* IPv6 */
+      b += sizeof(struct in6_addr);     /* 16 */
+      break;
+
+    case 3:     /* hostname */
+      b += *b;
+      break;
+    }
+    b += 2;   /* port */
+    if (b > ih->inend)
+    {
+      register_reciever (ih, b - ih->inend);
+      return;
+    }
+    ih->step = SOCKS5_step_done;
+    LOG (GNUNET_ERROR_TYPE_DEBUG,
+         "SOCKS5 server : %s\n",
+         SOCKS5_REP_names (b[1]));
+    ih->instart = b;
+    SOCKS5_handshake_done (ih);
+    return;
+
+  case SOCKS5_step_done:
+    GNUNET_assert (0);
+  }
+  ih->instart = b;
+  /* Do not reschedule the sender unless we're done reading.
+   * I imagine this lets us avoid ever cancelling the transmit handle. */
+  register_sender (ih);
+}
+
+
+/**
+ * Callback to read from the SOCKS5 proxy.
+ *
+ * @param client the service
+ * @param handler function to call with the message
+ * @param handler_cls closure for @a handler
+ */
+void
+reciever (void *cls,
+          const void *buf,
+          size_t available,
+          const struct sockaddr *addr,
+          socklen_t addrlen,
+          int errCode)
+{
+  struct GNUNET_SOCKS_Handshake *ih = cls;
+
+  GNUNET_assert (&ih->inend[available] < &ih->inbuf[1024]);
+  GNUNET_memcpy (ih->inend, buf, available);
+  ih->inend += available;
+  SOCKS5_handshake_step (ih);
+}
+
+
+/**
+ * Register callback to read from the SOCKS5 proxy.
+ *
+ * @param client the service
+ * @param handler function to call with the message
+ * @param handler_cls closure for @a handler
+ */
+void
+register_reciever (struct GNUNET_SOCKS_Handshake *ih, int want)
+{
+  GNUNET_CONNECTION_receive (ih->socks5_connection,
+                             want,
+                             GNUNET_TIME_relative_get_minute_ (),
+                             &reciever,
+                             ih);
+}
+
+
+/**
+ * Register SOCKS5 handshake sender
+ *
+ * @param cls closure (SOCKS handshake)
+ * @param size number of bytes available in @a buf
+ * @param buf where the callee should write the message
+ * @return number of bytes written to @a buf
+ */
+size_t
+transmit_ready (void *cls, size_t size, void *buf)
+{
+  struct GNUNET_SOCKS_Handshake *ih = cls;
+
+  /* connection.c has many routines that call us with buf == NULL :
+   * signal_transmit_error() - DNS, etc. active
+   *   connect_fail_continuation()
+   *     connect_probe_continuation() - timeout
+   *     try_connect_using_address() - DNS failure/timeout
+   *     transmit_timeout() - retry failed?
+   * GNUNET_CONNECTION_notify_transmit_ready() can schedule :
+   *   transmit_timeout() - DNS still working
+   *   connect_error() - DNS done but no socket?
+   * transmit_ready() - scheduler shutdown or timeout, or signal_transmit_error()
+   * We'd need to dig into the scheduler to guess at the reason, as
+   * connection.c tells us nothing itself, but mostly its timouts.
+   * Initially, we'll simply ignore this and leave massive timeouts, but
+   * maybe that should change for error handling pruposes.  It appears that
+   * successful operations, including DNS resolution, do not use this.  */if (NULL == buf)
+  {
+    if (0 == ih->step)
+    {
+      LOG (GNUNET_ERROR_TYPE_WARNING,
+           "Timeout contacting SOCKS server, retrying indefinitely, but probably hopeless.\n");
+      register_sender (ih);
+    }
+    else
+    {
+      LOG (GNUNET_ERROR_TYPE_ERROR,
+           "Timeout during mid SOCKS handshake (step %u), probably not a SOCKS server.\n",
+           ih->step);
+      GNUNET_break (0);
+    }
+    return 0;
+  }
+
+  GNUNET_assert ((1024 >= size) && (size > 0));
+  GNUNET_assert ((SOCKS5_step_done > ih->step) && (ih->step >= 0));
+  unsigned char *b = ih->outstep[ih->step];
+  unsigned char *e = ih->outstep[ih->step + 1];
+  GNUNET_assert (e <= &ih->outbuf[1024]);
+  unsigned int l = e - b;
+  GNUNET_assert (size >= l);
+  GNUNET_memcpy (buf, b, l);
+  register_reciever (ih, register_reciever_wants (ih));
+  return l;
+}
+
+
+/**
+ * Register SOCKS5 handshake sender
+ *
+ * @param ih handshake
+ * @return non-NULL if the notify callback was queued,
+ *         NULL if we are already going to notify someone else (busy)
+ */
+struct GNUNET_CONNECTION_TransmitHandle *
+register_sender (struct GNUNET_SOCKS_Handshake *ih)
+{
+  struct GNUNET_TIME_Relative timeout = GNUNET_TIME_UNIT_MINUTES;
+
+  GNUNET_assert (SOCKS5_step_done > ih->step);
+  GNUNET_assert (ih->step >= 0);
+  if (0 == ih->step)
+    timeout = GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 3);
+  unsigned char *b = ih->outstep[ih->step];
+  unsigned char *e = ih->outstep[ih->step + 1];
+  GNUNET_assert (ih->outbuf <= b && b < e && e < &ih->outbuf[1024]);
+  ih->th = GNUNET_CONNECTION_notify_transmit_ready (ih->socks5_connection,
+                                                    e - b,
+                                                    timeout,
+                                                    &transmit_ready,
+                                                    ih);
+  return ih->th;
+}
+
+
+/**
+ * Initialize a SOCKS5 handshake for authentication via username and
+ * password.  Tor uses SOCKS username and password authentication to assign
+ * programs unique circuits.
+ *
+ * @param user username for the proxy
+ * @param pass password for the proxy
+ * @return Valid SOCKS5 hanbdshake handle
+ */
+struct GNUNET_SOCKS_Handshake *
+GNUNET_SOCKS_init_handshake (const char *user, const char *pass)
+{
+  struct GNUNET_SOCKS_Handshake *ih =
+    GNUNET_new (struct GNUNET_SOCKS_Handshake);
+  unsigned char *b = ih->outbuf;
+
+  ih->outstep[SOCKS5_step_greet] = b;
+  *(b++) = 5; /* SOCKS5 */
+  unsigned char *n = b++;
+  *n = 1; /* Number of authentication methods */
+  /* We support no authentication even when requesting authentication,
+   * but this appears harmless, given the way that Tor uses authentication.
+   * And some SOCKS5 servers might require this.  */
+  *(b++) = SOCKS5_AUTH_NOAUTH;
+  if (NULL != user)
+  {
+    *(b++) = SOCKS5_AUTH_USERPASS;
+    (*n)++;
+  }
+  /* There is no apperent reason to support authentication methods beyond
+   * username and password since afaik Tor does not support them. */
+
+  /* We authenticate with an empty username and password if the server demands
+   * them but we do not have any. */
+  if (user == NULL)
+    user = "";
+  if (pass == NULL)
+    pass = "";
+
+  ih->outstep[SOCKS5_step_auth] = b;
+  *(b++) = 1; /* subnegotiation ver.: 1 */
+  b = SOCK5_proto_string (b, user);
+  b = SOCK5_proto_string (b, pass);
+
+  ih->outstep[SOCKS5_step_cmd] = b;
+
+  ih->inend = ih->instart = ih->inbuf;
+
+  return ih;
+}
+
+
+/**
+ * Initialize a SOCKS5 handshake without authentication, thereby possibly
+ * sharing a Tor circuit with another process.
+ *
+ * @return Valid SOCKS5 hanbdshake handle
+ */
+struct GNUNET_SOCKS_Handshake *
+GNUNET_SOCKS_init_handshake_noauth ()
+{
+  return GNUNET_SOCKS_init_handshake (NULL, NULL);
+}
+
+
+/**
+ * Build request that the SOCKS5 proxy open a TCP/IP stream to the given host
+ * and port.
+ *
+ * @param ih SOCKS5 handshake
+ * @param hostname
+ * @param port
+ */
+void
+GNUNET_SOCKS_set_handshake_destination (struct GNUNET_SOCKS_Handshake *ih,
+                                        const char *host,
+                                        uint16_t port)
+{
+  union
+  {
+    struct in_addr in4;
+    struct in6_addr in6;
+  } ia;
+  unsigned char *b = ih->outstep[SOCKS5_step_cmd];
+
+  *(b++) = 5; /* SOCKS5 */
+  *(b++) = 1; /* Establish a TCP/IP stream */
+  *(b++) = 0; /* reserved */
+
+  /* Specify destination */
+  if (1 == inet_pton (AF_INET, host, &ia.in4))
+  {
+    *(b++) = 1;   /* IPv4 */
+    GNUNET_memcpy (b, &ia.in4, sizeof(struct in_addr));
+    b += sizeof(struct in_addr);   /* 4 */
+  }
+  else if (1 == inet_pton (AF_INET6, host, &ia.in6))
+  {
+    *(b++) = 4;   /* IPv6 */
+    GNUNET_memcpy (b, &ia.in6, sizeof(struct in6_addr));
+    b += sizeof(struct in6_addr);   /* 16 */
+  }
+  else
+  {
+    *(b++) = 3;   /* hostname */
+    b = SOCK5_proto_string (b, host);
+  }
+
+  /* Specify port */
+  *(uint16_t *) b = htons (port);
+  b += 2;
+
+  ih->outstep[SOCKS5_step_done] = b;
+}
+
+
+/**
+ * Run a SOCKS5 handshake on an open but unused TCP connection.
+ *
+ * @param ih SOCKS5 handshake, consumed here.
+ * @param c open unused connection, consumed here.
+ * @return Connection handle that becomes usable when the SOCKS5 handshake completes.
+ */
+struct GNUNET_CONNECTION_Handle *
+GNUNET_SOCKS_run_handshake (struct GNUNET_SOCKS_Handshake *ih,
+                            struct GNUNET_CONNECTION_Handle *c)
+{
+  ih->socks5_connection = c;
+  ih->target_connection = GNUNET_CONNECTION_create_proxied_from_handshake (c);
+  register_sender (ih);
+
+  return ih->target_connection;
+}
+
+
+/**
+ * Check if a SOCKS proxy is required by a service.  Do not use local service
+ * if a SOCKS proxy port is configured as this could deanonymize a user.
+ *
+ * @param service_name name of service to connect to
+ * @param cfg configuration to use
+ * @return GNUNET_YES if so, GNUNET_NO if not
+ */
+int
+GNUNET_SOCKS_check_service (const char *service_name,
+                            const struct GNUNET_CONFIGURATION_Handle *cfg)
+{
+  return GNUNET_CONFIGURATION_have_value (cfg, service_name, "SOCKSPORT") ||
+         GNUNET_CONFIGURATION_have_value (cfg, service_name, "SOCKSHOST");
+}
+
+
+/**
+ * Try to connect to a service configured to use a SOCKS5 proxy.
+ *
+ * @param service_name name of service to connect to
+ * @param cfg configuration to use
+ * @return Connection handle that becomes usable when the handshake completes.
+ *         NULL if SOCKS not configured or not configured properly
+ */
+struct GNUNET_CONNECTION_Handle *
+GNUNET_SOCKS_do_connect (const char *service_name,
+                         const struct GNUNET_CONFIGURATION_Handle *cfg)
+{
+  struct GNUNET_SOCKS_Handshake *ih;
+  struct GNUNET_CONNECTION_Handle *socks5; /* *proxied */
+  char *host0;
+  char *host1;
+  char *user;
+  char *pass;
+  unsigned long long port0;
+  unsigned long long port1;
+
+  if (GNUNET_YES != GNUNET_SOCKS_check_service (service_name, cfg))
+    return NULL;
+  if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_number (cfg,
+                                                          service_name,
+                                                          "SOCKSPORT",
+                                                          &port0))
+    port0 = 9050;
+  /* A typical Tor client should usually try port 9150 for the TBB too, but
+   * GNUnet can probably assume a system Tor installation. */
+  if ((port0 > 65535) || (port0 <= 0))
+  {
+    LOG (GNUNET_ERROR_TYPE_WARNING,
+         _ (
+           "Attempting to use invalid port %d as SOCKS proxy for service `%s'.\n"),
+         port0,
+         service_name);
+    return NULL;
+  }
+  if ((GNUNET_OK != GNUNET_CONFIGURATION_get_value_number (cfg,
+                                                           service_name,
+                                                           "PORT",
+                                                           &port1)) ||
+      (port1 > 65535) || (port1 <= 0) ||
+      (GNUNET_OK != GNUNET_CONFIGURATION_get_value_string (cfg,
+                                                           service_name,
+                                                           "HOSTNAME",
+                                                           &host1)))
+  {
+    LOG (GNUNET_ERROR_TYPE_WARNING,
+         _ (
+           "Attempting to proxy service `%s' to invalid port %d or hostname.\n"),
+         service_name,
+         port1);
+    return NULL;
+  }
+  /* Appeared to still work after host0 corrupted, so either test case is broken, or
+     this whole routine is not being called. */
+  if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_string (cfg,
+                                                          service_name,
+                                                          "SOCKSHOST",
+                                                          &host0))
+    host0 = NULL;
+  socks5 = GNUNET_CONNECTION_create_from_connect (cfg,
+                                                  (host0 != NULL) ? host0
+                                                  : "127.0.0.1",
+                                                  port0);
+  GNUNET_free (host0);
+
+  /* Sets to NULL if they do not exist */
+  (void) GNUNET_CONFIGURATION_get_value_string (cfg,
+                                                service_name,
+                                                "SOCKSUSER",
+                                                &user);
+  (void) GNUNET_CONFIGURATION_get_value_string (cfg,
+                                                service_name,
+                                                "SOCKSPASS",
+                                                &pass);
+  ih = GNUNET_SOCKS_init_handshake (user, pass);
+  GNUNET_free (user);
+  GNUNET_free (pass);
+
+  GNUNET_SOCKS_set_handshake_destination (ih, host1, port1);
+  GNUNET_free (host1);
+  return GNUNET_SOCKS_run_handshake (ih, socks5);
+}
+
+
+/* socks.c */
diff --git a/src/util/strings.c b/src/util/strings.c
index 5148d03686bc0f5abdd1910775baf9b7c32c8375..9d6f4039ebc35cdaa40c1290e755ae4c7b2223f2 100644
--- a/src/util/strings.c
+++ b/src/util/strings.c
@@ -29,6 +29,7 @@
 #include <iconv.h>
 #endif
 #include "gnunet_crypto_lib.h"
+#include "gnunet_buffer_lib.h"
 #include "gnunet_strings_lib.h"
 #include <unicase.h>
 #include <unistr.h>
@@ -1985,7 +1986,7 @@ GNUNET_STRINGS_base64_decode (const char *data, size_t len, void **out)
                 "ignoring CR/LF\n");                              \
     i++;                                                          \
     if (i >= len)                                                 \
-      goto END;                                                   \
+    goto END;                                                   \
   }
 
   GNUNET_assert (len / 3 < SIZE_MAX);
@@ -2088,4 +2089,161 @@ GNUNET_STRINGS_base64url_decode (const char *data, size_t len, void **out)
 }
 
 
+/**
+ * url/percent encode (RFC3986).
+ *
+ * @param data the data to encode
+ * @param len the length of the input
+ * @param output where to write the output (*output should be NULL,
+ *   is allocated)
+ * @return the size of the output
+ */
+size_t
+GNUNET_STRINGS_urldecode (const char *data, size_t len, char **out)
+{
+  const char *rpos = data;
+  *out = GNUNET_malloc (len + 1); /* output should always fit into input */
+  char *wpos = *out;
+  size_t resl = 0;
+
+  while ('\0' != *rpos)
+  {
+    unsigned int num;
+    switch (*rpos)
+    {
+    case '%':
+      if (1 != sscanf (rpos + 1, "%2x", &num))
+        break;
+      *wpos = (char) ((unsigned char) num);
+      wpos++;
+      resl++;
+      rpos += 3;
+      break;
+    /* TODO: add bad sequence handling */
+    /* intentional fall through! */
+    default:
+      *wpos = *rpos;
+      wpos++;
+      resl++;
+      rpos++;
+    }
+  }
+  *wpos = '\0'; /* add 0-terminator */
+  return resl;
+}
+
+
+/**
+ * url/percent encode (RFC3986).
+ *
+ * @param data the data to decode
+ * @param len the length of the input
+ * @param output where to write the output (*output should be NULL,
+ *   is allocated)
+ * @return the size of the output
+ */
+size_t
+GNUNET_STRINGS_urlencode (const char *data, size_t len, char **out)
+{
+  struct GNUNET_Buffer buf = { 0 };
+  const uint8_t *i8 = (uint8_t *) data;
+
+  while (0 != *i8)
+  {
+    if (0 == (0x80 & *i8))
+    {
+      /* traditional ASCII */
+      if (isalnum (*i8) || (*i8 == '-') || (*i8 == '_') || (*i8 == '.') ||
+          (*i8 == '~') )
+        GNUNET_buffer_write (&buf, (const char*) i8, 1);
+      else if (*i8 == ' ')
+        GNUNET_buffer_write (&buf, "+", 1);
+      else
+        GNUNET_buffer_write_fstr (&buf,
+                                  "%%%X%X",
+                                  *i8 >> 4,
+                                  *i8 & 15);
+      i8++;
+      continue;
+    }
+    if (0x80 + 0x40 == ((0x80 + 0x40 + 0x20) & *i8))
+    {
+      /* 2-byte value, percent-encode */
+      GNUNET_buffer_write_fstr (&buf,
+                                "%%%X%X",
+                                *i8 >> 4,
+                                *i8 & 15);
+      i8++;
+      GNUNET_buffer_write_fstr (&buf,
+                                "%%%X%X",
+                                *i8 >> 4,
+                                *i8 & 15);
+      i8++;
+      continue;
+    }
+    if (0x80 + 0x40 + 0x20 == ((0x80 + 0x40 + 0x20 + 0x10) & *i8))
+    {
+      /* 3-byte value, percent-encode */
+      for (unsigned int i = 0; i<3; i++)
+      {
+        GNUNET_buffer_write_fstr (&buf,
+                                  "%%%X%X",
+                                  *i8 >> 4,
+                                  *i8 & 15);
+        i8++;
+      }
+      continue;
+    }
+    if (0x80 + 0x40 + 0x20 + 0x10 == ((0x80 + 0x40 + 0x20 + 0x10 + 0x08) & *i8))
+    {
+      /* 4-byte value, percent-encode */
+      for (unsigned int i = 0; i<4; i++)
+      {
+        GNUNET_buffer_write_fstr (&buf,
+                                  "%%%X%X",
+                                  *i8 >> 4,
+                                  *i8 & 15);
+        i8++;
+      }
+      continue;
+    }
+    if (0x80 + 0x40 + 0x20 + 0x10 + 0x08 == ((0x80 + 0x40 + 0x20 + 0x10 + 0x08
+                                              + 0x04) & *i8))
+    {
+      /* 5-byte value, percent-encode (outside of UTF-8 modern standard, but so what) */
+      for (unsigned int i = 0; i<5; i++)
+      {
+        GNUNET_buffer_write_fstr (&buf,
+                                  "%%%X%X",
+                                  *i8 >> 4,
+                                  *i8 & 15);
+        i8++;
+      }
+      continue;
+    }
+    if (0x80 + 0x40 + 0x20 + 0x10 + 0x08 + 0x04 == ((0x80 + 0x40 + 0x20 + 0x10
+                                                     + 0x08 + 0x04 + 0x02)
+                                                    & *i8))
+    {
+      /* 6-byte value, percent-encode (outside of UTF-8 modern standard, but so what) */
+      for (unsigned int i = 0; i<6; i++)
+      {
+        GNUNET_buffer_write_fstr (&buf,
+                                  "%%%X%X",
+                                  *i8 >> 4,
+                                  *i8 & 15);
+        i8++;
+      }
+      continue;
+    }
+    /* really, really invalid UTF-8: fail */
+    GNUNET_break (0);
+    GNUNET_buffer_clear (&buf);
+    return 0;
+  }
+  *out = GNUNET_buffer_reap_str (&buf);
+  return strlen (*out);
+}
+
+
 /* end of strings.c */
diff --git a/src/util/test_bio.c b/src/util/test_bio.c
index 0c8453121434dfb1c4eeac4cb603d1f2b1cc327e..f180147192a90f142252c5394d0cd9ce96c4d53e 100644
--- a/src/util/test_bio.c
+++ b/src/util/test_bio.c
@@ -52,14 +52,14 @@ test_normal_rw (void)
     GNUNET_BIO_write_spec_string ("test-normal-rw-string", TESTSTRING),
     GNUNET_BIO_write_spec_meta_data ("test-normal-rw-metadata", mdW),
     GNUNET_BIO_write_spec_int64 ("test-normal-rw-int64", &wNum),
-    GNUNET_BIO_write_spec_end(),
+    GNUNET_BIO_write_spec_end (),
   };
 
   struct GNUNET_BIO_ReadSpec rs[] = {
     GNUNET_BIO_read_spec_string ("test-normal-rw-string", &rString, 200),
     GNUNET_BIO_read_spec_meta_data ("test-normal-rw-metadata", &mdR),
     GNUNET_BIO_read_spec_int64 ("test-normal-rw-int64", &rNum),
-    GNUNET_BIO_read_spec_end(),
+    GNUNET_BIO_read_spec_end (),
   };
 
   /* I/O on file */
@@ -73,12 +73,13 @@ test_normal_rw (void)
   GNUNET_assert (GNUNET_OK == GNUNET_BIO_read_spec_commit (rh, rs));
   GNUNET_assert (GNUNET_OK == GNUNET_BIO_read_close (rh, NULL));
   GNUNET_assert (0 == strcmp (TESTSTRING, rString));
-  GNUNET_assert (GNUNET_YES == GNUNET_CONTAINER_meta_data_test_equal (mdR, mdW));
+  GNUNET_assert (GNUNET_YES == GNUNET_CONTAINER_meta_data_test_equal (mdR,
+                                                                      mdW));
   GNUNET_assert (wNum == rNum);
 
   GNUNET_CONTAINER_meta_data_destroy (mdR);
   GNUNET_assert (GNUNET_OK == GNUNET_DISK_directory_remove (filename));
-  GNUNET_free(filename);
+  GNUNET_free (filename);
 
   /* I/O on buffer */
   wh = GNUNET_BIO_write_open_buffer ();
@@ -96,7 +97,8 @@ test_normal_rw (void)
   GNUNET_assert (GNUNET_OK == GNUNET_BIO_read_spec_commit (rh, rs));
   GNUNET_assert (GNUNET_OK == GNUNET_BIO_read_close (rh, NULL));
   GNUNET_assert (0 == strcmp (TESTSTRING, rString));
-  GNUNET_assert (GNUNET_YES == GNUNET_CONTAINER_meta_data_test_equal (mdR, mdW));
+  GNUNET_assert (GNUNET_YES == GNUNET_CONTAINER_meta_data_test_equal (mdR,
+                                                                      mdW));
   GNUNET_assert (wNum == rNum);
 
   GNUNET_free (buffer);
@@ -314,7 +316,7 @@ test_fullfile_rw (void)
                                  200),
     GNUNET_BIO_read_spec_meta_data ("test-fullfile-rw-metadata",
                                     &mdR),
-    GNUNET_BIO_read_spec_end(),
+    GNUNET_BIO_read_spec_end (),
   };
 
   wh = GNUNET_BIO_write_open_file ("/dev/full");
diff --git a/src/util/test_common_logging_runtime_loglevels.c b/src/util/test_common_logging_runtime_loglevels.c
index e6d83d52c2eb21e5f5dd4ecb4ccb45545314b77a..79cf9d53a9f1c4f05255bd4673ffbbb1fb25b29f 100644
--- a/src/util/test_common_logging_runtime_loglevels.c
+++ b/src/util/test_common_logging_runtime_loglevels.c
@@ -207,7 +207,7 @@ read_output_line (int phase_from1, int phase_to1, int phase_from2,
  */
 #define LOG_MAX_LINE_LENGTH (17)
 
-#define LOG_BUFFER_SIZE LOG_MAX_NUM_LINES * LOG_MAX_LINE_LENGTH
+#define LOG_BUFFER_SIZE LOG_MAX_NUM_LINES *LOG_MAX_LINE_LENGTH
 
 static char buf[LOG_BUFFER_SIZE];
 
@@ -347,8 +347,7 @@ runone ()
 {
   const struct GNUNET_DISK_FileHandle *stdout_read_handle;
 
-  pipe_stdout = GNUNET_DISK_pipe (GNUNET_YES, GNUNET_YES, GNUNET_NO,
-                                  GNUNET_YES);
+  pipe_stdout = GNUNET_DISK_pipe (GNUNET_DISK_PF_BLOCKING_RW);
 
   if (pipe_stdout == NULL)
   {
@@ -403,7 +402,7 @@ runone ()
     break;
   }
 
-  proc = GNUNET_OS_start_process (GNUNET_NO, GNUNET_OS_INHERIT_STD_OUT_AND_ERR,
+  proc = GNUNET_OS_start_process (GNUNET_OS_INHERIT_STD_OUT_AND_ERR,
                                   NULL, pipe_stdout, NULL,
                                   "./test_common_logging_dummy",
                                   "test_common_logging_dummy", NULL);
diff --git a/src/util/test_container_multihashmap.c b/src/util/test_container_multihashmap.c
index bd9e7af31a9e1303ce322879cd4cb6d7bf9786d4..f46b9f56ed9b2f7af51adf3c45494fc6b87fb6b5 100644
--- a/src/util/test_container_multihashmap.c
+++ b/src/util/test_container_multihashmap.c
@@ -31,7 +31,7 @@
                   if (m != NULL) GNUNET_CONTAINER_multihashmap_destroy (m); \
                   if (NULL != \
                       iter) \
-                    GNUNET_CONTAINER_multihashmap_iterator_destroy (iter); \
+                  GNUNET_CONTAINER_multihashmap_iterator_destroy (iter); \
                   return 1; }
 #define CHECK(c) { if (! (c)) ABORT (); }
 
diff --git a/src/util/test_container_multipeermap.c b/src/util/test_container_multipeermap.c
index 9aeead56cb7f2f459234d8626ad8d0e37b7df815..cb6fc30d25de0696c32f4098bed5d7602553f20a 100644
--- a/src/util/test_container_multipeermap.c
+++ b/src/util/test_container_multipeermap.c
@@ -31,7 +31,7 @@
                   if (NULL != m) GNUNET_CONTAINER_multipeermap_destroy (m); \
                   if (NULL != \
                       iter) \
-                    GNUNET_CONTAINER_multipeermap_iterator_destroy (iter); \
+                  GNUNET_CONTAINER_multipeermap_iterator_destroy (iter); \
                   return 1; }
 #define CHECK(c) { if (! (c)) ABORT (); }
 
diff --git a/src/util/test_os_start_process.c b/src/util/test_os_start_process.c
index 2bdca5c9d8f18eb00497c33ee503a0dc429426dd..ff5021d034709af3ec43eef1301f578964f898f6 100644
--- a/src/util/test_os_start_process.c
+++ b/src/util/test_os_start_process.c
@@ -124,11 +124,8 @@ run_task (void *cls)
 
   GNUNET_asprintf (&fn, "cat");
 
-  hello_pipe_stdin = GNUNET_DISK_pipe (GNUNET_YES, GNUNET_YES, GNUNET_YES,
-                                       GNUNET_NO);
-  hello_pipe_stdout = GNUNET_DISK_pipe (GNUNET_YES, GNUNET_YES, GNUNET_NO,
-                                        GNUNET_YES);
-
+  hello_pipe_stdin = GNUNET_DISK_pipe (GNUNET_DISK_PF_BLOCKING_RW);
+  hello_pipe_stdout = GNUNET_DISK_pipe (GNUNET_DISK_PF_BLOCKING_RW);
   if ((hello_pipe_stdout == NULL) || (hello_pipe_stdin == NULL))
   {
     GNUNET_break (0);
@@ -138,7 +135,7 @@ run_task (void *cls)
   }
 
   proc =
-    GNUNET_OS_start_process (GNUNET_NO, GNUNET_OS_INHERIT_STD_ERR,
+    GNUNET_OS_start_process (GNUNET_OS_INHERIT_STD_ERR,
                              hello_pipe_stdin, hello_pipe_stdout, NULL,
                              fn,
                              "test_gnunet_echo_hello", "-", NULL);
@@ -202,17 +199,16 @@ check_kill ()
 {
   char *fn;
 
-  hello_pipe_stdin = GNUNET_DISK_pipe (GNUNET_YES, GNUNET_YES, GNUNET_YES,
-                                       GNUNET_NO);
-  hello_pipe_stdout = GNUNET_DISK_pipe (GNUNET_YES, GNUNET_YES, GNUNET_NO,
-                                        GNUNET_YES);
+  hello_pipe_stdin = GNUNET_DISK_pipe (GNUNET_DISK_PF_BLOCKING_RW);
+  hello_pipe_stdout = GNUNET_DISK_pipe (GNUNET_DISK_PF_BLOCKING_RW);
   if ((hello_pipe_stdout == NULL) || (hello_pipe_stdin == NULL))
   {
     return 1;
   }
   fn = GNUNET_OS_get_libexec_binary_path ("gnunet-service-resolver");
   proc =
-    GNUNET_OS_start_process (GNUNET_YES, GNUNET_OS_INHERIT_STD_ERR,
+    GNUNET_OS_start_process (GNUNET_OS_INHERIT_STD_ERR
+                             | GNUNET_OS_USE_PIPE_CONTROL,
                              hello_pipe_stdin,
                              hello_pipe_stdout,
                              NULL,
@@ -246,17 +242,16 @@ check_instant_kill ()
 {
   char *fn;
 
-  hello_pipe_stdin = GNUNET_DISK_pipe (GNUNET_YES, GNUNET_YES, GNUNET_YES,
-                                       GNUNET_NO);
-  hello_pipe_stdout = GNUNET_DISK_pipe (GNUNET_YES, GNUNET_YES, GNUNET_NO,
-                                        GNUNET_YES);
+  hello_pipe_stdin = GNUNET_DISK_pipe (GNUNET_DISK_PF_BLOCKING_RW);
+  hello_pipe_stdout = GNUNET_DISK_pipe (GNUNET_DISK_PF_BLOCKING_RW);
   if ((hello_pipe_stdout == NULL) || (hello_pipe_stdin == NULL))
   {
     return 1;
   }
   fn = GNUNET_OS_get_libexec_binary_path ("gnunet-service-resolver");
   proc =
-    GNUNET_OS_start_process (GNUNET_YES, GNUNET_OS_INHERIT_STD_ERR,
+    GNUNET_OS_start_process (GNUNET_OS_INHERIT_STD_ERR
+                             | GNUNET_OS_USE_PIPE_CONTROL,
                              hello_pipe_stdin, hello_pipe_stdout, NULL,
                              fn,
                              "gnunet-service-resolver", "-", NULL);
diff --git a/src/util/test_peer.c b/src/util/test_peer.c
index 320746c76cb258bb5ee9184d91c0748614ae2075..bb0bc48dc54c75b1dacd2acf839b45cc8a2b53d5 100644
--- a/src/util/test_peer.c
+++ b/src/util/test_peer.c
@@ -106,8 +106,7 @@ check ()
    * is expected to be set to zero
    */GNUNET_log_skip (1, GNUNET_YES);
   GNUNET_PEER_resolve (0, &res);
-  GNUNET_assert (0 ==
-                 GNUNET_is_zero (&res));
+  GNUNET_assert (GNUNET_YES == GNUNET_is_zero (&res));
 
   /* Removing peer entries 1 and 3 from table using the list decrement function */
   /* If count = 0, nothing should be done whatsoever */
diff --git a/src/util/test_resolver_api.c b/src/util/test_resolver_api.c
index 05716741e6906911b8bb09ee326dcdc0cb682b01..eefb208907c832745bb43fe6ff25339672ed7c42 100644
--- a/src/util/test_resolver_api.c
+++ b/src/util/test_resolver_api.c
@@ -348,8 +348,8 @@ main (int argc, char *argv[])
                     "WARNING",
                     NULL);
   fn = GNUNET_OS_get_libexec_binary_path ("gnunet-service-resolver");
-  proc = GNUNET_OS_start_process (GNUNET_YES,
-                                  GNUNET_OS_INHERIT_STD_OUT_AND_ERR,
+  proc = GNUNET_OS_start_process (GNUNET_OS_INHERIT_STD_OUT_AND_ERR
+                                  | GNUNET_OS_USE_PIPE_CONTROL,
                                   NULL, NULL, NULL,
                                   fn,
                                   "gnunet-service-resolver",
diff --git a/src/util/test_scheduler.c b/src/util/test_scheduler.c
index 471ca64e5face158e3d59ac708bdc4dc8cc89f51..0e2e7f76021c5dc849fe148123cf222136854338 100644
--- a/src/util/test_scheduler.c
+++ b/src/util/test_scheduler.c
@@ -133,7 +133,7 @@ task4 (void *cls)
 
   GNUNET_assert (4 == *ok);
   (*ok) = 6;
-  p = GNUNET_DISK_pipe (GNUNET_NO, GNUNET_NO, GNUNET_NO, GNUNET_NO);
+  p = GNUNET_DISK_pipe (GNUNET_DISK_PF_NONE);
   GNUNET_assert (NULL != p);
   fds[0] = GNUNET_DISK_pipe_handle (p, GNUNET_DISK_PIPE_END_READ);
   fds[1] = GNUNET_DISK_pipe_handle (p, GNUNET_DISK_PIPE_END_WRITE);
diff --git a/src/util/test_socks.c b/src/util/test_socks.c
new file mode 100644
index 0000000000000000000000000000000000000000..c5a703db43e5a325e87cbc99afa07767cf25ba31
--- /dev/null
+++ b/src/util/test_socks.c
@@ -0,0 +1,257 @@
+/*
+     This file is part of GNUnet.
+     Copyright (C) 2015, 2016 GNUnet e.V.
+
+     GNUnet is free software: you can redistribute it and/or modify it
+     under the terms of the GNU Affero General Public License as published
+     by the Free Software Foundation, either version 3 of the License,
+     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
+     Affero General Public License for more details.
+
+     You should have received a copy of the GNU Affero General Public License
+     along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+     SPDX-License-Identifier: AGPL3.0-or-later
+ */
+/**
+ * @file util/test_socks.c
+ * @brief tests for socks.c
+ */
+#include "platform.h"
+#include "gnunet_util_lib.h"
+
+
+#define PORT 35124
+
+#define MYNAME "test_sockst"
+
+static struct GNUNET_MQ_Handle *mq;
+
+static struct GNUNET_SERVER_Handle *server;
+
+static struct GNUNET_CONFIGURATION_Handle *cfg;
+
+#define MY_TYPE 130
+
+struct CopyContext
+{
+  struct GNUNET_SERVER_Client *client;
+  struct GNUNET_MessageHeader *cpy;
+};
+
+static size_t
+copy_msg (void *cls, size_t size, void *buf)
+{
+  struct CopyContext *ctx = cls;
+  struct GNUNET_MessageHeader *cpy = ctx->cpy;
+
+  GNUNET_assert (sizeof(struct GNUNET_MessageHeader) == ntohs (cpy->size));
+  GNUNET_assert (size >= ntohs (cpy->size));
+  GNUNET_memcpy (buf, cpy, ntohs (cpy->size));
+  GNUNET_SERVER_receive_done (ctx->client, GNUNET_OK);
+  GNUNET_free (cpy);
+  GNUNET_free (ctx);
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Message bounced back to client\n");
+  return sizeof(struct GNUNET_MessageHeader);
+}
+
+
+/**
+ * Callback that just bounces the message back to the sender.
+ */
+static void
+echo_cb (void *cls, struct GNUNET_SERVER_Client *client,
+         const struct GNUNET_MessageHeader *message)
+{
+  struct CopyContext *cc;
+  struct GNUNET_MessageHeader *cpy;
+
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "Receiving message from client, bouncing back\n");
+  GNUNET_assert (sizeof(struct GNUNET_MessageHeader) == ntohs (message->size));
+  cc = GNUNET_new (struct CopyContext);
+  cc->client = client;
+  cpy = GNUNET_malloc (ntohs (message->size));
+  GNUNET_memcpy (cpy, message, ntohs (message->size));
+  cc->cpy = cpy;
+  GNUNET_assert (NULL !=
+                 GNUNET_SERVER_notify_transmit_ready (client,
+                                                      ntohs (message->size),
+                                                      GNUNET_TIME_UNIT_SECONDS,
+                                                      &copy_msg, cc));
+}
+
+
+static struct GNUNET_SERVER_MessageHandler handlers[] = {
+  { &echo_cb, NULL, MY_TYPE, sizeof(struct GNUNET_MessageHeader) },
+  { NULL, NULL, 0, 0 }
+};
+
+
+static void
+handle_bounce (void *cls,
+               const struct GNUNET_MessageHeader *got)
+{
+  int *ok = cls;
+
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "Receiving bounce, checking content\n");
+  GNUNET_assert (NULL != got);
+  GNUNET_MQ_destroy (mq);
+  mq = NULL;
+  GNUNET_SERVER_destroy (server);
+  server = NULL;
+  *ok = 0;
+}
+
+
+/**
+ * Generic error handler, called with the appropriate error code and
+ * the same closure specified at the creation of the message queue.
+ * Not every message queue implementation supports an error handler.
+ *
+ * @param cls closure with the `struct GNUNET_STATISTICS_Handle *`
+ * @param error error code
+ */
+static void
+mq_error_handler (void *cls,
+                  enum GNUNET_MQ_Error error)
+{
+  GNUNET_assert (0);  /* should never happen */
+}
+
+
+static void
+task (void *cls)
+{
+  struct sockaddr_in sa;
+  struct sockaddr *sap[2];
+  socklen_t slens[2];
+  struct GNUNET_MQ_Envelope *env;
+  struct GNUNET_MessageHeader *msg;
+  struct GNUNET_MQ_MessageHandler chandlers[] = {
+    GNUNET_MQ_hd_fixed_size (bounce,
+                             MY_TYPE,
+                             struct GNUNET_MessageHeader,
+                             cls),
+    GNUNET_MQ_handler_end ()
+  };
+
+  /* test IPC between client and server */
+  sap[0] = (struct sockaddr *) &sa;
+  slens[0] = sizeof(sa);
+  sap[1] = NULL;
+  slens[1] = 0;
+  memset (&sa, 0, sizeof(sa));
+#if HAVE_SOCKADDR_IN_SIN_LEN
+  sa.sin_len = sizeof(sa);
+#endif
+  sa.sin_family = AF_INET;
+  sa.sin_port = htons (PORT);
+  server =
+    GNUNET_SERVER_create (NULL, NULL, sap, slens,
+                          GNUNET_TIME_relative_multiply
+                            (GNUNET_TIME_UNIT_MILLISECONDS, 10000), GNUNET_NO);
+  GNUNET_assert (server != NULL);
+  handlers[0].callback_cls = cls;
+  handlers[1].callback_cls = cls;
+  GNUNET_SERVER_add_handlers (server, handlers);
+  mq = GNUNET_CLIENT_connect (cfg,
+                              MYNAME,
+                              chandlers,
+                              &mq_error_handler,
+                              NULL);
+  GNUNET_assert (NULL != mq);
+  env = GNUNET_MQ_msg (msg,
+                       MY_TYPE);
+  GNUNET_MQ_send (mq,
+                  env);
+}
+
+
+int
+main (int argc, char *argv[])
+{
+  int ok;
+  int status;
+  const char *socksport = "1081";
+
+  GNUNET_log_setup ("test_client",
+                    "WARNING",
+                    NULL);
+
+  pid_t pid = fork ();
+  GNUNET_assert (pid >= 0);
+  if (pid == 0)
+  {
+    execlp ("ssh",
+            "ssh", "-D", socksport,
+            "-o", "BatchMode yes",
+            "-o", "UserKnownHostsFile /tmp/gnunet_test_socks_ssh_garbage",
+            "-o", "StrictHostKeyChecking no",
+            "127.0.0.1", "-N", (char *) NULL);
+    perror (
+      "execlp (\"ssh\",\"ssh\",...,\"-D\",\"1081\",\"127.0.0.1\",\"-N\") ");
+    printf (""
+            "Please ensure you have ssh installed and have sshd installed and running :\n"
+            "\tsudo apt-get install openssh-client openssh-server\n"
+            "If you run Tor as a network proxy then Tor might prevent ssh from connecting\n"
+            "to localhost.  Please either run  make check  from an unproxied user, or else\n"
+            "add these lines to the beginning of your ~/.ssh/config file :"
+            "\tHost 127.0.0.1 localhost\n"
+            "\t  CheckHostIP no\n"
+            "\t  Protocol 2\n"
+            "\t  ProxyCommand nc 127.0.0.1 22\n");
+    kill (getppid (), SIGALRM);
+    return 1;
+  }
+  if (0 != sleep (1))
+  {
+    /* sleep interrupted, likely SIGALRM, failure to
+       launch child, terminate */
+    printf (""
+            "Please ensure you have ssh installed and have sshd installed and running :\n"
+            "\tsudo apt-get install openssh-client openssh-server\n"
+            "If you run Tor as a network proxy then Tor might prevent ssh from connecting\n"
+            "to localhost.  Please either run  make check  from an unproxied user, or else\n"
+            "add these lines to the beginning of your ~/.ssh/config file :"
+            "\tHost 127.0.0.1 localhost\n"
+            "\t  CheckHostIP no\n"
+            "\t  Protocol 2\n"
+            "\t  ProxyCommand nc 127.0.0.1 22\n");
+    return 77;
+  }
+  /* check if child exec()ed but died */
+  if (0 != waitpid (pid, &status, WNOHANG))
+  {
+    printf (""
+            "If you run Tor as a network proxy then Tor might prevent ssh from connecting\n"
+            "to localhost.  Please either run  make check  from an unproxied user, or else\n"
+            "add these lines to the beginning of your ~/.ssh/config file :"
+            "\tHost 127.0.0.1 localhost\n"
+            "\t  CheckHostIP no\n"
+            "\t  Protocol 2\n"
+            "\t  ProxyCommand nc 127.0.0.1 22\n");
+    return 77;
+  }
+
+  cfg = GNUNET_CONFIGURATION_create ();
+  GNUNET_CONFIGURATION_set_value_string (cfg, MYNAME, "SOCKSHOST", "127.0.0.1");
+  GNUNET_CONFIGURATION_set_value_string (cfg, MYNAME, "SOCKSPORT", socksport);
+  GNUNET_CONFIGURATION_set_value_number (cfg, MYNAME, "PORT", PORT);
+  GNUNET_CONFIGURATION_set_value_string (cfg, MYNAME, "HOSTNAME", "127.0.0.1");
+  ok = 1;
+  GNUNET_SCHEDULER_run (&task, &ok);
+  GNUNET_CONFIGURATION_destroy (cfg);
+
+  GNUNET_break (0 == kill (pid, SIGTERM));
+  GNUNET_break (pid == waitpid (pid, &status, 0));
+  return ok;
+}
+
+
+/* end of test_socks.c */
diff --git a/src/util/test_strings.c b/src/util/test_strings.c
index 90d06a4739560cc195fabf2ddd4e69ad0adb3876..753ec69080204970c4c1b7bad85fd70775c18ddf 100644
--- a/src/util/test_strings.c
+++ b/src/util/test_strings.c
@@ -39,6 +39,10 @@
 #define WANTB(a, b, l) if (0 != memcmp (a, b, l)) { GNUNET_break (0); return 1; \
 } else { }
 
+#define URLENCODE_TEST_VECTOR_PLAIN "Asbjlaw=ljsdlasjd?人aslkdsa"
+
+#define URLENCODE_TEST_VECTOR_ENCODED "Asbjlaw\%3Dljsdlasjd\%3F\%E4\%BA\%BAaslkdsa"
+
 int
 main (int argc, char *argv[])
 {
@@ -137,6 +141,16 @@ main (int argc, char *argv[])
                  GNUNET_STRINGS_fancy_time_to_relative ("15 m", &rtx));
   GNUNET_assert (rt.rel_value_us == rtx.rel_value_us);
 
+  GNUNET_assert (0 != GNUNET_STRINGS_urlencode (URLENCODE_TEST_VECTOR_PLAIN,
+                                                strlen (URLENCODE_TEST_VECTOR_PLAIN),
+                                                &b));
+  WANT (URLENCODE_TEST_VECTOR_ENCODED, b);
+  GNUNET_free (b);
+  GNUNET_assert (0 != GNUNET_STRINGS_urldecode (URLENCODE_TEST_VECTOR_ENCODED,
+                                                strlen (URLENCODE_TEST_VECTOR_ENCODED),
+                                                &b));
+  WANT (URLENCODE_TEST_VECTOR_PLAIN, b);
+  GNUNET_free (b);
   return 0;
 }
 
diff --git a/src/util/test_uri.c b/src/util/test_uri.c
new file mode 100644
index 0000000000000000000000000000000000000000..7c81566486334ebb2288fdbe0c44644bd8d9ee10
--- /dev/null
+++ b/src/util/test_uri.c
@@ -0,0 +1,837 @@
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include "gnunet_uri_lib.h"
+
+#define KNRM  "\x1B[0m"
+#define KBLU  "\x1B[34m"
+#define KGRN  "\x1B[32m"
+#define KERR  "\x1B[5;31;50m"
+
+/* macro to print out the header for a new group of tests */
+#define mu_group(name) printf ("%s • %s%s\n", KBLU, name, KNRM)
+
+/* macro for asserting a statement */
+#define mu_assert(message, test) do { \
+    if (!(test)) { \
+      printf ("\t%s× %s%s\n", KERR, message, KNRM); \
+      return message; \
+    } \
+    printf ("\t%s• %s%s\n", KGRN, message, KNRM); \
+  } while (0)
+
+/* macro for asserting a statement without printing it unless it is a failure */
+#define mu_silent_assert(message, test) do { \
+    if (!(test)) { \
+      printf ("\t\t%s× %s%s\n", KERR, message, KNRM); \
+      return message; \
+    } \
+  } while (0)
+
+/* run a test function and return result */
+#define mu_run_test(test) do { \
+    char *message = test (); tests_run++; \
+    if (message) { return message; } \
+  } while (0)
+
+
+int tests_run;
+
+static int
+strcmp_wrap (const char *str,
+             const char *str2)
+{
+  if (NULL == str && NULL == str2) {
+    return 0;
+  }
+  if (NULL == str) {
+    return 1;
+  }
+  if (NULL == str2) {
+    return -1;
+  }
+
+  return strcmp (str, str2);
+}
+
+#define assert_struct(as_url, \
+                      as_scheme, \
+                      as_user, \
+                      as_pass, \
+                      as_host, \
+                      as_port, \
+                      as_path, \
+                      as_query, \
+                      as_fragment) \
+  mu_silent_assert ("should set the scheme attribute correctly", \
+                    0 == strcmp_wrap (as_url.scheme, as_scheme)); \
+  mu_silent_assert ("should set the username attribute correctly", \
+                    0 == strcmp_wrap (as_url.username, as_user)); \
+  mu_silent_assert ("should set the password attribute correctly", \
+                    0 == strcmp_wrap (as_url.password, as_pass)); \
+  mu_silent_assert ("should set the host attribute correctly", \
+                    0 == strcmp_wrap (as_url.host, as_host)); \
+  mu_silent_assert ("should set the port attribute correctly", \
+                    as_port == as_url.port); \
+  mu_silent_assert ("should set the path attribute correctly", \
+                    0 == strcmp_wrap (as_url.path, as_path)); \
+  mu_silent_assert ("should set the query attribute correctly", \
+                    0 == strcmp_wrap (as_url.query, as_query)); \
+  mu_silent_assert ("should set the fragment attribute correctly", \
+                    0 == strcmp_wrap (as_url.fragment, as_fragment));
+
+static char *
+test_parse_http_url_ok (void)
+{
+  int rc;
+  struct GNUNET_Uri url;
+  char *url_string;
+
+  /* Minimal URL */
+  url_string = strdup ("http://example.com");
+  rc = GNUNET_uri_parse (&url,
+                         url_string);
+  mu_assert ("minimal HTTP URL", -1 != rc);
+  assert_struct (url,
+                 "http",
+                 NULL,
+                 NULL,
+                 "example.com",
+                 0,
+                 NULL,
+                 NULL,
+                 NULL);
+  free (url_string);
+
+  /* With path (/) */
+  url_string = strdup ("http://example.com/");
+  rc = GNUNET_uri_parse (&url,
+                         url_string);
+  mu_assert ("with path ('/')", -1 != rc);
+  assert_struct (url,
+                 "http",
+                 NULL,
+                 NULL,
+                 "example.com",
+                 0,
+                 "",
+                 NULL,
+                 NULL);
+  free (url_string);
+
+  /* With path */
+  url_string = strdup ("http://example.com/path");
+  rc = GNUNET_uri_parse (&url,
+                         url_string);
+  mu_assert ("with path ('/path')", -1 != rc);
+  assert_struct (url,
+                 "http",
+                 NULL,
+                 NULL,
+                 "example.com",
+                 0,
+                 "path",
+                 NULL,
+                 NULL);
+  free (url_string);
+
+  /* With port */
+  url_string = strdup ("http://example.com:80");
+  rc = GNUNET_uri_parse (&url,
+                         url_string);
+  mu_assert ("with port only",
+             -1 != rc);
+  assert_struct (url,
+                 "http",
+                 NULL,
+                 NULL,
+                 "example.com",
+                 80,
+                 NULL,
+                 NULL,
+                 NULL);
+  free (url_string);
+
+  /* With query */
+  url_string = strdup ("http://example.com?query=only");
+  rc = GNUNET_uri_parse (&url,
+                         url_string);
+  mu_assert ("with query only",
+             -1 != rc);
+  assert_struct (url,
+                 "http",
+                 NULL,
+                 NULL,
+                 "example.com",
+                 0,
+                 NULL,
+                 "query=only",
+                 NULL);
+  free (url_string);
+
+  /* With fragment */
+  url_string = strdup ("http://example.com#frag=f1");
+  rc = GNUNET_uri_parse (&url,
+                         url_string);
+  mu_assert ("with fragment only",
+             -1 != rc);
+  assert_struct (url,
+                 "http",
+                 NULL,
+                 NULL,
+                 "example.com",
+                 0,
+                 NULL,
+                 NULL,
+                 "frag=f1");
+  free (url_string);
+
+  /* With credentials */
+  url_string = strdup ("http://u:p@example.com");
+  rc = GNUNET_uri_parse (&url,
+                         url_string);
+  mu_assert ("with credentials only",
+             -1 != rc);
+  assert_struct (url,
+                 "http",
+                 "u",
+                 "p",
+                 "example.com",
+                 0,
+                 NULL,
+                 NULL,
+                 NULL);
+  free (url_string);
+
+  /* With port and path */
+  url_string = strdup ("http://example.com:8080/port/and/path");
+  rc = GNUNET_uri_parse (&url,
+                         url_string);
+  mu_assert ("with port and path",
+             -1 != rc);
+  assert_struct (url,
+                 "http",
+                 NULL,
+                 NULL,
+                 "example.com",
+                 8080,
+                 "port/and/path",
+                 NULL,
+                 NULL);
+  free (url_string);
+
+  /* With port and query */
+  url_string = strdup ("http://example.com:8080?query=portANDquery");
+  rc = GNUNET_uri_parse (&url,
+                         url_string);
+  mu_assert ("with port and query",
+             -1 != rc);
+  assert_struct (url,
+                 "http",
+                 NULL,
+                 NULL,
+                 "example.com",
+                 8080,
+                 NULL,
+                 "query=portANDquery",
+                 NULL);
+  free (url_string);
+
+  /* With port and fragment */
+  url_string = strdup ("http://example.com:8080#f1");
+  rc = GNUNET_uri_parse (&url,
+                         url_string);
+  mu_assert ("with port and fragment",
+             -1 != rc);
+  assert_struct (url,
+                 "http",
+                 NULL,
+                 NULL,
+                 "example.com",
+                 8080,
+                 NULL,
+                 NULL,
+                 "f1");
+  free (url_string);
+
+  /* With port and credentials */
+  url_string = strdup ("http://u:p@example.com:8080");
+  rc = GNUNET_uri_parse (&url,
+                         url_string);
+  mu_assert ("with port and credentials",
+             -1 != rc);
+  assert_struct (url,
+                 "http",
+                 "u",
+                 "p",
+                 "example.com",
+                 8080,
+                 NULL,
+                 NULL,
+                 NULL);
+  free (url_string);
+
+  /* With path and query */
+  url_string = strdup ("http://example.com/path/and/query?q=yes");
+  rc = GNUNET_uri_parse (&url,
+                         url_string);
+  mu_assert ("with path and query",
+             -1 != rc);
+  assert_struct (url,
+                 "http",
+                 NULL,
+                 NULL,
+                 "example.com",
+                 0,
+                 "path/and/query",
+                 "q=yes",
+                 NULL);
+  free (url_string);
+
+  /* With path and fragment */
+  url_string = strdup ("http://example.com/path/and#fragment");
+  rc = GNUNET_uri_parse (&url,
+                         url_string);
+  mu_assert ("with path and fragment",
+             -1 != rc);
+  assert_struct (url,
+                 "http",
+                 NULL,
+                 NULL,
+                 "example.com",
+                 0,
+                 "path/and",
+                 NULL,
+                 "fragment");
+  free (url_string);
+
+  /* With query and fragment */
+  url_string = strdup ("http://example.com?q=yes#f1");
+  rc = GNUNET_uri_parse (&url,
+                         url_string);
+  mu_assert ("with query and fragment",
+             -1 != rc);
+  assert_struct (url,
+                 "http",
+                 NULL,
+                 NULL,
+                 "example.com",
+                 0,
+                 NULL,
+                 "q=yes",
+                 "f1");
+  free (url_string);
+
+  /* With query and credentials */
+  url_string = strdup ("http://u:p@example.com?q=yes");
+  rc = GNUNET_uri_parse (&url,
+                         url_string);
+  mu_assert ("with query and credentials",
+             -1 != rc);
+  assert_struct (url,
+                 "http",
+                 "u",
+                 "p",
+                 "example.com",
+                 0,
+                 NULL,
+                 "q=yes",
+                 NULL);
+  free (url_string);
+
+  /* With empty credentials */
+  url_string = strdup ("http://:@example.com");
+  rc = GNUNET_uri_parse (&url,
+                         url_string);
+  mu_assert ("with empty credentials",
+             -1 != rc);
+  assert_struct (url,
+                 "http",
+                 "",
+                 "",
+                 "example.com",
+                 0,
+                 NULL,
+                 NULL,
+                 NULL);
+  free (url_string);
+
+  /* With empty credentials and port */
+  url_string = strdup ("http://:@example.com:89");
+  rc = GNUNET_uri_parse (&url,
+                         url_string);
+  mu_assert ("with empty credentials and port",
+             -1 != rc);
+  assert_struct (url,
+                 "http",
+                 "",
+                 "",
+                 "example.com",
+                 89,
+                 NULL,
+                 NULL,
+                 NULL);
+  free (url_string);
+
+  /* Full URL */
+  url_string = strdup ("https://jack:password@localhost:8989/path/to/test?query=yes&q=jack#fragment1");
+  rc = GNUNET_uri_parse (&url,
+                         url_string);
+  mu_assert ("with port, path and query",
+             -1 != rc);
+  assert_struct (url,
+                 "https",
+                 "jack",
+                 "password",
+                 "localhost",
+                 8989,
+                 "path/to/test",
+                 "query=yes&q=jack",
+                 "fragment1");
+  free (url_string);
+
+  return NULL;
+}
+
+static char *
+test_parse_http_rel_url_ok (void)
+{
+  int rc;
+  struct GNUNET_Uri url;
+  char *url_string;
+
+  /* Minimal relative URL */
+  url_string = strdup ("/");
+  rc = GNUNET_uri_parse (&url,
+                         url_string);
+  mu_assert ("minimal relative URL",
+             -1 != rc);
+  assert_struct (url,
+                 NULL,
+                 NULL,
+                 NULL,
+                 NULL,
+                 0,
+                 "",
+                 NULL,
+                 NULL);
+  free (url_string);
+
+  /* Path only */
+  url_string = strdup ("/hejsan");
+  rc = GNUNET_uri_parse (&url,
+                         url_string);
+  mu_assert ("path only",
+             -1 != rc);
+  assert_struct (url,
+                 NULL,
+                 NULL,
+                 NULL,
+                 NULL,
+                 0,
+                 "hejsan",
+                 NULL,
+                 NULL);
+  free (url_string);
+
+  /* Path and query */
+  url_string = strdup ("/hejsan?q=yes");
+  rc = GNUNET_uri_parse (&url,
+                         url_string);
+  mu_assert ("path only",
+             -1 != rc);
+  assert_struct (url,
+                 NULL,
+                 NULL,
+                 NULL,
+                 NULL,
+                 0,
+                 "hejsan",
+                 "q=yes",
+                 NULL);
+  free (url_string);
+
+  /* Path and fragment */
+  url_string = strdup ("/hejsan#fragment");
+  rc = GNUNET_uri_parse (&url,
+                         url_string);
+  mu_assert ("path and fragment",
+             -1 != rc);
+  assert_struct (url,
+                 NULL,
+                 NULL,
+                 NULL,
+                 NULL,
+                 0,
+                 "hejsan",
+                 NULL,
+                 "fragment");
+  free (url_string);
+
+  /* Path, query and fragment */
+  url_string = strdup ("/?q=yes&q2=no#fragment");
+  rc = GNUNET_uri_parse (&url,
+                         url_string);
+  mu_assert ("path, query and fragment",
+             -1 != rc);
+  assert_struct (url,
+                 NULL,
+                 NULL,
+                 NULL,
+                 NULL,
+                 0,
+                 "",
+                 "q=yes&q2=no",
+                 "fragment");
+  free (url_string);
+
+  return NULL;
+}
+
+static char *
+test_parse_url_fail (void)
+{
+  int rc;
+  struct GNUNET_Uri url;
+  char *url_string;
+
+  /* Empty */
+  url_string = strdup ("");
+  rc = GNUNET_uri_parse (&url,
+                         url_string);
+  mu_assert ("empty string should return -1",
+             -1 == rc);
+  free (url_string);
+
+  /* Scheme only */
+  url_string = strdup ("rtsp://");
+  rc = GNUNET_uri_parse (&url,
+                         url_string);
+  mu_assert ("scheme only should return -1",
+             -1 == rc);
+  free (url_string);
+
+  /* Hostname only */
+  url_string = strdup ("hostname");
+  rc = GNUNET_uri_parse (&url,
+                         url_string);
+  mu_assert ("hostname only should return -1",
+             -1 == rc);
+  free (url_string);
+
+  /* Query only */
+  url_string = strdup ("?query=only");
+  rc = GNUNET_uri_parse (&url,
+                         url_string);
+  mu_assert ("query only should return -1",
+             -1 == rc);
+  free (url_string);
+
+  /* Missing scheme */
+  url_string = strdup ("://");
+  rc = GNUNET_uri_parse (&url,
+                         url_string);
+  mu_assert ("missing scheme should return -1",
+             -1 == rc);
+  free (url_string);
+
+  /* Missing hostname */
+  url_string = strdup ("rtsp://:8910/path");
+  rc = GNUNET_uri_parse (&url,
+                         url_string);
+  mu_assert ("missing hostname should return -1",
+             -1 == rc);
+  free (url_string);
+
+  /* Missing credentials */
+  url_string = strdup ("rtsp://@hostname:8910/path");
+  rc = GNUNET_uri_parse (&url,
+                         url_string);
+  mu_assert ("missing credentials should return -1",
+             -1 == rc);
+  free (url_string);
+
+  return NULL;
+}
+
+static char *
+test_split_path_ok (void)
+{
+  int rc;
+  char *path;
+  char *parts[10];
+
+  /* Simple path */
+  path = strdup ("/this/is/a/path");
+  rc = GNUNET_uri_split_path (path,
+                              parts,
+                              10);
+  mu_assert ("should be able to parse a regular path",
+             4 == rc);
+  mu_silent_assert ("first part should be 'this'",
+                    0 == strcmp ("this", parts[0]));
+  mu_silent_assert ("second part should be 'is'",
+                    0 == strcmp ("is", parts[1]));
+  mu_silent_assert ("third part should be 'a'",
+                    0 == strcmp ("a", parts[2]));
+  mu_silent_assert ("fourth part should be 'path'",
+                    0 == strcmp ("path", parts[3]));
+  free (path);
+
+  /* Relative path */
+  path = strdup ("this/is/a/path");
+  rc = GNUNET_uri_split_path (path,
+                              parts,
+                              10);
+  mu_assert ("should be able to parse a relative path",
+             4 == rc);
+  mu_silent_assert ("first part should be 'this'",
+                    0 == strcmp ("this", parts[0]));
+  mu_silent_assert ("second part should be 'is'",
+                    0 == strcmp ("is", parts[1]));
+  mu_silent_assert ("third part should be 'a'",
+                    0 == strcmp ("a", parts[2]));
+  mu_silent_assert ("fourth part should be 'path'",
+                    0 == strcmp ("path", parts[3]));
+  free (path);
+
+  /* Path with empty parts */
+  path = strdup ("//this//is/a/path/");
+  rc = GNUNET_uri_split_path (path,
+                              parts,
+                              10);
+  mu_assert ("should treat multiple slashes as one",
+             4 == rc);
+  mu_silent_assert ("first part should be 'this'",
+                    0 == strcmp("this", parts[0]));
+  mu_silent_assert ("second part should be 'is'",
+                    0 == strcmp("is", parts[1]));
+  mu_silent_assert ("third part should be 'a'",
+                    0 == strcmp("a", parts[2]));
+  mu_silent_assert ("fourth part should be 'path'",
+                    0 == strcmp("path", parts[3]));
+  free (path);
+
+  /* Just one level */
+  path = strdup("/one_level");
+  rc = GNUNET_uri_split_path(path, parts, 10);
+  mu_assert("should be able to parse a path with one level", 1 == rc);
+  mu_silent_assert("first part should be 'this'", 0 == strcmp("one_level", parts[0]));
+  free(path);
+
+  return NULL;
+}
+
+static char *
+test_parse_query_ok (void)
+{
+  int rc;
+  char *q;
+  struct GNUNET_UriParam params[10];
+
+  /* One param query */
+  q = strdup ("q=yes");
+  rc = GNUNET_uri_parse_query (q,
+                               '&',
+                               params,
+                               10);
+  mu_assert ("single parameter with value",
+             1 == rc);
+  mu_silent_assert ("first param key should be 'q'",
+                    0 == strcmp ("q", params[0].key));
+  mu_silent_assert ("first param val should be 'yes'",
+                    0 == strcmp ("yes", params[0].val));
+  free (q);
+
+  /* One param query without value */
+  q = strdup ("q");
+  rc = GNUNET_uri_parse_query (q,
+                               '&',
+                               params,
+                               10);
+  mu_assert ("single parameter without value",
+             1 == rc);
+  mu_silent_assert ("first param key should be 'q'",
+                    0 == strcmp ("q", params[0].key));
+  mu_silent_assert ("first param val should be NULL",
+                    NULL == params[0].val);
+  free (q);
+
+  /* Two param query */
+  q = strdup ("query=yes&a1=hello");
+  rc = GNUNET_uri_parse_query (q,
+                               '&',
+                               params,
+                               10);
+  mu_assert ("multiple params with value",
+             2 == rc);
+  mu_silent_assert ("first param key should be 'query'",
+                    0 == strcmp ("query", params[0].key));
+  mu_silent_assert ("first param val should be 'yes'",
+                    0 == strcmp ("yes", params[0].val));
+  mu_silent_assert ("second param key should be 'a1'",
+                    0 == strcmp ("a1", params[1].key));
+  mu_silent_assert ("second param val should be 'hello'",
+                    0 == strcmp ("hello", params[1].val));
+  free (q);
+
+  /* Two param query, one without value */
+  q = strdup ("query=yes&forceHttps");
+  rc = GNUNET_uri_parse_query (q,
+                               '&',
+                               params,
+                               10);
+  mu_assert ("multiple params one without value",
+             2 == rc);
+  mu_silent_assert ("first param key should be 'query'",
+                    0 == strcmp ("query", params[0].key));
+  mu_silent_assert ("first param val should be 'yes'",
+                    0 == strcmp ("yes", params[0].val));
+  mu_silent_assert ("second param key should be 'forceHttps'",
+                    0 == strcmp ("forceHttps", params[1].key));
+  mu_silent_assert ("second param val should be NULL",
+                    NULL == params[1].val);
+  free (q);
+
+  /* Three param query, all without value */
+  q = strdup ("query&forceHttps&log");
+  rc = GNUNET_uri_parse_query (q,
+                               '&',
+                               params,
+                               10);
+  mu_assert ("multiple params all without value",
+             3 == rc);
+  mu_silent_assert ("first param key should be 'query'",
+                    0 == strcmp ("query", params[0].key));
+  mu_silent_assert ("first param val should be NULL",
+                    NULL == params[0].val);
+  mu_silent_assert ("second param key should be 'forceHttps'",
+                    0 == strcmp ("forceHttps", params[1].key));
+  mu_silent_assert ("second param val should be NULL",
+                    NULL == params[1].val);
+  mu_silent_assert ("third param key should be 'log'",
+                    0 == strcmp ("log", params[2].key));
+  mu_silent_assert ("third param val should be NULL",
+                    NULL == params[2].val);
+  free (q);
+
+  /* Param with empty value */
+  q = strdup ("param=&query=no");
+  rc = GNUNET_uri_parse_query (q,
+                               '&',
+                               params,
+                               10);
+  mu_assert ("param with empty value",
+             2 == rc);
+  mu_silent_assert ("first param key should be 'param'",
+                    0 == strcmp ("param", params[0].key));
+  mu_silent_assert ("first param val should be ''",
+                    0 == strcmp ("", params[0].val));
+  mu_silent_assert ("second param key should be 'query'",
+                    0 == strcmp ("query", params[1].key));
+  mu_silent_assert ("second param val should be 'no'",
+                    0 == strcmp ("no", params[1].val));
+  free (q);
+
+  /* Double delimiter */
+  q = strdup ("param=jack&&query=no");
+  rc = GNUNET_uri_parse_query (q,
+                               '&',
+                               params,
+                               10);
+  mu_assert ("double delimiter",
+             3 == rc);
+  mu_silent_assert ("first param key should be 'param'",
+                    0 == strcmp ("param", params[0].key));
+  mu_silent_assert ("first param val should be 'jack'",
+                    0 == strcmp ("jack", params[0].val));
+  mu_silent_assert ("second param key should be ''",
+                    0 == strcmp ("", params[1].key));
+  mu_silent_assert ("second param val should be NULL",
+                    NULL == params[1].val);
+  mu_silent_assert ("third param key should be 'query'",
+                    0 == strcmp ("query", params[2].key));
+  mu_silent_assert ("third param val should be 'no'",
+                    0 == strcmp ("no", params[2].val));
+  free (q);
+
+  /* Delimiter in beginning */
+  q = strdup ("&param=jack&query=no");
+  rc = GNUNET_uri_parse_query (q,
+                               '&',
+                               params,
+                               10);
+  mu_assert ("delimiter in beginning",
+             3 == rc);
+  mu_silent_assert ("first param key should be ''",
+                    0 == strcmp ("", params[0].key));
+  mu_silent_assert ("first param val should be NULL",
+                    NULL == params[0].val);
+  mu_silent_assert ("second param key should be 'param'",
+                    0 == strcmp ("param", params[1].key));
+  mu_silent_assert ("second param val should be 'jack'",
+                    0 == strcmp ("jack", params[1].val));
+  mu_silent_assert ("third param key should be 'query'",
+                    0 == strcmp ("query", params[2].key));
+  mu_silent_assert ("third param val should be 'no'",
+                    0 == strcmp ("no", params[2].val));
+  free (q);
+
+  /* Delimiter at the end */
+  q = strdup ("param=jack&query=no&");
+  rc = GNUNET_uri_parse_query (q,
+                               '&',
+                               params,
+                               10);
+  mu_assert ("delimiter at the end",
+             3 == rc);
+  mu_silent_assert ("first param key should be 'param'",
+                    0 == strcmp ("param", params[0].key));
+  mu_silent_assert ("first param val should be 'jack'",
+                    0 == strcmp ("jack", params[0].val));
+  mu_silent_assert ("second param key should be 'query'",
+                    0 == strcmp ("query", params[1].key));
+  mu_silent_assert ("second param val should be 'no'",
+                    0 == strcmp ("no", params[1].val));
+  mu_silent_assert ("third param key should be ''",
+                    0 == strcmp ("", params[2].key));
+  mu_silent_assert ("third param val should be NULL",
+                    NULL == params[2].val);
+  free (q);
+
+  return NULL;
+}
+
+static char *
+all_tests (void)
+{
+  mu_group ("GNUNET_uri_parse () with an HTTP URL");
+  mu_run_test (test_parse_http_url_ok);
+
+  mu_group ("GNUNET_uri_parse () with an relative URL");
+  mu_run_test (test_parse_http_rel_url_ok);
+
+  mu_group ("GNUNET_uri_parse () with faulty values");
+  mu_run_test (test_parse_url_fail);
+
+  mu_group ("GNUNET_uri_split_path ()");
+  mu_run_test (test_split_path_ok);
+
+  mu_group ("GNUNET_uri_parse_query ()");
+  mu_run_test (test_parse_query_ok);
+
+  return NULL;
+}
+
+int
+main (void)
+{
+  char *result;
+
+  result = all_tests ();
+  if (result != NULL) {
+    exit (EXIT_FAILURE);
+  }
+
+  exit (EXIT_SUCCESS);
+}
diff --git a/src/util/uri.c b/src/util/uri.c
new file mode 100644
index 0000000000000000000000000000000000000000..87101d7e1e0933b3ac7b240a805ba5a3d5cc20a7
--- /dev/null
+++ b/src/util/uri.c
@@ -0,0 +1,344 @@
+/**
+ * Copyright (C) 2016,2017 Jack Engqvist Johansson
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include "gnunet_uri_lib.h"
+
+
+/**
+ * Parse a non null terminated string into an integer.
+ *
+ * str: the string containing the number.
+ * len: Number of characters to parse.
+ */
+static inline int
+natoi (const char *str,
+       size_t len)
+{
+  int i, r = 0;
+  for (i = 0; i < len; i++) {
+    r *= 10;
+    r += str[i] - '0';
+  }
+
+  return r;
+}
+
+
+/**
+ * Check if a URL is relative (no scheme and hostname).
+ *
+ * url: the string containing the URL to check.
+ *
+ * Returns 1 if relative, otherwise 0.
+ */
+static inline int
+is_relative (const char *url)
+{
+  return (*url == '/') ? 1 : 0;
+}
+
+
+/**
+ * Parse the scheme of a URL by inserting a null terminator after the scheme.
+ *
+ * str: the string containing the URL to parse. Will be modified.
+ *
+ * Returns a pointer to the hostname on success, otherwise NULL.
+ */
+static inline char *
+parse_scheme (char *str)
+{
+  char *s;
+
+  /* If not found or first in string, return error */
+  s = strchr (str, ':');
+  if (s == NULL || s == str) {
+    return NULL;
+  }
+
+  /* If not followed by two slashes, return error */
+  if (s[1] == '\0' || s[1] != '/' || s[2] == '\0' || s[2] != '/') {
+    return NULL;
+  }
+
+  *s = '\0'; // Replace ':' with NULL
+
+  return s + 3;
+}
+
+
+/**
+ * Find a character in a string, replace it with '\0' and return the next
+ * character in the string.
+ *
+ * str: the string to search in.
+ * find: the character to search for.
+ *
+ * Returns a pointer to the character after the one to search for. If not
+ * found, NULL is returned.
+ */
+static inline char *
+find_and_terminate (char *str,
+                    char find)
+{
+  str = strchr(str, find);
+  if (NULL == str) {
+    return NULL;
+  }
+
+  *str = '\0';
+  return str + 1;
+}
+
+
+/* Yes, the following functions could be implemented as preprocessor macros
+     instead of inline functions, but I think that this approach will be more
+     clean in this case. */
+static inline char *
+find_fragment (char *str)
+{
+  return find_and_terminate (str, '#');
+}
+
+
+static inline char *
+find_query (char *str)
+{
+  return find_and_terminate (str, '?');
+}
+
+
+static inline char *
+find_path (char *str)
+{
+  return find_and_terminate (str, '/');
+}
+
+
+/**
+ * Parse a URL to a struct.
+ *
+ * The URL string should be in one of the following formats:
+ *
+ * Absolute URL:
+ * scheme ":" [ "//" ] [ username ":" password "@" ] host [ ":" port ] [ "/" ] [ path ] [ "?" query ] [ "#" fragment ]
+ *
+ * Relative URL:
+ * path [ "?" query ] [ "#" fragment ]
+ *
+ * The following parts will be parsed to the corresponding struct member.
+ *
+ * *url:     a pointer to the struct where to store the parsed values.
+ * *url_str: a pointer to the url to be parsed (null terminated). The string
+ *           will be modified.
+ *
+ * Returns 0 on success, otherwise -1.
+ */
+int
+GNUNET_uri_parse (struct GNUNET_Uri *url,
+                  char *u)
+{
+  if (NULL == url || NULL == u) {
+    return -1;
+  }
+
+  memset(url, 0, sizeof (struct GNUNET_Uri));
+
+  /* (Fragment) */
+  url->fragment = find_fragment (u);
+
+  /* (Query) */
+  url->query = find_query (u);
+
+  /* Relative URL? Parse scheme and hostname */
+  if (!is_relative (u)) {
+    /* Scheme */
+    url->scheme = u;
+    u = parse_scheme (u);
+    if (u == NULL) {
+      return -1;
+    }
+
+    /* Host */
+    if ('\0' == *u) {
+      return -1;
+    }
+    url->host = u;
+
+    /* (Path) */
+    url->path = find_path (u);
+
+    /* (Credentials) */
+    u = strchr (url->host, '@');
+    if (NULL != u) {
+      /* Missing credentials? */
+      if (u == url->host) {
+        return -1;
+      }
+
+      url->username = url->host;
+      url->host = u + 1;
+      *u = '\0';
+
+      u = strchr (url->username, ':');
+      if (NULL == u) {
+        return -1;
+      }
+
+      url->password = u + 1;
+      *u = '\0';
+    }
+
+    /* Missing hostname? */
+    if ('\0' == *url->host) {
+      return -1;
+    }
+
+    /* (Port) */
+    u = strchr (url->host, ':');
+    if (NULL != u && (NULL == url->path || u < url->path)) {
+      *(u++) = '\0';
+      if ('\0' == *u) {
+        return -1;
+      }
+
+      if (url->path) {
+        url->port = natoi (u, url->path - u - 1);
+      } else {
+        url->port = atoi (u);
+      }
+    }
+
+    /* Missing hostname? */
+    if ('\0' == *url->host) {
+      return -1;
+    }
+  } else {
+    /* (Path) */
+    url->path = find_path (u);
+  }
+
+  return 0;
+}
+
+
+/**
+ * Split a path into several strings.
+ *
+ * No data is copied, the slashed are used as null terminators and then
+ * pointers to each path part will be stored in **parts. Double slashes will be
+ * treated as one.
+ *
+ * *path:     the path to split. The string will be modified.
+ * **parts:   a pointer to an array of (char *) where to store the result.
+ * max_parts: max number of parts to parse.
+ *
+ * Returns the number of parsed items. -1 on error.
+ */
+int
+GNUNET_uri_split_path (char *path,
+                       char **parts,
+                       int max_parts)
+{
+  int i = 0;
+
+  if (NULL == path || '\0' == *path) {
+    return -1;
+  }
+
+  do {
+    /* Forward to after slashes */
+    while (*path == '/') path++;
+
+    if ('\0' == *path) {
+      break;
+    }
+
+    parts[i++] = path;
+
+    path = strchr (path, '/');
+    if (NULL == path) {
+      break;
+    }
+
+    *(path++) = '\0';
+  } while (i < max_parts);
+
+  return i;
+}
+
+
+/**
+ * Parse a query string into a key/value struct.
+ *
+ * The query string should be a null terminated string of parameters separated by
+ * a delimiter. Each parameter are checked for the equal sign character. If it
+ * appears in the parameter, it will be used as a null terminator and the part
+ * that comes after it will be the value of the parameter.
+ *
+ * No data are copied, the equal sign and delimiters are used as null
+ * terminators and then pointers to each parameter key and value will be stored
+ * in the yuarel_param struct.
+ *
+ * *query:     the query string to parse. The string will be modified.
+ * delimiter:  the character that separates the key/value pairs from eachother.
+ * *params:    an array of (struct yuarel_param) where to store the result.
+ * max_values: max number of parameters to parse.
+ *
+ * Returns the number of parsed items. -1 on error.
+ */
+int
+GNUNET_uri_parse_query (char *query,
+                        char delimiter,
+                        struct GNUNET_UriParam *params,
+                        int max_params)
+{
+  int i = 0;
+
+  if (NULL == query || '\0' == *query) {
+    return -1;
+  }
+
+  params[i++].key = query;
+  while (i < max_params && NULL != (query = strchr (query, delimiter))) {
+    *query = '\0';
+    params[i].key = ++query;
+    params[i].val = NULL;
+
+    /* Go back and split previous param */
+    if (i > 0) {
+      if ((params[i - 1].val = strchr (params[i - 1].key, '=')) != NULL) {
+        *(params[i - 1].val)++ = '\0';
+      }
+    }
+    i++;
+  }
+
+  /* Go back and split last param */
+  if ((params[i - 1].val = strchr (params[i - 1].key, '=')) != NULL) {
+    *(params[i - 1].val)++ = '\0';
+  }
+
+  return i;
+}
diff --git a/src/util/util.supp b/src/util/util.supp
new file mode 100644
index 0000000000000000000000000000000000000000..f04775cacdc0c31e930f3b4b8214b33e197b6ab8
--- /dev/null
+++ b/src/util/util.supp
@@ -0,0 +1,11 @@
+{
+  cache-libexecdir-value
+  Memcheck:Leak
+  fun:malloc
+  fun:GNUNET_xmalloc_unchecked_
+  fun:GNUNET_xmalloc_
+  fun:GNUNET_asprintf
+  fun:GNUNET_OS_installation_get_path
+  fun:GNUNET_OS_get_libexec_binary_path
+  ...
+}
\ No newline at end of file
diff --git a/src/vpn/.gitignore b/src/vpn/.gitignore
new file mode 100644
index 0000000000000000000000000000000000000000..b76ea0f93a4132450d88b8167bb9f372c4b19a80
--- /dev/null
+++ b/src/vpn/.gitignore
@@ -0,0 +1,3 @@
+gnunet-vpn
+gnunet-helper-vpn
+gnunet-service-vpn
diff --git a/src/vpn/tests/expected b/src/vpn/tests/expected
new file mode 100644
index 0000000000000000000000000000000000000000..26ed82af9e57af53ebfe0b0762d57fc8e67358c9
Binary files /dev/null and b/src/vpn/tests/expected differ
diff --git a/src/vpn/tests/ping b/src/vpn/tests/ping
new file mode 100644
index 0000000000000000000000000000000000000000..ccc8555380b80c5dfea794f38cf8dd1e605caf17
Binary files /dev/null and b/src/vpn/tests/ping differ
diff --git a/src/vpn/tests/test-helper-icmp.sh b/src/vpn/tests/test-helper-icmp.sh
new file mode 100755
index 0000000000000000000000000000000000000000..2d0c8425ac743297d26226032aba0479a082d2ba
--- /dev/null
+++ b/src/vpn/tests/test-helper-icmp.sh
@@ -0,0 +1,17 @@
+#!/bin/sh
+
+/opt/gnunet/bin/gnunet-helper-vpn < ping > result 2>/dev/null &
+
+PID=$!
+
+sleep 1
+
+kill $PID
+
+if cmp result expected; then
+	echo OK
+	exit 0
+else
+	echo FAILED: ICMP-Reply
+	exit 1
+fi
diff --git a/src/vpn/tests/test-helper-ifaddr.sh b/src/vpn/tests/test-helper-ifaddr.sh
new file mode 100755
index 0000000000000000000000000000000000000000..b8fde999dc2c4672b0c369bd852467e53d272d89
--- /dev/null
+++ b/src/vpn/tests/test-helper-ifaddr.sh
@@ -0,0 +1,41 @@
+#!/bin/sh
+
+FIFO=$(mktemp)
+
+rm $FIFO
+
+mkfifo $FIFO
+
+/opt/gnunet/bin/gnunet-helper-vpn > $FIFO 2>&1 &
+
+PID=$!
+
+sleep 1
+
+IF=""
+while read line < $FIFO; do
+	IF=$(echo $line | grep interface | sed -e 's/.*interface \([^ ]*\).*/\1/')
+	if [ "$IF" != "" ]; then
+		break
+	fi
+done
+
+r=0
+if /sbin/ifconfig $IF | grep inet6 | grep -q '1234::1/16'; then
+	echo OK
+else
+	echo FAILED: Interface-Address not set for IPv6!
+	r=1
+fi
+
+if /sbin/ifconfig $IF | grep "inet " | grep -q '10.10.10.1'; then
+	echo OK
+else
+	echo FAILED: Interface-Address not set for IPv4!
+	r=1
+fi
+
+rm $FIFO
+kill $PID
+
+exit $r
diff --git a/src/zonemaster/.gitignore b/src/zonemaster/.gitignore
new file mode 100644
index 0000000000000000000000000000000000000000..cde57fa0a997297694974f6925060198186efac9
--- /dev/null
+++ b/src/zonemaster/.gitignore
@@ -0,0 +1,2 @@
+gnunet-service-zonemaster
+gnunet-service-zonemaster-monitor