summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authort3sserakt <t3ss@posteo.de>2020-08-28 17:57:44 +0200
committert3sserakt <t3ss@posteo.de>2020-08-28 17:57:53 +0200
commit2b552a5f5e85fab1c14af73735c0de61b46cc3dc (patch)
tree1ed739ddb116d77a7f2dfcc69c013f0eb9f731e7
parent03f6a0233f72c2c4c3925f0d6f6f7a81987c6530 (diff)
parentbbf9540c93da3c6b950920ee7eaae479c95403c5 (diff)
Merge branch 'master' of ssh://gnunet.org/gnunet
-rwxr-xr-x.buildbot/build.sh4
-rw-r--r--ChangeLog63
-rwxr-xr-xbootstrap12
-rw-r--r--configure.ac30
-rw-r--r--contrib/Makefile.inc6
-rw-r--r--doc/handbook/chapters/developer.texi516
-rw-r--r--doc/handbook/chapters/user.texi95
-rw-r--r--doc/handbook/images/structure.dot6
-rw-r--r--po/POTFILES.in17
-rw-r--r--src/Makefile.am2
-rw-r--r--src/ats/ats_api_performance.c2
-rw-r--r--src/ats/gnunet-service-ats_addresses.c2
-rw-r--r--src/cadet/gnunet-service-cadet_peer.c2
-rw-r--r--src/curl/curl.c27
-rw-r--r--src/gns/plugin_rest_gns.c44
-rw-r--r--src/gnsrecord/.gitignore1
-rw-r--r--src/identity/plugin_rest_identity.c38
-rw-r--r--src/include/Makefile.am1
-rw-r--r--src/include/gnunet_block_lib.h13
-rw-r--r--src/include/gnunet_common.h6
-rw-r--r--src/include/gnunet_crypto_lib.h12
-rw-r--r--src/include/gnunet_curl_lib.h22
-rw-r--r--src/include/gnunet_gnsrecord_lib.h7
-rw-r--r--src/include/gnunet_my_lib.h2
-rw-r--r--src/include/gnunet_mysql_lib.h6
-rw-r--r--src/include/gnunet_protocols.h215
-rw-r--r--src/include/gnunet_reclaim_lib.h412
-rw-r--r--src/include/gnunet_reclaim_plugin.h197
-rw-r--r--src/include/gnunet_reclaim_service.h79
-rw-r--r--src/include/gnunet_seti_service.h369
-rw-r--r--src/include/gnunet_setu_service.h390
-rw-r--r--src/include/gnunet_uri_lib.h122
-rw-r--r--src/mysql/mysql.c2
-rw-r--r--src/namestore/gnunet-service-namestore.c4
-rw-r--r--src/namestore/namestore_api_monitor.c2
-rw-r--r--src/namestore/plugin_rest_namestore.c40
-rw-r--r--src/nse/gnunet-service-nse.c9
-rw-r--r--src/nse/perf_kdf.c3
-rw-r--r--src/peerinfo-tool/plugin_rest_peerinfo.c38
-rw-r--r--src/reclaim/Makefile.am29
-rw-r--r--src/reclaim/gnunet-reclaim.c221
-rw-r--r--src/reclaim/gnunet-service-reclaim.c314
-rw-r--r--src/reclaim/gnunet-service-reclaim_tickets.c343
-rw-r--r--src/reclaim/gnunet-service-reclaim_tickets.h7
-rw-r--r--src/reclaim/json_reclaim.c68
-rw-r--r--src/reclaim/json_reclaim.h11
-rw-r--r--src/reclaim/oidc_helper.c127
-rw-r--r--src/reclaim/oidc_helper.h23
-rw-r--r--src/reclaim/plugin_gnsrecord_reclaim.c12
-rw-r--r--src/reclaim/plugin_reclaim_credential_jwt.c (renamed from src/reclaim/plugin_reclaim_attestation_jwt.c)206
-rw-r--r--src/reclaim/plugin_rest_openid_connect.c257
-rw-r--r--src/reclaim/plugin_rest_reclaim.c186
-rw-r--r--src/reclaim/reclaim.h35
-rw-r--r--src/reclaim/reclaim_api.c224
-rw-r--r--src/reclaim/reclaim_attestation.c570
-rw-r--r--src/reclaim/reclaim_attribute.c67
-rw-r--r--src/reclaim/reclaim_attribute.h47
-rw-r--r--src/reclaim/reclaim_credential.c1037
-rw-r--r--src/reclaim/reclaim_credential.h (renamed from src/reclaim/reclaim_attestation.h)61
-rw-r--r--src/reclaim/test_reclaim_attribute.c51
-rw-r--r--src/rest/gnunet-rest-server.c20
-rw-r--r--src/rest/plugin_rest_config.c37
-rw-r--r--src/rest/plugin_rest_copying.c28
-rw-r--r--src/revocation/.gitignore1
-rw-r--r--src/revocation/Makefile.am2
-rw-r--r--src/revocation/gnunet-service-revocation.c90
-rw-r--r--src/revocation/revocation_api.c6
-rw-r--r--src/scalarproduct/Makefile.am8
-rw-r--r--src/scalarproduct/gnunet-service-scalarproduct-ecc_alice.c75
-rw-r--r--src/scalarproduct/gnunet-service-scalarproduct-ecc_bob.c70
-rw-r--r--src/scalarproduct/gnunet-service-scalarproduct_alice.c77
-rw-r--r--src/scalarproduct/gnunet-service-scalarproduct_bob.c71
-rw-r--r--src/seti/.gitignore3
-rw-r--r--src/seti/Makefile.am90
-rw-r--r--src/seti/gnunet-service-seti.c2515
-rw-r--r--src/seti/gnunet-service-seti_protocol.h144
-rw-r--r--src/seti/gnunet-seti-profiler.c480
-rw-r--r--src/seti/plugin_block_seti_test.c123
-rw-r--r--src/seti/seti.conf.in12
-rw-r--r--src/seti/seti.h267
-rw-r--r--src/seti/seti_api.c896
-rw-r--r--src/seti/test_seti.conf32
-rw-r--r--src/seti/test_seti_api.c345
-rw-r--r--src/setu/.gitignore6
-rw-r--r--src/setu/Makefile.am102
-rw-r--r--src/setu/gnunet-service-setu.c3683
-rw-r--r--src/setu/gnunet-service-setu_protocol.h226
-rw-r--r--src/setu/gnunet-service-setu_strata_estimator.c303
-rw-r--r--src/setu/gnunet-service-setu_strata_estimator.h169
-rw-r--r--src/setu/gnunet-setu-ibf-profiler.c308
-rw-r--r--src/setu/gnunet-setu-profiler.c499
-rw-r--r--src/setu/ibf.c409
-rw-r--r--src/setu/ibf.h255
-rw-r--r--src/setu/ibf_sim.c142
-rw-r--r--src/setu/plugin_block_setu_test.c123
-rw-r--r--src/setu/setu.conf.in12
-rw-r--r--src/setu/setu.h315
-rw-r--r--src/setu/setu_api.c897
-rw-r--r--src/setu/test_setu_api.c360
-rw-r--r--src/transport/gnunet-service-tng.c2
-rw-r--r--src/util/.gitignore3
-rw-r--r--src/util/Makefile.am7
-rw-r--r--src/util/common_allocation.c8
-rw-r--r--src/util/crypto_pow.c3
-rw-r--r--src/util/gnunet-scrypt.c9
-rw-r--r--src/util/service.c2
-rw-r--r--src/util/test_os_start_process.c19
-rw-r--r--src/util/test_peer.c3
-rw-r--r--src/util/test_uri.c837
-rw-r--r--src/util/uri.c344
110 files changed, 19160 insertions, 1992 deletions
diff --git a/.buildbot/build.sh b/.buildbot/build.sh
index 394558ff0..f2cdb3f2a 100755
--- a/.buildbot/build.sh
+++ b/.buildbot/build.sh
@@ -1,5 +1,3 @@
#!/bin/bash
-./bootstrap
-./configure --prefix=/tmp/gnunet --enable-experimental
-make
+./bootstrap && ./configure --prefix=/tmp/gnunet --enable-experimental && make
diff --git a/ChangeLog b/ChangeLog
index 4ed6576e7..98b3b40b4 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,66 @@
+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/bootstrap b/bootstrap
index b4f5b4dc3..8fc4c4426 100755
--- a/bootstrap
+++ b/bootstrap
@@ -79,8 +79,8 @@ check_libtool()
existence libtoolize || \
existence glibtoolize || \
existence slibtool; then
- autoreconf -if
- . "bin/pogen.sh"
+ autoreconf -if || exit 1
+ . "bin/pogen.sh" || exit 1
else
echo "*** No libtoolize (libtool) or libtool found, please install it ***" >&2;
exit 1
@@ -97,15 +97,15 @@ submodules()
if ! git --version >/dev/null; then
echo "git not installed, skipping submodule update"
else
- git submodule update --init || true
- git submodule update --recursive || true
- git submodule sync || true
+ 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 || true
+ cp contrib/build-common/Makefile.inc contrib/Makefile.inc || exit 1
}
main()
diff --git a/configure.ac b/configure.ac
index 39e7ffa7e..bd92bd0e9 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.2], [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="#"
@@ -1404,12 +1406,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 +1424,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 +1939,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/Makefile.inc b/contrib/Makefile.inc
index 35c2d42a8..a563ef4a1 100644
--- a/contrib/Makefile.inc
+++ b/contrib/Makefile.inc
@@ -3,6 +3,12 @@
# itself.
BUILDCOMMON_SHLIB_FILES = \
+ build-common/sh/bin.sh/python.sh \
+ build-common/sh/lib.sh/existence.sh \
+ build-common/sh/lib.sh/existence_python.sh \
+ build-common/sh/lib.sh/msg.sh \
+ build-common/sh/lib.sh/progname.sh \
+ build-common/sh/lib.sh/version_gnunet.sh \
build-common/LICENSE
BUILDCOMMON_CONF_FILES = \
diff --git a/doc/handbook/chapters/developer.texi b/doc/handbook/chapters/developer.texi
index 6d8ddd3c2..369e5327c 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 523f286d0..adc287e04 100644
--- a/doc/handbook/chapters/user.texi
+++ b/doc/handbook/chapters/user.texi
@@ -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/images/structure.dot b/doc/handbook/images/structure.dot
index a53db90b8..f3cf193d8 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/po/POTFILES.in b/po/POTFILES.in
index 1f5cc81c3..2f37f5852 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -272,12 +272,12 @@ 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_credential_jwt.c
src/reclaim/plugin_reclaim_attribute_basic.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_credential.c
src/reclaim/reclaim_attribute.c
src/regex/gnunet-daemon-regexprofiler.c
src/regex/gnunet-regex-profiler.c
@@ -333,6 +333,19 @@ src/set/ibf.c
src/set/ibf_sim.c
src/set/plugin_block_set_test.c
src/set/set_api.c
+src/seti/gnunet-service-set_intersection.c
+src/seti/gnunet-service-seti.c
+src/seti/gnunet-seti-profiler.c
+src/seti/plugin_block_seti_test.c
+src/seti/setu_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
diff --git a/src/Makefile.am b/src/Makefile.am
index 446b1aa2a..234a63389 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/ats/ats_api_performance.c b/src/ats/ats_api_performance.c
index acc9356ed..7349fb989 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/gnunet-service-ats_addresses.c b/src/ats/gnunet-service-ats_addresses.c
index e8a95c65e..3cd831a39 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/cadet/gnunet-service-cadet_peer.c b/src/cadet/gnunet-service-cadet_peer.c
index a2068b31b..221364c5d 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);
diff --git a/src/curl/curl.c b/src/curl/curl.c
index eb9dd6a29..d89c97176 100644
--- a/src/curl/curl.c
+++ b/src/curl/curl.c
@@ -472,6 +472,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
* CURLOPT_PRIVATE facility of the CURL @a eh. Used to download
@@ -864,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++;
diff --git a/src/gns/plugin_rest_gns.c b/src/gns/plugin_rest_gns.c
index a3006ce23..6ec921f70 100644
--- a/src/gns/plugin_rest_gns.c
+++ b/src/gns/plugin_rest_gns.c
@@ -81,6 +81,16 @@ struct Plugin
struct RequestHandle
{
/**
+ * DLL
+ */
+ struct RequestHandle *next;
+
+ /**
+ * DLL
+ */
+ struct RequestHandle *prev;
+
+ /**
* Active GNS lookup
*/
struct GNUNET_GNS_LookupWithTldRequest *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
@@ -165,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);
}
@@ -198,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);
}
@@ -374,8 +396,12 @@ 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';
if (GNUNET_NO ==
@@ -386,8 +412,6 @@ rest_process_request (struct GNUNET_REST_RequestHandle *rest_handle,
}
- handle->timeout_task =
- GNUNET_SCHEDULER_add_delayed (handle->timeout, &do_timeout, handle);
return GNUNET_YES;
}
@@ -405,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);
@@ -437,12 +459,18 @@ 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);
- plugin->cfg = NULL;
if (NULL != gns)
GNUNET_GNS_disconnect (gns);
+ plugin = api->cls;
+
+ plugin->cfg = NULL;
GNUNET_free (allow_methods);
GNUNET_free (api);
diff --git a/src/gnsrecord/.gitignore b/src/gnsrecord/.gitignore
index 53d3bb22d..dca3bd309 100644
--- a/src/gnsrecord/.gitignore
+++ b/src/gnsrecord/.gitignore
@@ -3,3 +3,4 @@ test_gnsrecord_crypto
test_gnsrecord_serialization
zonefiles
perf_gnsrecord_crypto
+gnunet-gnsrecord-tvg
diff --git a/src/identity/plugin_rest_identity.c b/src/identity/plugin_rest_identity.c
index 6859396d6..d86d29e36 100644
--- a/src/identity/plugin_rest_identity.c
+++ b/src/identity/plugin_rest_identity.c
@@ -191,6 +191,16 @@ struct EgoEntry
struct RequestHandle
{
/**
+ * DLL
+ */
+ struct RequestHandle *next;
+
+ /**
+ * DLL
+ */
+ struct RequestHandle *prev;
+
+ /**
* The data from the REST request
*/
const char *data;
@@ -252,6 +262,16 @@ struct RequestHandle
};
/**
+ * DLL
+ */
+static struct RequestHandle *requests_head;
+
+/**
+ * DLL
+ */
+static struct RequestHandle *requests_tail;
+
+/**
* Cleanup lookup handle
* @param handle Handle to clean up
*/
@@ -273,7 +293,9 @@ cleanup_handle (void *cls)
GNUNET_free (handle->emsg);
if (NULL != handle->name)
GNUNET_free (handle->name);
-
+ GNUNET_CONTAINER_DLL_remove (requests_head,
+ requests_tail,
+ handle);
GNUNET_free (handle);
}
@@ -1274,13 +1296,13 @@ rest_process_request (struct GNUNET_REST_RequestHandle *rest_handle,
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, &ego_get_all },
- { MHD_HTTP_METHOD_GET, GNUNET_REST_API_NS_IDENTITY_PUBKEY,
+ { { 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 },
@@ -1310,6 +1332,11 @@ 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';
+ 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))
@@ -1318,8 +1345,6 @@ rest_process_request (struct GNUNET_REST_RequestHandle *rest_handle,
return GNUNET_NO;
}
- handle->timeout_task =
- GNUNET_SCHEDULER_add_delayed (handle->timeout, &do_error, handle);
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Connected\n");
return GNUNET_YES;
}
@@ -1353,6 +1378,7 @@ 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"));
@@ -1375,6 +1401,8 @@ libgnunet_plugin_rest_identity_done (void *cls)
struct EgoEntry *ego_tmp;
plugin->cfg = NULL;
+ while (NULL != requests_head)
+ cleanup_handle (requests_head);
if (NULL != identity_handle)
GNUNET_IDENTITY_disconnect (identity_handle);
diff --git a/src/include/Makefile.am b/src/include/Makefile.am
index d2c254ae6..e542038d3 100644
--- a/src/include/Makefile.am
+++ b/src/include/Makefile.am
@@ -119,5 +119,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_block_lib.h b/src/include/gnunet_block_lib.h
index 18ca6f63f..73b51252e 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_common.h b/src/include/gnunet_common.h
index b2f99cd55..fcaae1026 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_crypto_lib.h b/src/include/gnunet_crypto_lib.h
index f8eef5406..8c3f4f058 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).
@@ -668,6 +669,15 @@ GNUNET_CRYPTO_hash (const void *block,
/**
+ * 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).
*
* @param salt salt for the hash. Must be crypto_pwhash_argon2id_SALTBYTES long.
@@ -676,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);
diff --git a/src/include/gnunet_curl_lib.h b/src/include/gnunet_curl_lib.h
index 9de58d608..f291d6b14 100644
--- a/src/include/gnunet_curl_lib.h
+++ b/src/include/gnunet_curl_lib.h
@@ -275,9 +275,8 @@ GNUNET_CURL_set_userpass (struct GNUNET_CURL_Context *ctx,
/**
- * Force use of the provided TLS client certificate
- * for client authentication for all operations performed
- * with @a ctx.
+ * 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
@@ -298,9 +297,9 @@ GNUNET_CURL_set_tlscert (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.
+ * 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.
@@ -345,6 +344,17 @@ GNUNET_CURL_job_add_raw (struct GNUNET_CURL_Context *ctx,
/**
+ * 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_gnsrecord_lib.h b/src/include/gnunet_gnsrecord_lib.h
index c976c89c5..960203fb1 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_my_lib.h b/src/include/gnunet_my_lib.h
index 74e7bf492..b8513ca84 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 964483024..843d3ccb3 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_protocols.h b/src/include/gnunet_protocols.h
index 5af58664f..d9821ffe8 100644
--- a/src/include/gnunet_protocols.h
+++ b/src/include/gnunet_protocols.h
@@ -1659,9 +1659,212 @@ extern "C" {
/*******************************************************************************
+ * 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
/**************************************************
diff --git a/src/include/gnunet_reclaim_lib.h b/src/include/gnunet_reclaim_lib.h
index 4f2d6dba5..bbf1c3ad3 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,6 +83,8 @@ 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 == \
@@ -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 7ee9e730f..2ba8fc8a0 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,47 +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) (
+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
@@ -240,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.
@@ -250,37 +354,78 @@ struct GNUNET_RECLAIM_AttestationPluginFunctions
/**
* Conversion to string.
*/
- GNUNET_RECLAIM_AttestationValueToStringFunction value_to_string;
+ GNUNET_RECLAIM_CredentialValueToStringFunction value_to_string;
+
+ /**
+ * Conversion to binary.
+ */
+ GNUNET_RECLAIM_CredentialStringToValueFunction string_to_value;
+
+ /**
+ * Typename to number.
+ */
+ GNUNET_RECLAIM_CredentialTypenameToNumberFunction typename_to_number;
+
+ /**
+ * Number to typename.
+ */
+ GNUNET_RECLAIM_CredentialNumberToTypenameFunction number_to_typename;
+
+ /**
+ * Attesation attributes.
+ */
+ GNUNET_RECLAIM_CredentialGetAttributesFunction get_attributes;
+
+ /**
+ * Attesation issuer.
+ */
+ GNUNET_RECLAIM_CredentialGetIssuerFunction get_issuer;
+
+ /**
+ * Expiration.
+ */
+ GNUNET_RECLAIM_CredentialGetExpirationFunction get_expiration;
+
+ /**
+ * Conversion to string.
+ */
+ GNUNET_RECLAIM_PresentationValueToStringFunction value_to_string_p;
/**
* Conversion to binary.
*/
- GNUNET_RECLAIM_AttestationStringToValueFunction string_to_value;
+ GNUNET_RECLAIM_PresentationStringToValueFunction string_to_value_p;
/**
* Typename to number.
*/
- GNUNET_RECLAIM_AttestationTypenameToNumberFunction typename_to_number;
+ GNUNET_RECLAIM_PresentationTypenameToNumberFunction typename_to_number_p;
/**
* Number to typename.
*/
- GNUNET_RECLAIM_AttestationNumberToTypenameFunction number_to_typename;
+ GNUNET_RECLAIM_PresentationNumberToTypenameFunction number_to_typename_p;
/**
* Attesation attributes.
*/
- GNUNET_RECLAIM_AttestationGetAttributesFunction get_attributes;
+ GNUNET_RECLAIM_PresentationGetAttributesFunction get_attributes_p;
/**
* Attesation issuer.
*/
- GNUNET_RECLAIM_AttestationGetIssuerFunction get_issuer;
+ GNUNET_RECLAIM_PresentationGetIssuerFunction get_issuer_p;
/**
* Expiration.
*/
- GNUNET_RECLAIM_AttestationGetExpirationFunction get_expiration;
+ GNUNET_RECLAIM_PresentationGetExpirationFunction get_expiration_p;
+
+ /**
+ * Get presentation
+ */
+ GNUNET_RECLAIM_CredentialToPresentation create_presentation;
+
};
diff --git a/src/include/gnunet_reclaim_service.h b/src/include/gnunet_reclaim_service.h
index 139c44ae7..368058f56 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,34 +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);
/**
@@ -347,8 +360,8 @@ 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);
/**
@@ -370,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_seti_service.h b/src/include/gnunet_seti_service.h
new file mode 100644
index 000000000..c0b6f41a5
--- /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 000000000..634c5c40b
--- /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_uri_lib.h b/src/include/gnunet_uri_lib.h
new file mode 100644
index 000000000..d428bdd9a
--- /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/mysql/mysql.c b/src/mysql/mysql.c
index 713227068..e20debc82 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/namestore/gnunet-service-namestore.c b/src/namestore/gnunet-service-namestore.c
index bb8138e23..b24bb2952 100644
--- a/src/namestore/gnunet-service-namestore.c
+++ b/src/namestore/gnunet-service-namestore.c
@@ -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_monitor.c b/src/namestore/namestore_api_monitor.c
index ab6140328..9dc955544 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 c993518ea..9354b9896 100644
--- a/src/namestore/plugin_rest_namestore.c
+++ b/src/namestore/plugin_rest_namestore.c
@@ -161,6 +161,16 @@ enum UpdateStrategy
struct RequestHandle
{
/**
+ * DLL
+ */
+ struct RequestHandle *next;
+
+ /**
+ * DLL
+ */
+ struct RequestHandle *prev;
+
+ /**
* Records to store
*/
char *record_name;
@@ -258,6 +268,17 @@ struct RequestHandle
};
/**
+ * DLL
+ */
+static struct RequestHandle *requests_head;
+
+/**
+ * DLL
+ */
+static struct RequestHandle *requests_tail;
+
+
+/**
* Cleanup lookup handle
* @param handle Handle to clean up
*/
@@ -298,7 +319,9 @@ cleanup_handle (void *cls)
{
json_decref (handle->resp_object);
}
-
+ GNUNET_CONTAINER_DLL_remove (requests_head,
+ requests_tail,
+ handle);
GNUNET_free (handle);
}
@@ -329,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);
}
@@ -1024,10 +1047,14 @@ 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");
if (GNUNET_NO ==
GNUNET_REST_handle_request (handle->rest_handle, handlers, &err, handle))
@@ -1036,9 +1063,6 @@ rest_process_request (struct GNUNET_REST_RequestHandle *rest_handle,
return GNUNET_NO;
}
- handle->timeout_task =
- GNUNET_SCHEDULER_add_delayed (handle->timeout, &do_error, handle);
-
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Connected\n");
return GNUNET_YES;
}
@@ -1065,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,
@@ -1091,10 +1116,13 @@ 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)
diff --git a/src/nse/gnunet-service-nse.c b/src/nse/gnunet-service-nse.c
index ebf39585e..dfd71e57a 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/perf_kdf.c b/src/nse/perf_kdf.c
index 89b70903a..10207675f 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/plugin_rest_peerinfo.c b/src/peerinfo-tool/plugin_rest_peerinfo.c
index 1d7461b1a..99cec7e58 100644
--- a/src/peerinfo-tool/plugin_rest_peerinfo.c
+++ b/src/peerinfo-tool/plugin_rest_peerinfo.c
@@ -180,6 +180,16 @@ static struct PrintContext *pc_tail;
struct RequestHandle
{
/**
+ * DLL
+ */
+ struct RequestHandle *next;
+
+ /**
+ * DLL
+ */
+ struct RequestHandle *prev;
+
+ /**
* JSON temporary array
*/
json_t *temp_array;
@@ -251,6 +261,15 @@ struct RequestHandle
int response_code;
};
+/**
+ * DLL
+ */
+static struct RequestHandle *requests_head;
+
+/**
+ * DLL
+ */
+static struct RequestHandle *requests_tail;
/**
* Cleanup lookup handle
@@ -300,7 +319,9 @@ cleanup_handle (void *cls)
GNUNET_PEERINFO_disconnect (peerinfo_handle);
peerinfo_handle = NULL;
}
-
+ GNUNET_CONTAINER_DLL_remove (requests_head,
+ requests_tail,
+ handle);
GNUNET_free (handle);
}
@@ -733,6 +754,13 @@ 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';
+ 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,
@@ -742,10 +770,6 @@ rest_process_request (struct GNUNET_REST_RequestHandle *rest_handle,
cleanup_handle (handle);
return GNUNET_NO;
}
- handle->timeout_task =
- GNUNET_SCHEDULER_add_delayed (handle->timeout,
- &do_error,
- handle);
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Connected\n");
return GNUNET_YES;
}
@@ -800,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/reclaim/Makefile.am b/src/reclaim/Makefile.am
index a9829c47e..a58127abf 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 6bef5b6fe..ab281a645 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 0cd8c10a5..d2cdc62a2 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)
{
@@ -851,28 +873,28 @@ consume_result_cb (void *cls,
struct GNUNET_MQ_Envelope *env;
char *data_tmp;
size_t attrs_len = 0;
- size_t attests_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 7e6b07514..4dd8100f9 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
@@ -173,6 +173,11 @@ struct TicketIssueHandle
struct GNUNET_RECLAIM_AttributeList *attrs;
/**
+ * Presentations to add
+ */
+ struct GNUNET_RECLAIM_PresentationList *presentations;
+
+ /**
* Issuer Key
*/
struct GNUNET_CRYPTO_EcdsaPrivateKey identity;
@@ -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 1c7214d42..0dd790fc7 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 c470ea567..8a3479b8a 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 c57971dcb..613ddf873 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,11 +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 9b5938c43..b307a358c 100644
--- a/src/reclaim/oidc_helper.c
+++ b/src/reclaim/oidc_helper.c
@@ -62,9 +62,9 @@ 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
@@ -156,25 +156,25 @@ fix_base64 (char *str)
static json_t*
generate_userinfo_json(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)
{
struct GNUNET_RECLAIM_AttributeListEntry *le;
- struct GNUNET_RECLAIM_AttestationListEntry *ale;
+ struct GNUNET_RECLAIM_PresentationListEntry *ple;
char *subject;
char *source_name;
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;
json_t *addr_claim = NULL;
- int num_attestations = 0;
+ 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++;
}
subject =
@@ -191,23 +191,25 @@ generate_userinfo_json(const struct GNUNET_CRYPTO_EcdsaPublicKey *sub_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));
- attest_val_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++;
@@ -216,7 +218,7 @@ generate_userinfo_json(const struct GNUNET_CRYPTO_EcdsaPublicKey *sub_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 =
@@ -247,18 +249,24 @@ generate_userinfo_json(const struct GNUNET_CRYPTO_EcdsaPublicKey *sub_key,
}
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);
@@ -269,9 +277,6 @@ generate_userinfo_json(const struct GNUNET_CRYPTO_EcdsaPublicKey *sub_key,
}
if (NULL != addr_claim)
json_object_set_new (body, "address", addr_claim);
-
- if (NULL != attest_val_str)
- GNUNET_free (attest_val_str);
if (0 != i)
{
json_object_set_new (body, "_claim_names", aggr_names);
@@ -286,18 +291,18 @@ generate_userinfo_json(const struct GNUNET_CRYPTO_EcdsaPublicKey *sub_key,
*
* @param sub_key the subject (user)
* @param attrs user attribute list
- * @param attests user attribute attestation list (may be empty)
+ * @param presentations credential presentation list (may be empty)
* @return Userinfo JSON
*/
char *
OIDC_generate_userinfo (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)
{
char *body_str;
json_t* body = generate_userinfo_json (sub_key,
attrs,
- attests);
+ presentations);
body_str = json_dumps (body, JSON_INDENT (0) | JSON_COMPACT);
json_decref (body);
return body_str;
@@ -310,6 +315,7 @@ OIDC_generate_userinfo (const struct GNUNET_CRYPTO_EcdsaPublicKey *sub_key,
* @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.
@@ -317,8 +323,8 @@ OIDC_generate_userinfo (const struct GNUNET_CRYPTO_EcdsaPublicKey *sub_key,
char *
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)
@@ -339,7 +345,7 @@ OIDC_generate_id_token (const struct GNUNET_CRYPTO_EcdsaPublicKey *aud_key,
body = generate_userinfo_json (sub_key,
attrs,
- attests);
+ presentations);
// iat REQUIRED time now
time_now = GNUNET_TIME_absolute_get ();
// exp REQUIRED time expired from config
@@ -426,6 +432,7 @@ OIDC_generate_id_token (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 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)
@@ -433,8 +440,8 @@ OIDC_generate_id_token (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_str,
const char *code_challenge)
{
@@ -447,7 +454,7 @@ 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_len = 0;
struct GNUNET_CRYPTO_EccSignaturePurpose *purpose;
@@ -481,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
@@ -510,8 +517,8 @@ OIDC_build_authz_code (const struct GNUNET_CRYPTO_EcdsaPrivateKey *issuer,
}
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 **/
@@ -564,7 +571,7 @@ OIDC_build_authz_code (const struct GNUNET_CRYPTO_EcdsaPrivateKey *issuer,
* if used in request.
* @param ticket where to store the ticket
* @param attrs the attributes in the code
- * @param attests the attestations in the code (if any)
+ * @param presentations credential presentation list
* @param nonce_str where to store the nonce (if contained)
* @return GNUNET_OK if successful, else GNUNET_SYSERR
*/
@@ -574,14 +581,14 @@ OIDC_parse_authz_code (const struct GNUNET_CRYPTO_EcdsaPublicKey *audience,
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;
@@ -589,7 +596,7 @@ OIDC_parse_authz_code (const struct GNUNET_CRYPTO_EcdsaPublicKey *audience,
struct GNUNET_CRYPTO_EcdsaSignature *signature;
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_len = 0;
@@ -621,6 +628,7 @@ OIDC_parse_authz_code (const struct GNUNET_CRYPTO_EcdsaPublicKey *audience,
// 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)
@@ -639,7 +647,6 @@ OIDC_parse_authz_code (const struct GNUNET_CRYPTO_EcdsaPublicKey *audience,
// 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 (0 !=
strncmp (expected_code_challenge, code_challenge, code_challenge_len))
@@ -692,10 +699,11 @@ OIDC_parse_authz_code (const struct GNUNET_CRYPTO_EcdsaPublicKey *audience,
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);
+ 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);
return GNUNET_OK;
@@ -769,7 +777,7 @@ OIDC_access_token_parse (const char *token,
/**
* Checks if a claim is implicitly requested through standard
- * scope(s)
+ * scope(s) or explicitly through non-standard scope.
*
* @param scopes the scopes which have been requested
* @param attr the attribute name to check
@@ -832,6 +840,11 @@ OIDC_check_scopes_for_claim_request (const char*scopes,
}
}
+ } else if (0 == strcmp (attr, scope_variable))
+ {
+ /** attribute matches requested scope **/
+ GNUNET_free (scope_variables);
+ return GNUNET_YES;
}
scope_variable = strtok (NULL, delimiter);
}
diff --git a/src/reclaim/oidc_helper.h b/src/reclaim/oidc_helper.h
index e713dab62..10a6f3d1f 100644
--- a/src/reclaim/oidc_helper.h
+++ b/src/reclaim/oidc_helper.h
@@ -44,6 +44,7 @@
* @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.
@@ -51,8 +52,8 @@
char*
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_generate_id_token (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_generate_id_token (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,6 +88,7 @@ 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
*/
@@ -95,7 +98,7 @@ OIDC_parse_authz_code (const struct GNUNET_CRYPTO_EcdsaPublicKey *ecdsa_pub,
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);
/**
@@ -136,8 +139,8 @@ OIDC_access_token_parse (const char* token,
* @return GNUNET_YES if attribute is implcitly requested
*/
enum GNUNET_GenericReturnValue
-OIDC_check_scopes_for_claim_request (const char*scopes,
- const char*attr);
+OIDC_check_scopes_for_claim_request (const char *scopes,
+ const char *attr);
/**
@@ -145,12 +148,12 @@ OIDC_check_scopes_for_claim_request (const char*scopes,
*
* @param sub_key the subject (user)
* @param attrs user attribute list
- * @param attests user attribute attestation list (may be empty)
+ * @param presentations credential presentation list
* @return Userinfo JSON
*/
char *
OIDC_generate_userinfo (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);
#endif
diff --git a/src/reclaim/plugin_gnsrecord_reclaim.c b/src/reclaim/plugin_gnsrecord_reclaim.c
index b91e123a3..60c49fd6a 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_attestation_jwt.c b/src/reclaim/plugin_reclaim_credential_jwt.c
index c87d3e61a..148865223 100644
--- a/src/reclaim/plugin_reclaim_attestation_jwt.c
+++ b/src/reclaim/plugin_reclaim_credential_jwt.c
@@ -19,10 +19,9 @@
*/
/**
- * @file reclaim-attribute/plugin_reclaim_attestation_gnuid.c
- * @brief reclaim-attribute-plugin-gnuid attribute plugin to provide the API for
- * fundamental
- * attribute types.
+ * @file reclaim/plugin_reclaim_credential_jwt.c
+ * @brief reclaim-credential-plugin-jwt attribute plugin to provide the API for
+ * JWT credentials.
*
* @author Martin Schanzenbach
*/
@@ -33,10 +32,10 @@
#include <jansson.h>
/**
- * Convert the 'value' of an attestation to a string.
+ * Convert the 'value' of an credential to a string.
*
* @param cls closure, unused
- * @param type type of the attestation
+ * @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
@@ -49,7 +48,7 @@ jwt_value_to_string (void *cls,
{
switch (type)
{
- case GNUNET_RECLAIM_ATTESTATION_TYPE_JWT:
+ case GNUNET_RECLAIM_CREDENTIAL_TYPE_JWT:
return GNUNET_strndup (data, data_size);
default:
@@ -59,11 +58,11 @@ jwt_value_to_string (void *cls,
/**
- * Convert human-readable version of a 'value' of an attestation to the binary
+ * Convert human-readable version of a 'value' of an credential to the binary
* representation.
*
* @param cls closure, unused
- * @param type type of the attestation
+ * @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
@@ -80,7 +79,7 @@ jwt_string_to_value (void *cls,
return GNUNET_SYSERR;
switch (type)
{
- case GNUNET_RECLAIM_ATTESTATION_TYPE_JWT:
+ case GNUNET_RECLAIM_CREDENTIAL_TYPE_JWT:
*data = GNUNET_strdup (s);
*data_size = strlen (s);
return GNUNET_OK;
@@ -92,15 +91,15 @@ jwt_string_to_value (void *cls,
/**
- * Mapping of attestation type numbers to human-readable
- * attestation type names.
+ * Mapping of credential type numbers to human-readable
+ * credential type names.
*/
static struct
{
const char *name;
uint32_t number;
-} jwt_attest_name_map[] = { { "JWT", GNUNET_RECLAIM_ATTESTATION_TYPE_JWT },
- { NULL, UINT32_MAX } };
+} jwt_cred_name_map[] = { { "JWT", GNUNET_RECLAIM_CREDENTIAL_TYPE_JWT },
+ { NULL, UINT32_MAX } };
/**
* Convert a type name to the corresponding number.
@@ -115,10 +114,10 @@ jwt_typename_to_number (void *cls, const char *jwt_typename)
unsigned int i;
i = 0;
- while ((NULL != jwt_attest_name_map[i].name) &&
- (0 != strcasecmp (jwt_typename, jwt_attest_name_map[i].name)))
+ while ((NULL != jwt_cred_name_map[i].name) &&
+ (0 != strcasecmp (jwt_typename, jwt_cred_name_map[i].name)))
i++;
- return jwt_attest_name_map[i].number;
+ return jwt_cred_name_map[i].number;
}
@@ -135,11 +134,11 @@ jwt_number_to_typename (void *cls, uint32_t type)
unsigned int i;
i = 0;
- while ((NULL != jwt_attest_name_map[i].name) && (type !=
- jwt_attest_name_map[i].
- number))
+ while ((NULL != jwt_cred_name_map[i].name) && (type !=
+ jwt_cred_name_map[i].
+ number))
i++;
- return jwt_attest_name_map[i].name;
+ return jwt_cred_name_map[i].name;
}
@@ -147,12 +146,12 @@ jwt_number_to_typename (void *cls, uint32_t type)
* Parse a JWT and return the respective claim value as Attribute
*
* @param cls the plugin
- * @param attest the jwt attestation
+ * @param cred the jwt credential
* @return a GNUNET_RECLAIM_Attribute, containing the new value
*/
struct GNUNET_RECLAIM_AttributeList *
jwt_parse_attributes (void *cls,
- const struct GNUNET_RECLAIM_Attestation *attest)
+ const char *data)
{
char *jwt_string;
struct GNUNET_RECLAIM_AttributeList *attrs;
@@ -163,17 +162,14 @@ jwt_parse_attributes (void *cls,
json_t *json_val;
json_error_t *json_err = NULL;
- /* GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "%s\n", attest->data); (not OK: 'data' is not defined as 0-terminated text, but binary) */
- if (GNUNET_RECLAIM_ATTESTATION_TYPE_JWT != attest->type)
- return NULL;
attrs = GNUNET_new (struct GNUNET_RECLAIM_AttributeList);
- jwt_string = GNUNET_strdup (attest->data);
+ 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_ERROR, "%s\n", 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;
@@ -204,15 +200,45 @@ jwt_parse_attributes (void *cls,
/**
+ * 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 attest the jwt attestation
+ * @param cred the jwt credential
* @return a string, containing the isser
*/
char *
jwt_get_issuer (void *cls,
- const struct GNUNET_RECLAIM_Attestation *attest)
+ const char *data)
{
const char *jwt_body;
char *jwt_string;
@@ -224,9 +250,7 @@ jwt_get_issuer (void *cls,
json_t *json_val;
json_error_t *json_err = NULL;
- if (GNUNET_RECLAIM_ATTESTATION_TYPE_JWT != attest->type)
- return NULL;
- jwt_string = GNUNET_strdup (attest->data);
+ 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),
@@ -242,15 +266,49 @@ jwt_get_issuer (void *cls,
/**
+ * 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 attest the jwt attestation
+ * @param cred the jwt credential
* @return a string, containing the isser
*/
int
jwt_get_expiration (void *cls,
- const struct GNUNET_RECLAIM_Attestation *attest,
+ const char *data,
struct GNUNET_TIME_Absolute *exp)
{
const char *jwt_body;
@@ -262,9 +320,7 @@ jwt_get_expiration (void *cls,
json_t *json_val;
json_error_t *json_err = NULL;
- if (GNUNET_RECLAIM_ATTESTATION_TYPE_JWT != attest->type)
- return GNUNET_NO;
- jwt_string = GNUNET_strdup (attest->data);
+ 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),
@@ -280,24 +336,80 @@ jwt_get_expiration (void *cls,
/**
+ * 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_attestation_jwt_init (void *cls)
+libgnunet_plugin_reclaim_credential_jwt_init (void *cls)
{
- struct GNUNET_RECLAIM_AttestationPluginFunctions *api;
+ struct GNUNET_RECLAIM_CredentialPluginFunctions *api;
- api = GNUNET_new (struct GNUNET_RECLAIM_AttestationPluginFunctions);
+ 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;
- api->get_issuer = &jwt_get_issuer;
- api->get_expiration = &jwt_get_expiration;
+ 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;
}
@@ -309,13 +421,13 @@ libgnunet_plugin_reclaim_attestation_jwt_init (void *cls)
* @return NULL
*/
void *
-libgnunet_plugin_reclaim_attestation_jwt_done (void *cls)
+libgnunet_plugin_reclaim_credential_jwt_done (void *cls)
{
- struct GNUNET_RECLAIM_AttestationPluginFunctions *api = cls;
+ struct GNUNET_RECLAIM_CredentialPluginFunctions *api = cls;
GNUNET_free (api);
return NULL;
}
-/* end of plugin_reclaim_attestation_type_gnuid.c */
+/* 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 06e1b0061..5b0bb2b6f 100644
--- a/src/reclaim/plugin_rest_openid_connect.c
+++ b/src/reclaim/plugin_rest_openid_connect.c
@@ -393,6 +393,15 @@ struct EgoEntry
struct RequestHandle
{
+ /**
+ * DLL
+ */
+ struct RequestHandle *next;
+
+ /**
+ * DLL
+ */
+ struct RequestHandle *prev;
/**
* Selected ego
@@ -430,10 +439,14 @@ 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
@@ -452,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;
/**
@@ -528,6 +541,16 @@ struct RequestHandle
int public_client;
};
+/**
+ * DLL
+ */
+static struct RequestHandle *requests_head;
+
+/**
+ * DLL
+ */
+static struct RequestHandle *requests_tail;
+
/**
* Cleanup lookup handle
@@ -542,8 +565,8 @@ cleanup_handle (struct RequestHandle *handle)
GNUNET_SCHEDULER_cancel (handle->timeout_task);
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)
@@ -571,20 +594,17 @@ cleanup_handle (struct RequestHandle *handle)
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);
-
+ 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.
*
@@ -613,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);
}
@@ -640,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);
}
@@ -667,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);
}
@@ -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) &&
@@ -974,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);
@@ -996,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);
@@ -1021,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);
@@ -1037,14 +1059,19 @@ 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);
+ 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,
@@ -1059,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);
}
@@ -1110,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 (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);
}
@@ -1136,7 +1163,7 @@ attr_in_claims_request (struct RequestHandle *handle,
const char *key;
json_t *value;
- /** Check if attribute is requested through standard scope **/
+ /** 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;
@@ -1193,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);
@@ -1208,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);
@@ -1332,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;
}
@@ -1709,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));
@@ -1739,7 +1766,7 @@ 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);
}
@@ -1963,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;
@@ -2038,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);
@@ -2051,7 +2076,7 @@ token_endpoint (struct GNUNET_REST_RequestHandle *con_handle,
// decode code
if (GNUNET_OK != OIDC_parse_authz_code (&cid, code, code_verifier, &ticket,
- &cl, &al, &nonce))
+ &cl, &pl, &nonce))
{
handle->emsg = GNUNET_strdup (OIDC_ERROR_KEY_INVALID_REQUEST);
handle->edesc = GNUNET_strdup ("invalid code");
@@ -2091,7 +2116,7 @@ token_endpoint (struct GNUNET_REST_RequestHandle *con_handle,
id_token = OIDC_generate_id_token (&ticket.audience,
&ticket.identity,
cl,
- al,
+ pl,
&expiration_time,
(NULL != nonce) ? nonce : NULL,
jwt_secret);
@@ -2107,11 +2132,11 @@ token_endpoint (struct GNUNET_REST_RequestHandle *con_handle,
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);
}
@@ -2122,22 +2147,21 @@ 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_AttestationListEntry *atle;
+ struct GNUNET_RECLAIM_PresentationListEntry *atle;
struct MHD_Response *resp;
char *result_str;
handle->idp_op = NULL;
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Attr: %s\n", attr->name);
if (NULL == identity)
{
result_str = OIDC_generate_userinfo (&handle->ticket.identity,
handle->attr_userinfo_list,
- handle->attests_list);
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Userinfo: %s\n", result_str);
+ 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);
@@ -2146,33 +2170,35 @@ consume_ticket (void *cls,
}
ale = GNUNET_new (struct GNUNET_RECLAIM_AttributeListEntry);
ale->attribute = GNUNET_RECLAIM_attribute_new (attr->name,
- &attr->attestation,
+ &attr->credential,
attr->type,
attr->data,
attr->data_size);
ale->attribute->id = attr->id;
ale->attribute->flag = attr->flag;
- ale->attribute->attestation = attr->attestation;
+ ale->attribute->credential = attr->credential;
GNUNET_CONTAINER_DLL_insert (handle->attr_userinfo_list->list_head,
handle->attr_userinfo_list->list_tail,
ale);
- for (atle = handle->attests_list->list_head; NULL != atle; atle = atle->next)
+ if (NULL == pres)
+ return;
+ for (atle = handle->presentations->list_head;
+ NULL != atle; atle = atle->next)
{
- if (GNUNET_NO == GNUNET_RECLAIM_id_is_equal (&atle->attestation->id,
- &attest->id))
+ if (GNUNET_NO == GNUNET_RECLAIM_id_is_equal (&atle->presentation->credential_id,
+ &pres->credential_id))
continue;
break; /** already in list **/
}
if (NULL == atle)
{
- /** Attestation matches for attribute, add **/
- atle = GNUNET_new (struct GNUNET_RECLAIM_AttestationListEntry);
- atle->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 **/
+ 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);
}
}
@@ -2271,8 +2297,8 @@ userinfo_endpoint (struct GNUNET_REST_RequestHandle *con_handle,
privkey = GNUNET_IDENTITY_ego_get_private_key (aud_ego->ego);
handle->attr_userinfo_list =
GNUNET_new (struct GNUNET_RECLAIM_AttributeList);
- handle->attests_list =
- GNUNET_new (struct GNUNET_RECLAIM_AttestationList);
+ handle->presentations =
+ GNUNET_new (struct GNUNET_RECLAIM_PresentationList);
handle->idp_op = GNUNET_RECLAIM_ticket_consume (idp,
privkey,
@@ -2442,6 +2468,12 @@ oidc_config_endpoint (struct GNUNET_REST_RequestHandle *con_handle,
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);
@@ -2533,14 +2565,17 @@ rest_identity_process_request (struct GNUNET_REST_RequestHandle *rest_handle,
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';
if (GNUNET_NO ==
GNUNET_REST_handle_request (handle->rest_handle, handlers, &err, handle))
return GNUNET_NO;
- handle->timeout_task =
- GNUNET_SCHEDULER_add_delayed (handle->timeout, &do_timeout, handle);
return GNUNET_YES;
}
@@ -2585,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.
*
@@ -2599,19 +2642,15 @@ libgnunet_plugin_rest_openid_connect_done (void *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);
-
- 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);
diff --git a/src/reclaim/plugin_rest_reclaim.c b/src/reclaim/plugin_rest_reclaim.c
index c2d14825e..ff11d2a56 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
@@ -154,6 +154,15 @@ struct EgoEntry
struct RequestHandle
{
+ /**
+ * DLL
+ */
+ struct RequestHandle *next;
+
+ /**
+ * DLL
+ */
+ struct RequestHandle *prev;
/**
* Selected ego
@@ -193,7 +202,7 @@ struct RequestHandle
/**
* Attribute iterator
*/
- struct GNUNET_RECLAIM_AttestationIterator *attest_it;
+ struct GNUNET_RECLAIM_CredentialIterator *cred_it;
/**
* Ticket iterator
@@ -247,6 +256,17 @@ struct RequestHandle
};
/**
+ * DLL
+ */
+static struct RequestHandle *requests_head;
+
+/**
+ * DLL
+ */
+static struct RequestHandle *requests_tail;
+
+
+/**
* Cleanup lookup handle
* @param handle Handle to clean up
*/
@@ -262,8 +282,8 @@ cleanup_handle (void *cls)
GNUNET_SCHEDULER_cancel (handle->timeout_task);
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->url)
@@ -272,6 +292,9 @@ cleanup_handle (void *cls)
GNUNET_free (handle->emsg);
if (NULL != handle->attr_list)
GNUNET_RECLAIM_attribute_list_destroy (handle->attr_list);
+ GNUNET_CONTAINER_DLL_remove (requests_head,
+ requests_tail,
+ handle);
GNUNET_free (handle);
}
@@ -296,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, handle);
+ cleanup_handle (handle);
GNUNET_free (json_error);
}
@@ -319,7 +342,7 @@ do_timeout (void *cls)
static void
collect_error_cb (void *cls)
{
- do_error (cls);
+ GNUNET_SCHEDULER_add_now (&do_error, cls);
}
@@ -329,6 +352,7 @@ 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);
@@ -389,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);
}
@@ -436,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)
{
@@ -444,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");
@@ -464,7 +488,7 @@ 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 = ego_head; NULL != ego_entry;
ego_entry = ego_entry->next)
@@ -494,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;
@@ -505,7 +529,7 @@ 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);
exp = GNUNET_TIME_UNIT_HOURS;
- handle->idp_op = GNUNET_RECLAIM_attestation_store (idp,
+ handle->idp_op = GNUNET_RECLAIM_credential_store (idp,
identity_priv,
attribute,
&exp,
@@ -516,52 +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 (
+ 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)
@@ -582,27 +606,27 @@ attest_collect (void *cls,
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)
{
@@ -612,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");
@@ -622,7 +646,7 @@ 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 = ego_head; NULL != ego_entry;
ego_entry = ego_entry->next)
@@ -639,11 +663,11 @@ list_attestation_cont (struct GNUNET_REST_RequestHandle *con_handle,
return;
}
priv_key = GNUNET_IDENTITY_ego_get_private_key (ego_entry->ego);
- handle->attest_it = GNUNET_RECLAIM_get_attestations_start (idp,
+ handle->cred_it = GNUNET_RECLAIM_get_credentials_start (idp,
priv_key,
&collect_error_cb,
handle,
- &attest_collect,
+ &cred_collect,
handle,
&
collect_finished_cb,
@@ -652,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");
@@ -681,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))
@@ -706,10 +730,10 @@ delete_attestation_cont (struct GNUNET_REST_RequestHandle *con_handle,
return;
}
priv_key = GNUNET_IDENTITY_ego_get_private_key (ego_entry->ego);
- 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 (idp,
+ handle->idp_op = GNUNET_RECLAIM_credential_delete (idp,
priv_key,
&attr,
&delete_finished_cb,
@@ -787,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",
@@ -853,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;
@@ -875,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),
@@ -903,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;
@@ -941,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"));
@@ -950,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);
@@ -1156,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;
@@ -1403,11 +1427,11 @@ rest_identity_process_request (struct GNUNET_REST_RequestHandle *rest_handle,
{ 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 },
+ GNUNET_REST_API_NS_RECLAIM_CREDENTIAL, &list_credential_cont },
{ MHD_HTTP_METHOD_POST,
- GNUNET_REST_API_NS_RECLAIM_ATTESTATION, &add_attestation_cont },
+ GNUNET_REST_API_NS_RECLAIM_CREDENTIAL, &add_credential_cont },
{ MHD_HTTP_METHOD_DELETE,
- GNUNET_REST_API_NS_RECLAIM_ATTESTATION, &delete_attestation_cont },
+ 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,
@@ -1422,12 +1446,16 @@ rest_identity_process_request (struct GNUNET_REST_RequestHandle *rest_handle,
handle->timeout = GNUNET_TIME_UNIT_FOREVER_REL;
handle->proc_cls = proc_cls;
handle->proc = proc;
- 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';
+ handle->timeout_task =
+ GNUNET_SCHEDULER_add_delayed (handle->timeout, &do_timeout, handle);
+ GNUNET_CONTAINER_DLL_insert (requests_head,
+ requests_tail,
+ handle);
if (GNUNET_NO ==
GNUNET_REST_handle_request (handle->rest_handle, handlers, &err, handle))
{
@@ -1435,8 +1463,6 @@ rest_identity_process_request (struct GNUNET_REST_RequestHandle *rest_handle,
return GNUNET_NO;
}
- handle->timeout_task =
- GNUNET_SCHEDULER_add_delayed (handle->timeout, &do_timeout, handle);
return GNUNET_YES;
}
@@ -1470,6 +1496,7 @@ libgnunet_plugin_rest_reclaim_init (void *cls)
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"));
@@ -1488,10 +1515,13 @@ 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)
diff --git a/src/reclaim/reclaim.h b/src/reclaim/reclaim.h
index 7b5d7ab19..bc7f34365 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
@@ -463,9 +463,16 @@ 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 d73241a6f..1e0251519 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
@@ -92,6 +92,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.
*/
struct GNUNET_MQ_Envelope *env;
@@ -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);
@@ -1573,7 +1611,7 @@ GNUNET_RECLAIM_ticket_consume (
if (NULL != h->mq)
GNUNET_MQ_send_copy (h->mq, op->env);
else
- reconnect(h);
+ reconnect (h);
return op;
}
diff --git a/src/reclaim/reclaim_attestation.c b/src/reclaim/reclaim_attestation.c
deleted file mode 100644
index 1f2b1890b..000000000
--- a/src/reclaim/reclaim_attestation.c
+++ /dev/null
@@ -1,570 +0,0 @@
-/*
- 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-attribute/reclaim_attestation.c
- * @brief helper library to manage identity attribute attestations
- * @author Martin Schanzenbach
- */
-#include "platform.h"
-#include "gnunet_util_lib.h"
-#include "gnunet_reclaim_plugin.h"
-#include "reclaim_attestation.h"
-
-
-/**
- * Handle for a plugin
- */
-struct Plugin
-{
- /**
- * Name of the plugin
- */
- char *library_name;
-
- /**
- * Plugin API
- */
- struct GNUNET_RECLAIM_AttestationPluginFunctions *api;
-};
-
-
-/**
- * Plugins
- */
-static struct Plugin **attest_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_AttestationPluginFunctions *api = lib_ret;
- struct Plugin *plugin;
-
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Loading attestation plugin `%s'\n",
- library_name);
- plugin = GNUNET_new (struct Plugin);
- plugin->api = api;
- plugin->library_name = GNUNET_strdup (library_name);
- GNUNET_array_append (attest_plugins, num_plugins, plugin);
-}
-
-
-/**
- * Load plugins
- */
-static void
-init ()
-{
- if (GNUNET_YES == initialized)
- return;
- initialized = GNUNET_YES;
- GNUNET_PLUGIN_load_all ("libgnunet_plugin_reclaim_attestation_",
- NULL,
- &add_plugin,
- NULL);
-}
-
-
-/**
- * Convert an attestation 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)
-{
- unsigned int i;
- struct Plugin *plugin;
- uint32_t ret;
- init ();
- for (i = 0; i < num_plugins; i++)
- {
- plugin = attest_plugins[i];
- if (UINT32_MAX !=
- (ret = plugin->api->typename_to_number (plugin->api->cls,
- typename)))
- return ret;
- }
- return UINT32_MAX;
-}
-
-
-/**
- * Convert an attestation type number to the corresponding attestation 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)
-{
- unsigned int i;
- struct Plugin *plugin;
- const char *ret;
-
- init ();
- for (i = 0; i < num_plugins; i++)
- {
- plugin = attest_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 attestation 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_attestation_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 = attest_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 attestation to a string
- *
- * @param type the type of attestation
- * @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,
- const void *data,
- size_t data_size)
-{
- unsigned int i;
- struct Plugin *plugin;
- char *ret;
-
- init ();
- for (i = 0; i < num_plugins; i++)
- {
- plugin = attest_plugins[i];
- if (NULL != (ret = plugin->api->value_to_string (plugin->api->cls,
- type,
- data,
- data_size)))
- return ret;
- }
- return NULL;
-}
-
-
-/**
- * Create a new attestation.
- *
- * @param attr_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 *attr_name,
- uint32_t type,
- const void *data,
- size_t data_size)
-{
- struct GNUNET_RECLAIM_Attestation *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_Attestation)
- + 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_attestation_list_serialize_get_size (
- const struct GNUNET_RECLAIM_AttestationList *attestations)
-{
- struct GNUNET_RECLAIM_AttestationListEntry *le;
- size_t len = 0;
-
- for (le = attestations->list_head; NULL != le; le = le->next)
- {
- GNUNET_assert (NULL != le->attestation);
- len += GNUNET_RECLAIM_attestation_serialize_get_size (le->attestation);
- len += sizeof(struct GNUNET_RECLAIM_AttestationListEntry);
- }
- 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_attestation_list_serialize (
- const struct GNUNET_RECLAIM_AttestationList *attestations,
- char *result)
-{
- struct GNUNET_RECLAIM_AttestationListEntry *le;
- size_t len;
- size_t total_len;
- char *write_ptr;
- write_ptr = result;
- total_len = 0;
- for (le = attestations->list_head; NULL != le; le = le->next)
- {
- GNUNET_assert (NULL != le->attestation);
- len = GNUNET_RECLAIM_attestation_serialize (le->attestation, write_ptr);
- total_len += len;
- write_ptr += len;
- }
- return total_len;
-}
-
-
-/**
- * Deserialize an attestation 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_AttestationList *
-GNUNET_RECLAIM_attestation_list_deserialize (const char *data, size_t data_size)
-{
- struct GNUNET_RECLAIM_AttestationList *al;
- struct GNUNET_RECLAIM_AttestationListEntry *ale;
- size_t att_len;
- const char *read_ptr;
-
- al = GNUNET_new (struct GNUNET_RECLAIM_AttestationList);
-
- if ((data_size < sizeof(struct
- Attestation)
- + sizeof(struct GNUNET_RECLAIM_AttestationListEntry)))
- return al;
-
- read_ptr = data;
- while (((data + data_size) - read_ptr) >= sizeof(struct Attestation))
- {
- ale = GNUNET_new (struct GNUNET_RECLAIM_AttestationListEntry);
- ale->attestation =
- GNUNET_RECLAIM_attestation_deserialize (read_ptr,
- data_size - (read_ptr - data));
- if (NULL == ale->attestation)
- {
- GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
- "Failed to deserialize malformed attestation.\n");
- GNUNET_free (ale);
- return al;
- }
- GNUNET_CONTAINER_DLL_insert (al->list_head, al->list_tail, ale);
- att_len = GNUNET_RECLAIM_attestation_serialize_get_size (ale->attestation);
- read_ptr += att_len;
- }
- return al;
-}
-
-
-/**
- * Make a (deep) copy of the attestation list
- * @param attrs claim list to copy
- * @return copied claim list
- */
-struct GNUNET_RECLAIM_AttestationList *
-GNUNET_RECLAIM_attestation_list_dup (
- const struct GNUNET_RECLAIM_AttestationList *al)
-{
- struct GNUNET_RECLAIM_AttestationListEntry *ale;
- struct GNUNET_RECLAIM_AttestationListEntry *result_ale;
- struct GNUNET_RECLAIM_AttestationList *result;
-
- result = GNUNET_new (struct GNUNET_RECLAIM_AttestationList);
- for (ale = al->list_head; NULL != ale; ale = ale->next)
- {
- result_ale = GNUNET_new (struct GNUNET_RECLAIM_AttestationListEntry);
- GNUNET_assert (NULL != ale->attestation);
- result_ale->attestation =
- GNUNET_RECLAIM_attestation_new (ale->attestation->name,
- ale->attestation->type,
- ale->attestation->data,
- ale->attestation->data_size);
- result_ale->attestation->id = ale->attestation->id;
- GNUNET_CONTAINER_DLL_insert (result->list_head,
- result->list_tail,
- result_ale);
- }
- return result;
-}
-
-
-/**
- * Destroy attestation list
- *
- * @param attrs list to destroy
- */
-void
-GNUNET_RECLAIM_attestation_list_destroy (
- struct GNUNET_RECLAIM_AttestationList *al)
-{
- struct GNUNET_RECLAIM_AttestationListEntry *ale;
- struct GNUNET_RECLAIM_AttestationListEntry *tmp_ale;
-
- for (ale = al->list_head; NULL != ale;)
- {
- if (NULL != ale->attestation)
- GNUNET_free (ale->attestation);
- tmp_ale = ale;
- ale = ale->next;
- GNUNET_free (tmp_ale);
- }
- GNUNET_free (al);
-}
-
-
-/**
- * Get required size for serialization buffer
- *
- * @param attr the attestation to serialize
- * @return the required buffer size
- */
-size_t
-GNUNET_RECLAIM_attestation_serialize_get_size (
- const struct GNUNET_RECLAIM_Attestation *attestation)
-{
- return sizeof(struct Attestation) + strlen (attestation->name)
- + attestation->data_size;
-}
-
-
-/**
- * Serialize an attestation
- *
- * @param attr the attestation to serialize
- * @param result the serialized attestation
- * @return length of serialized data
- */
-size_t
-GNUNET_RECLAIM_attestation_serialize (
- const struct GNUNET_RECLAIM_Attestation *attestation,
- char *result)
-{
- size_t data_len_ser;
- size_t name_len;
- struct Attestation *atts;
- char *write_ptr;
-
- atts = (struct Attestation *) result;
- atts->attestation_type = htons (attestation->type);
- atts->attestation_flag = htonl (attestation->flag);
- atts->attestation_id = attestation->id;
- name_len = strlen (attestation->name);
- atts->name_len = htons (name_len);
- write_ptr = (char *) &atts[1];
- GNUNET_memcpy (write_ptr, attestation->name, name_len);
- write_ptr += name_len;
- // TODO plugin-ize
- // data_len_ser = plugin->serialize_attribute_value (attr,
- // &attr_ser[1]);
- data_len_ser = attestation->data_size;
- GNUNET_memcpy (write_ptr, attestation->data, attestation->data_size);
- atts->data_size = htons (data_len_ser);
-
- return sizeof(struct Attestation) + strlen (attestation->name)
- + attestation->data_size;
-}
-
-
-/**
- * Deserialize an attestation
- *
- * @param data the serialized attestation
- * @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_Attestation *attestation;
- struct Attestation *atts;
- size_t data_len;
- size_t name_len;
- char *write_ptr;
-
- if (data_size < sizeof(struct Attestation))
- return NULL;
-
- atts = (struct Attestation *) data;
- data_len = ntohs (atts->data_size);
- name_len = ntohs (atts->name_len);
- if (data_size < sizeof(struct Attestation) + data_len + name_len)
- {
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- "Buffer too small to deserialize\n");
- return NULL;
- }
- attestation = GNUNET_malloc (sizeof(struct GNUNET_RECLAIM_Attestation)
- + data_len + name_len + 1);
- attestation->type = ntohs (atts->attestation_type);
- attestation->flag = ntohl (atts->attestation_flag);
- attestation->id = atts->attestation_id;
- attestation->data_size = data_len;
-
- write_ptr = (char *) &attestation[1];
- GNUNET_memcpy (write_ptr, &atts[1], name_len);
- write_ptr[name_len] = '\0';
- attestation->name = write_ptr;
-
- write_ptr += name_len + 1;
- GNUNET_memcpy (write_ptr, (char *) &atts[1] + name_len,
- attestation->data_size);
- attestation->data = write_ptr;
- return attestation;
-}
-
-
-struct GNUNET_RECLAIM_AttributeList*
-GNUNET_RECLAIM_attestation_get_attributes (const struct
- GNUNET_RECLAIM_Attestation *attest)
-{
- unsigned int i;
- struct Plugin *plugin;
- struct GNUNET_RECLAIM_AttributeList *ret;
- init ();
- for (i = 0; i < num_plugins; i++)
- {
- plugin = attest_plugins[i];
- if (NULL !=
- (ret = plugin->api->get_attributes (plugin->api->cls,
- attest)))
- return ret;
- }
- return NULL;
-}
-
-
-char*
-GNUNET_RECLAIM_attestation_get_issuer (const struct
- GNUNET_RECLAIM_Attestation *attest)
-{
- unsigned int i;
- struct Plugin *plugin;
- char *ret;
- init ();
- for (i = 0; i < num_plugins; i++)
- {
- plugin = attest_plugins[i];
- if (NULL !=
- (ret = plugin->api->get_issuer (plugin->api->cls,
- attest)))
- return ret;
- }
- return NULL;
-}
-
-
-int
-GNUNET_RECLAIM_attestation_get_expiration (const struct
- GNUNET_RECLAIM_Attestation *attest,
- struct GNUNET_TIME_Absolute*exp)
-{
- unsigned int i;
- struct Plugin *plugin;
- init ();
- for (i = 0; i < num_plugins; i++)
- {
- plugin = attest_plugins[i];
- if (GNUNET_OK != plugin->api->get_expiration (plugin->api->cls,
- attest,
- exp))
- continue;
- return GNUNET_OK;
- }
- return GNUNET_SYSERR;
-}
diff --git a/src/reclaim/reclaim_attribute.c b/src/reclaim/reclaim_attribute.c
index 05bdc1ac6..2217987ac 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
@@ -231,7 +231,7 @@ 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,
+ GNUNET_RECLAIM_Identifier *credential,
uint32_t type,
const void *data,
size_t data_size)
@@ -244,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;
@@ -272,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)
@@ -281,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,
@@ -306,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;
}
@@ -355,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;
@@ -403,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);
@@ -478,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];
@@ -503,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);
@@ -522,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 e54b210b9..285d75d83 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 000000000..5c8974400
--- /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_attestation.h b/src/reclaim/reclaim_credential.h
index 5747d8896..7704ed968 100644
--- a/src/reclaim/reclaim_attestation.h
+++ b/src/reclaim/reclaim_credential.h
@@ -19,34 +19,34 @@
*/
/**
* @author Martin Schanzenbach
- * @file reclaim-attribute/reclaim_attestation.h
- * @brief GNUnet reclaim identity attribute attestations
+ * @file reclaim/reclaim_credential.h
+ * @brief GNUnet reclaim identity attribute credentials
*
*/
-#ifndef RECLAIM_ATTESTATION_H
-#define RECLAIM_ATTESTATION_H
+#ifndef RECLAIM_CREDENTIAL_H
+#define RECLAIM_CREDENTIAL_H
#include "gnunet_reclaim_service.h"
/**
- * Serialized attestation claim
+ * Serialized credential claim
*/
-struct Attestation
+struct Credential
{
/**
- * Attestation type
+ * Credential type
*/
- uint32_t attestation_type;
+ uint32_t credential_type;
/**
- * Attestation flag
+ * Credential flag
*/
- uint32_t attestation_flag;
+ uint32_t credential_flag;
/**
- * Attestation ID
+ * Credential ID
*/
- struct GNUNET_RECLAIM_Identifier attestation_id;
+ struct GNUNET_RECLAIM_Identifier credential_id;
/**
* Name length
@@ -58,7 +58,42 @@ struct Attestation
*/
uint32_t data_size;
- // followed by data_size Attestation value data
+ // 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_attribute.c b/src/reclaim/test_reclaim_attribute.c
new file mode 100644
index 000000000..f71d86b56
--- /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/rest/gnunet-rest-server.c b/src/rest/gnunet-rest-server.c
index 436b5b205..e6e03b16d 100644
--- a/src/rest/gnunet-rest-server.c
+++ b/src/rest/gnunet-rest-server.c
@@ -208,6 +208,11 @@ struct AcceptedRequest
* Connection
*/
struct MhdConnectionHandle *con_handle;
+
+ /**
+ * State
+ */
+ int socket_with_mhd;
};
/**
@@ -310,7 +315,13 @@ cleanup_ar (struct AcceptedRequest *ar)
{
cleanup_handle (ar->con_handle);
}
- GNUNET_NETWORK_socket_free_memory_only_ (ar->sock);
+ 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);
@@ -529,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
@@ -767,7 +778,7 @@ mhd_completed_cb (void *cls,
cleanup_handle (ar->con_handle);
ar->con_handle = NULL;
}
- schedule_httpd ();
+ ar->socket_with_mhd = GNUNET_YES;
*con_cls = NULL;
}
@@ -882,6 +893,7 @@ do_accept (void *cls)
else
GNUNET_assert (0);
ar = GNUNET_new (struct AcceptedRequest);
+ ar->socket_with_mhd = GNUNET_YES;
ar->sock = GNUNET_NETWORK_socket_accept (lsock, NULL, NULL);
if (NULL == ar->sock)
{
@@ -925,7 +937,7 @@ do_shutdown (void *cls)
GNUNET_CONTAINER_DLL_remove (plugins_head,
plugins_tail,
ple);
- GNUNET_PLUGIN_unload (ple->libname, NULL);
+ GNUNET_PLUGIN_unload (ple->libname, ple->plugin);
GNUNET_free (ple->libname);
GNUNET_free (ple);
}
diff --git a/src/rest/plugin_rest_config.c b/src/rest/plugin_rest_config.c
index d9ae57acd..af833efff 100644
--- a/src/rest/plugin_rest_config.c
+++ b/src/rest/plugin_rest_config.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
*/
struct GNUNET_REST_RequestHandle *rest_handle;
@@ -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);
}
@@ -367,7 +391,9 @@ 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))
{
@@ -392,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;
}
@@ -415,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 1649da3bb..6d074d3d1 100644
--- a/src/rest/plugin_rest_copying.c
+++ b/src/rest/plugin_rest_copying.c
@@ -46,6 +46,16 @@ const struct GNUNET_CONFIGURATION_Handle *cfg;
struct RequestHandle
{
/**
+ * DLL
+ */
+ struct RequestHandle *next;
+
+ /**
+ * DLL
+ */
+ struct RequestHandle *prev;
+
+ /**
* Handle to rest request
*/
struct GNUNET_REST_RequestHandle *rest_handle;
@@ -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,6 +96,9 @@ 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);
}
@@ -153,7 +175,9 @@ rest_copying_process_request (struct GNUNET_REST_RequestHandle *conndata_handle,
handle->proc_cls = proc_cls;
handle->proc = proc;
handle->rest_handle = conndata_handle;
-
+ GNUNET_CONTAINER_DLL_insert (requests_head,
+ requests_tail,
+ handle);
return GNUNET_REST_handle_request (conndata_handle,
handlers,
&err,
@@ -201,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
index 9acd3ac33..1432f7922 100644
--- a/src/revocation/.gitignore
+++ b/src/revocation/.gitignore
@@ -2,3 +2,4 @@ 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 a90f8cd79..9d98502a6 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-service-revocation.c b/src/revocation/gnunet-service-revocation.c
index 81a30748c..ddebb38ad 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 e0b195aa9..75cfd8761 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
@@ -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);
@@ -644,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/scalarproduct/Makefile.am b/src/scalarproduct/Makefile.am
index 311cfd1af..f3448725a 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 20ab292cf..447451aef 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 2da79f845..4c835d52a 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 44534c850..1ca7f61da 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 c000749af..b0299779d 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/seti/.gitignore b/src/seti/.gitignore
new file mode 100644
index 000000000..5f234a4c2
--- /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 000000000..b4980b670
--- /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-set_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 000000000..af478233b
--- /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 000000000..51968376e
--- /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 000000000..b8230bcfc
--- /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 000000000..55cf31bea
--- /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 000000000..e4f7b60b5
--- /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 000000000..aa7014034
--- /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 000000000..5b88b0469
--- /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 000000000..c87433419
--- /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 000000000..9074fab41
--- /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 000000000..35295449b
--- /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 000000000..b37ceba51
--- /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.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 000000000..326589186
--- /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
+
+/**